Skip to content

Commit dbef608

Browse files
author
Gabriel Schulhof
committed
n-api: cache Symbol.hasInstance
This improves the performance of napi_instanceof() by retrieving Symbol.hasInstance from the global object once and then storing a persistent reference to it in the env. Re #209 Re #214
1 parent 0a5bf4a commit dbef608

File tree

1 file changed

+41
-20
lines changed

1 file changed

+41
-20
lines changed

src/node_api.cc

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,16 @@ void napi_clear_last_error(napi_env env);
2323

2424
class napi_env__ {
2525
public:
26-
explicit napi_env__(v8::Isolate* _isolate): isolate(_isolate), last_error() {}
26+
explicit napi_env__(v8::Isolate* _isolate): isolate(_isolate),
27+
has_instance_available(true), last_error() {}
2728
~napi_env__() {
2829
last_exception.Reset();
30+
has_instance.Reset();
2931
}
3032
v8::Isolate* isolate;
3133
v8::Persistent<v8::Value> last_exception;
34+
v8::Persistent<v8::Value> has_instance;
35+
bool has_instance_available;
3236
napi_extended_error_info last_error;
3337
};
3438

@@ -2149,28 +2153,43 @@ napi_status napi_instanceof(napi_env env,
21492153
return napi_set_last_error(env, napi_function_expected);
21502154
}
21512155

2152-
napi_value value, js_result;
2153-
napi_status status;
2154-
napi_valuetype value_type;
2156+
if (env->has_instance_available) {
2157+
napi_value value, js_result, has_instance = nullptr;
2158+
napi_status status;
2159+
napi_valuetype value_type;
21552160

2156-
// Get "Symbol" from the global object
2157-
status = napi_get_global(env, &value);
2158-
if (status != napi_ok) return status;
2159-
status = napi_get_named_property(env, value, "Symbol", &value);
2160-
if (status != napi_ok) return status;
2161-
status = napi_typeof(env, value, &value_type);
2162-
if (status != napi_ok) return status;
2161+
// Get "Symbol" from the global object
2162+
if (env->has_instance.IsEmpty()) {
2163+
status = napi_get_global(env, &value);
2164+
if (status != napi_ok) return status;
2165+
status = napi_get_named_property(env, value, "Symbol", &value);
2166+
if (status != napi_ok) return status;
2167+
status = napi_typeof(env, value, &value_type);
2168+
if (status != napi_ok) return status;
21632169

2164-
// Get "hasInstance" from Symbol
2165-
if (value_type == napi_function) {
2166-
status = napi_get_named_property(env, value, "hasInstance", &value);
2167-
if (status != napi_ok) return status;
2168-
status = napi_typeof(env, value, &value_type);
2169-
if (status != napi_ok) return status;
2170+
// Get "hasInstance" from Symbol
2171+
if (value_type == napi_function) {
2172+
status = napi_get_named_property(env, value, "hasInstance", &value);
2173+
if (status != napi_ok) return status;
2174+
status = napi_typeof(env, value, &value_type);
2175+
if (status != napi_ok) return status;
2176+
2177+
// Store Symbol.hasInstance in a global persistent reference
2178+
if (value_type == napi_symbol) {
2179+
env->has_instance.Reset(env->isolate,
2180+
v8impl::V8LocalValueFromJsValue(value));
2181+
if (status != napi_ok) return status;
2182+
has_instance = value;
2183+
}
2184+
}
2185+
} else {
2186+
has_instance = v8impl::JsValueFromV8LocalValue(
2187+
v8::Local<v8::Value>::New(env->isolate, env->has_instance));
2188+
if (status != napi_ok) return status;
2189+
}
21702190

2171-
// Retrieve the function at the Symbol(hasInstance) key of the constructor
2172-
if (value_type == napi_symbol) {
2173-
status = napi_get_property(env, constructor, value, &value);
2191+
if (has_instance) {
2192+
status = napi_get_property(env, constructor, has_instance, &value);
21742193
if (status != napi_ok) return status;
21752194
status = napi_typeof(env, value, &value_type);
21762195
if (status != napi_ok) return status;
@@ -2184,6 +2203,8 @@ napi_status napi_instanceof(napi_env env,
21842203
return napi_get_value_bool(env, js_result, result);
21852204
}
21862205
}
2206+
2207+
env->has_instance_available = false;
21872208
}
21882209

21892210
// If running constructor[Symbol.hasInstance](object) did not work, we perform

0 commit comments

Comments
 (0)