aboutsummaryrefslogtreecommitdiff
path: root/benchmark
diff options
context:
space:
mode:
authorGabriel Schulhof <gabriel.schulhof@intel.com>2019-06-14 16:44:18 -0700
committerGabriel Schulhof <gabriel.schulhof@intel.com>2020-07-31 18:30:30 -0700
commitcc7ec889e863433c248bc4b5c8e33f61ccc40f29 (patch)
tree308069adb8a8948f965504ada6835a5d30c6d10e /benchmark
parent8b3ad75b03ee49688ac0e9e4aa2481231fd4ff96 (diff)
downloadios-node-v8-cc7ec889e863433c248bc4b5c8e33f61ccc40f29.tar.gz
ios-node-v8-cc7ec889e863433c248bc4b5c8e33f61ccc40f29.tar.bz2
ios-node-v8-cc7ec889e863433c248bc4b5c8e33f61ccc40f29.zip
n-api: support type-tagging objects
`napi_instanceof()` is insufficient for reliably establishing the data type to which a pointer stored with `napi_wrap()` or `napi_create_external()` inside a JavaScript object points. Thus, we need a way to "mark" an object with a value that, when later retrieved, can unambiguously tell us whether it is safe to cast the pointer stored inside it to a certain structure. Such a check must survive loading/unloading/multiple instances of an addon, so we use UUIDs chosen *a priori*. Fixes: https://github.com/nodejs/node/issues/28164 Co-authored-by: Anna Henningsen <github@addaleax.net> PR-URL: https://github.com/nodejs/node/pull/28237 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Signed-off-by: Gabriel Schulhof <gabriel.schulhof@intel.com>
Diffstat (limited to 'benchmark')
-rw-r--r--benchmark/napi/type-tag-check/binding.gyp8
-rw-r--r--benchmark/napi/type-tag-check/index.js18
-rw-r--r--benchmark/napi/type-tag/binding.c84
-rw-r--r--benchmark/napi/type-tag/binding.gyp8
-rw-r--r--benchmark/napi/type-tag/check-object-tag.js18
-rw-r--r--benchmark/napi/type-tag/index.js18
6 files changed, 154 insertions, 0 deletions
diff --git a/benchmark/napi/type-tag-check/binding.gyp b/benchmark/napi/type-tag-check/binding.gyp
new file mode 100644
index 0000000000..595ab32523
--- /dev/null
+++ b/benchmark/napi/type-tag-check/binding.gyp
@@ -0,0 +1,8 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'binding',
+ 'sources': [ '../type-tag/binding.c' ]
+ }
+ ]
+}
diff --git a/benchmark/napi/type-tag-check/index.js b/benchmark/napi/type-tag-check/index.js
new file mode 100644
index 0000000000..346dfb7812
--- /dev/null
+++ b/benchmark/napi/type-tag-check/index.js
@@ -0,0 +1,18 @@
+'use strict';
+const common = require('../../common.js');
+
+let binding;
+try {
+ binding = require(`./build/${common.buildType}/binding`);
+} catch {
+ console.error(`${__filename}: Binding failed to load`);
+ process.exit(0);
+}
+
+const bench = common.createBenchmark(main, {
+ n: [1e5, 1e6, 1e7],
+});
+
+function main({ n }) {
+ binding.checkObjectTag(n, bench, bench.start, bench.end);
+}
diff --git a/benchmark/napi/type-tag/binding.c b/benchmark/napi/type-tag/binding.c
new file mode 100644
index 0000000000..7bc8b5d750
--- /dev/null
+++ b/benchmark/napi/type-tag/binding.c
@@ -0,0 +1,84 @@
+#include <assert.h>
+#define NAPI_EXPERIMENTAL
+#include <node_api.h>
+
+#define NAPI_CALL(call) \
+ do { \
+ napi_status status = call; \
+ assert(status == napi_ok && #call " failed"); \
+ } while (0);
+
+#define EXPORT_FUNC(env, exports, name, func) \
+ do { \
+ napi_value js_func; \
+ NAPI_CALL(napi_create_function((env), \
+ (name), \
+ NAPI_AUTO_LENGTH, \
+ (func), \
+ NULL, \
+ &js_func)); \
+ NAPI_CALL(napi_set_named_property((env), \
+ (exports), \
+ (name), \
+ js_func)); \
+ } while (0);
+
+static const napi_type_tag tag = {
+ 0xe7ecbcd5954842f6, 0x9e75161c9bf27282
+};
+
+static napi_value TagObject(napi_env env, napi_callback_info info) {
+ size_t argc = 4;
+ napi_value argv[4];
+ uint32_t n;
+ uint32_t index;
+ napi_handle_scope scope;
+
+ NAPI_CALL(napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
+ NAPI_CALL(napi_get_value_uint32(env, argv[0], &n));
+ NAPI_CALL(napi_open_handle_scope(env, &scope));
+ napi_value objects[n];
+ for (index = 0; index < n; index++) {
+ NAPI_CALL(napi_create_object(env, &objects[index]));
+ }
+
+ // Time the object tag creation.
+ NAPI_CALL(napi_call_function(env, argv[1], argv[2], 0, NULL, NULL));
+ for (index = 0; index < n; index++) {
+ NAPI_CALL(napi_type_tag_object(env, objects[index], &tag));
+ }
+ NAPI_CALL(napi_call_function(env, argv[1], argv[3], 1, &argv[0], NULL));
+
+ NAPI_CALL(napi_close_handle_scope(env, scope));
+ return NULL;
+}
+
+static napi_value CheckObjectTag(napi_env env, napi_callback_info info) {
+ size_t argc = 4;
+ napi_value argv[4];
+ uint32_t n;
+ uint32_t index;
+ bool is_of_type;
+
+ NAPI_CALL(napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
+ NAPI_CALL(napi_get_value_uint32(env, argv[0], &n));
+ napi_value object;
+ NAPI_CALL(napi_create_object(env, &object));
+ NAPI_CALL(napi_type_tag_object(env, object, &tag));
+
+ // Time the object tag checking.
+ NAPI_CALL(napi_call_function(env, argv[1], argv[2], 0, NULL, NULL));
+ for (index = 0; index < n; index++) {
+ NAPI_CALL(napi_check_object_type_tag(env, object, &tag, &is_of_type));
+ assert(is_of_type && " type mismatch");
+ }
+ NAPI_CALL(napi_call_function(env, argv[1], argv[3], 1, &argv[0], NULL));
+
+ return NULL;
+}
+
+NAPI_MODULE_INIT() {
+ EXPORT_FUNC(env, exports, "tagObject", TagObject);
+ EXPORT_FUNC(env, exports, "checkObjectTag", CheckObjectTag);
+ return exports;
+}
diff --git a/benchmark/napi/type-tag/binding.gyp b/benchmark/napi/type-tag/binding.gyp
new file mode 100644
index 0000000000..413621ade3
--- /dev/null
+++ b/benchmark/napi/type-tag/binding.gyp
@@ -0,0 +1,8 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'binding',
+ 'sources': [ 'binding.c' ]
+ }
+ ]
+}
diff --git a/benchmark/napi/type-tag/check-object-tag.js b/benchmark/napi/type-tag/check-object-tag.js
new file mode 100644
index 0000000000..346dfb7812
--- /dev/null
+++ b/benchmark/napi/type-tag/check-object-tag.js
@@ -0,0 +1,18 @@
+'use strict';
+const common = require('../../common.js');
+
+let binding;
+try {
+ binding = require(`./build/${common.buildType}/binding`);
+} catch {
+ console.error(`${__filename}: Binding failed to load`);
+ process.exit(0);
+}
+
+const bench = common.createBenchmark(main, {
+ n: [1e5, 1e6, 1e7],
+});
+
+function main({ n }) {
+ binding.checkObjectTag(n, bench, bench.start, bench.end);
+}
diff --git a/benchmark/napi/type-tag/index.js b/benchmark/napi/type-tag/index.js
new file mode 100644
index 0000000000..3f85b9af8e
--- /dev/null
+++ b/benchmark/napi/type-tag/index.js
@@ -0,0 +1,18 @@
+'use strict';
+const common = require('../../common.js');
+
+let binding;
+try {
+ binding = require(`./build/${common.buildType}/binding`);
+} catch {
+ console.error(`${__filename}: Binding failed to load`);
+ process.exit(0);
+}
+
+const bench = common.createBenchmark(main, {
+ n: [1e3, 1e4, 1e5],
+});
+
+function main({ n }) {
+ binding.tagObject(n, bench, bench.start, bench.end);
+}