aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/cases/legalizer_ta2.ll1
-rw-r--r--tests/cases/longjmp_tiny.ll (renamed from tests/cases/longjmp_tiny_noasm.ll)0
-rw-r--r--tests/cases/longjmp_tiny.txt (renamed from tests/cases/longjmp_tiny_noasm.txt)0
-rw-r--r--tests/cases/longjmp_tiny_invoke.ll (renamed from tests/cases/longjmp_tiny_noasm_invoke.ll)0
-rw-r--r--tests/cases/longjmp_tiny_invoke.txt (renamed from tests/cases/longjmp_tiny_noasm_invoke.txt)0
-rw-r--r--tests/cases/longjmp_tiny_phi.ll (renamed from tests/cases/longjmp_tiny_phi_noasm.ll)0
-rw-r--r--tests/cases/longjmp_tiny_phi.txt (renamed from tests/cases/longjmp_tiny_phi_noasm.txt)0
-rw-r--r--tests/cases/longjmp_tiny_phi2.ll (renamed from tests/cases/longjmp_tiny_phi2_noasm.ll)0
-rw-r--r--tests/cases/longjmp_tiny_phi2.txt (renamed from tests/cases/longjmp_tiny_phi2_noasm.txt)0
-rw-r--r--tests/embind/embind.benchmark.js201
-rwxr-xr-xtests/embind/embind.test.js164
-rw-r--r--tests/embind/embind_benchmark.cpp344
-rw-r--r--tests/embind/embind_test.cpp124
-rw-r--r--tests/embind/shell.html94
-rw-r--r--tests/gl_stride.c152
-rw-r--r--tests/gl_stride.pngbin0 -> 345620 bytes
-rwxr-xr-xtests/runner.py24
17 files changed, 1024 insertions, 80 deletions
diff --git a/tests/cases/legalizer_ta2.ll b/tests/cases/legalizer_ta2.ll
index 7e17c707..89ebcef6 100644
--- a/tests/cases/legalizer_ta2.ll
+++ b/tests/cases/legalizer_ta2.ll
@@ -188,4 +188,5 @@ done:
declare i32 @puts(i8*)
declare i32 @__gxx_personality_v0(...)
+declare void @__cxa_throw(i32, i32, i32) ; for asm1, where exceptions are enabled but this test needs a throw to bring in lib stuff
diff --git a/tests/cases/longjmp_tiny_noasm.ll b/tests/cases/longjmp_tiny.ll
index 0045847c..0045847c 100644
--- a/tests/cases/longjmp_tiny_noasm.ll
+++ b/tests/cases/longjmp_tiny.ll
diff --git a/tests/cases/longjmp_tiny_noasm.txt b/tests/cases/longjmp_tiny.txt
index 8a0aa386..8a0aa386 100644
--- a/tests/cases/longjmp_tiny_noasm.txt
+++ b/tests/cases/longjmp_tiny.txt
diff --git a/tests/cases/longjmp_tiny_noasm_invoke.ll b/tests/cases/longjmp_tiny_invoke.ll
index e1a72e00..e1a72e00 100644
--- a/tests/cases/longjmp_tiny_noasm_invoke.ll
+++ b/tests/cases/longjmp_tiny_invoke.ll
diff --git a/tests/cases/longjmp_tiny_noasm_invoke.txt b/tests/cases/longjmp_tiny_invoke.txt
index 8a0aa386..8a0aa386 100644
--- a/tests/cases/longjmp_tiny_noasm_invoke.txt
+++ b/tests/cases/longjmp_tiny_invoke.txt
diff --git a/tests/cases/longjmp_tiny_phi_noasm.ll b/tests/cases/longjmp_tiny_phi.ll
index cced7cab..cced7cab 100644
--- a/tests/cases/longjmp_tiny_phi_noasm.ll
+++ b/tests/cases/longjmp_tiny_phi.ll
diff --git a/tests/cases/longjmp_tiny_phi_noasm.txt b/tests/cases/longjmp_tiny_phi.txt
index 16f5a93e..16f5a93e 100644
--- a/tests/cases/longjmp_tiny_phi_noasm.txt
+++ b/tests/cases/longjmp_tiny_phi.txt
diff --git a/tests/cases/longjmp_tiny_phi2_noasm.ll b/tests/cases/longjmp_tiny_phi2.ll
index 1d7761c3..1d7761c3 100644
--- a/tests/cases/longjmp_tiny_phi2_noasm.ll
+++ b/tests/cases/longjmp_tiny_phi2.ll
diff --git a/tests/cases/longjmp_tiny_phi2_noasm.txt b/tests/cases/longjmp_tiny_phi2.txt
index 37e85737..37e85737 100644
--- a/tests/cases/longjmp_tiny_phi2_noasm.txt
+++ b/tests/cases/longjmp_tiny_phi2.txt
diff --git a/tests/embind/embind.benchmark.js b/tests/embind/embind.benchmark.js
new file mode 100644
index 00000000..4ce9355c
--- /dev/null
+++ b/tests/embind/embind.benchmark.js
@@ -0,0 +1,201 @@
+function _increment_counter_benchmark_js(N) {
+ var ctr = _get_counter();
+ var a = _emscripten_get_now();
+ for(i = 0; i < N; ++i) {
+ _increment_counter();
+ _increment_counter();
+ _increment_counter();
+ _increment_counter();
+ _increment_counter();
+ _increment_counter();
+ _increment_counter();
+ _increment_counter();
+ _increment_counter();
+ _increment_counter();
+ }
+ var b = _emscripten_get_now();
+ var ctr2 = _get_counter();
+ Module.print("JS increment_counter " + N + " iters: " + (b-a) + " msecs. result: " + (ctr2-ctr));
+}
+
+function _increment_class_counter_benchmark_embind_js(N) {
+ var foo = new Module['Foo']();
+ var a = _emscripten_get_now();
+ for(i = 0; i < N; ++i) {
+ foo['incr_class_counter']();
+ foo['incr_class_counter']();
+ foo['incr_class_counter']();
+ foo['incr_class_counter']();
+ foo['incr_class_counter']();
+ foo['incr_class_counter']();
+ foo['incr_class_counter']();
+ foo['incr_class_counter']();
+ foo['incr_class_counter']();
+ foo['incr_class_counter']();
+ }
+ var b = _emscripten_get_now();
+ Module.print("JS embind increment_class_counter " + N + " iters: " + (b-a) + " msecs. result: " + foo['class_counter_val']());
+ foo['delete']();
+}
+
+function _returns_input_benchmark_js() {
+ var a = _emscripten_get_now();
+ var t = 0;
+ for(i = 0; i < 100000; ++i) {
+ t += _returns_input(i);
+ t += _returns_input(i);
+ t += _returns_input(i);
+ t += _returns_input(i);
+ t += _returns_input(i);
+ t += _returns_input(i);
+ t += _returns_input(i);
+ t += _returns_input(i);
+ t += _returns_input(i);
+ t += _returns_input(i);
+ }
+ var b = _emscripten_get_now();
+ Module.print("JS returns_input 100000 iters: " + (b-a) + " msecs. result: " + t);
+}
+
+function _sum_int_benchmark_js() {
+ var a = _emscripten_get_now();
+ var r = 0;
+ for(i = 0; i < 100000; ++i) {
+ r += _sum_int(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_int(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_int(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_int(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_int(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_int(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_int(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_int(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_int(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_int(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ }
+ var b = _emscripten_get_now();
+ Module.print("JS sum_int 100000 iters: " + (b-a) + " msecs. result: " + r);
+}
+
+function _sum_float_benchmark_js() {
+ var a = _emscripten_get_now();
+ var r = 0;
+ for(i = 0; i < 100000; ++i) {
+ r += _sum_float(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_float(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_float(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_float(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_float(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_float(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_float(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_float(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_float(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += _sum_float(i, 2, 3, 4, 5, 6, 7, 8, 9);
+ }
+ var b = _emscripten_get_now();
+ Module.print("JS sum_float 100000 iters: " + (b-a) + " msecs. result: " + r);
+}
+
+function _increment_counter_benchmark_embind_js(N) {
+ var ctr = _get_counter();
+ var a = _emscripten_get_now();
+ for(i = 0; i < N; ++i) {
+ Module['increment_counter']();
+ Module['increment_counter']();
+ Module['increment_counter']();
+ Module['increment_counter']();
+ Module['increment_counter']();
+ Module['increment_counter']();
+ Module['increment_counter']();
+ Module['increment_counter']();
+ Module['increment_counter']();
+ Module['increment_counter']();
+ }
+ var b = _emscripten_get_now();
+ var ctr2 = _get_counter();
+ Module.print("JS embind increment_counter " + N + " iters: " + (b-a) + " msecs. result: " + (ctr2-ctr));
+}
+
+function _returns_input_benchmark_embind_js() {
+ var a = _emscripten_get_now();
+ var t = 0;
+ for(i = 0; i < 100000; ++i) {
+ t += Module['returns_input'](i);
+ t += Module['returns_input'](i);
+ t += Module['returns_input'](i);
+ t += Module['returns_input'](i);
+ t += Module['returns_input'](i);
+ t += Module['returns_input'](i);
+ t += Module['returns_input'](i);
+ t += Module['returns_input'](i);
+ t += Module['returns_input'](i);
+ t += Module['returns_input'](i);
+ }
+ var b = _emscripten_get_now();
+ Module.print("JS embind returns_input 100000 iters: " + (b-a) + " msecs. result: " + t);
+}
+
+function _sum_int_benchmark_embind_js() {
+ var a = _emscripten_get_now();
+ var r = 0;
+ for(i = 0; i < 100000; ++i) {
+ r += Module['sum_int'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_int'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_int'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_int'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_int'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_int'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_int'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_int'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_int'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_int'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ }
+ var b = _emscripten_get_now();
+ Module.print("JS embind sum_int 100000 iters: " + (b-a) + " msecs. result: " + r);
+}
+
+function _sum_float_benchmark_embind_js() {
+ var a = _emscripten_get_now();
+ var r = 0;
+ for(i = 0; i < 100000; ++i) {
+ r += Module['sum_float'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_float'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_float'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_float'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_float'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_float'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_float'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_float'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_float'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ r += Module['sum_float'](i, 2, 3, 4, 5, 6, 7, 8, 9);
+ }
+ var b = _emscripten_get_now();
+ Module.print("JS embind sum_float 100000 iters: " + (b-a) + " msecs. result: " + r);
+}
+
+function _move_gameobjects_benchmark_embind_js() {
+ var N = 10000;
+ var objects = [];
+ for(i = 0; i < N; ++i) {
+ objects.push(Module['create_game_object']());
+ }
+
+ var a = _emscripten_get_now();
+ for(i = 0; i < N; ++i) {
+ var t = objects[i]['GetTransform']();
+ var pos = Module['add'](t['GetPosition'](), [2, 0, 1]);
+ var rot = Module['add'](t['GetRotation'](), [0.1, 0.2, 0.3]);
+ t['SetPosition'](pos);
+ t['SetRotation'](rot);
+ t['delete']();
+ }
+ var b = _emscripten_get_now();
+
+ var accum = [0,0,0];
+ for(i = 0; i < N; ++i) {
+ var t = objects[i]['GetTransform']();
+ accum = Module['add'](Module['add'](accum, t['GetPosition']()), t['GetRotation']());
+ t['delete']();
+ }
+
+ Module.print("JS embind move_gameobjects " + N + " iters: " + (b-a) + " msecs. Result: " + (accum[0] + accum[1] + accum[2]));
+}
diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js
index 290fed72..8ef46ad8 100755
--- a/tests/embind/embind.test.js
+++ b/tests/embind/embind.test.js
@@ -143,33 +143,49 @@ module({
var e = assert.throws(cm.BindingError, function() {
cm.Derived.prototype.setMember.call(a, "foo");
});
- assert.equal('Derived.setMember incompatible with "this" of type HasTwoBases', e.message);
+ assert.equal('Expected null or instance of Derived, got an instance of Base2', e.message);
a.delete();
+
+ // Base1 and Base2 both have the method 'getField()' exposed - make sure
+ // that calling the Base2 function with a 'this' instance of Base1 doesn't accidentally work!
+ var b = new cm.Base1;
+ var e = assert.throws(cm.BindingError, function() {
+ cm.Base2.prototype.getField.call(b);
+ });
+ assert.equal('Expected null or instance of Base2, got an instance of Base1', e.message);
+ b.delete();
});
test("calling method with invalid this throws error", function() {
var e = assert.throws(cm.BindingError, function() {
cm.Derived.prototype.setMember.call(undefined, "foo");
});
- if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { // TODO: Enable this to work in Emscripten runner as well!
- // got Error: expected: Derived.setMember with invalid "this": undefined, actual: Derived.setMember incompatible with "this" of type Object
- assert.equal('Derived.setMember with invalid "this": undefined', e.message);
- }
+ assert.equal('Cannot pass "[object global]" as a Derived*', e.message);
+
+ var e = assert.throws(cm.BindingError, function() {
+ cm.Derived.prototype.setMember.call(true, "foo");
+ });
+ assert.equal('Cannot pass "true" as a Derived*', e.message);
+
+ var e = assert.throws(cm.BindingError, function() {
+ cm.Derived.prototype.setMember.call(null, "foo");
+ });
+ assert.equal('Cannot pass "[object global]" as a Derived*', e.message);
+
+ var e = assert.throws(cm.BindingError, function() {
+ cm.Derived.prototype.setMember.call(42, "foo");
+ });
+ assert.equal('Cannot pass "42" as a Derived*', e.message);
var e = assert.throws(cm.BindingError, function() {
cm.Derived.prototype.setMember.call("this", "foo");
});
- if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { // TODO: Enable this to work in Emscripten runner as well!
- // TODO got 'Derived.setMember incompatible with "this" of type Object'
- assert.equal('Derived.setMember with invalid "this": this', e.message);
- }
+ assert.equal('Cannot pass "this" as a Derived*', e.message);
var e = assert.throws(cm.BindingError, function() {
cm.Derived.prototype.setMember.call({}, "foo");
});
- if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { // TODO: Enable this to work in Emscripten runner as well!
- assert.equal('Derived.setMember incompatible with "this" of type Object', e.message);
- }
+ assert.equal('Cannot pass "[object Object]" as a Derived*', e.message);
});
test("setting and getting property on unrelated class throws error", function() {
@@ -388,6 +404,59 @@ module({
});
});
+ BaseFixture.extend("string", function() {
+ test("non-ascii strings", function() {
+ var expected = '';
+ for (var i = 0; i < 128; ++i) {
+ expected += String.fromCharCode(128 + i);
+ }
+ assert.equal(expected, cm.get_non_ascii_string());
+ });
+
+ test("passing non-8-bit strings from JS to std::string throws", function() {
+ assert.throws(cm.BindingError, function() {
+ cm.emval_test_take_and_return_std_string("\u1234");
+ });
+ });
+
+ test("can't pass integers as strings", function() {
+ var e = assert.throws(cm.BindingError, function() {
+ cm.emval_test_take_and_return_std_string(10);
+ });
+ });
+
+ test("can pass Uint8Array to std::string", function() {
+ var e = cm.emval_test_take_and_return_std_string(new Uint8Array([65, 66, 67, 68]));
+ assert.equal('ABCD', e);
+ });
+
+ test("can pass Int8Array to std::string", function() {
+ var e = cm.emval_test_take_and_return_std_string(new Int8Array([65, 66, 67, 68]));
+ assert.equal('ABCD', e);
+ });
+
+ test("can pass ArrayBuffer to std::string", function() {
+ var e = cm.emval_test_take_and_return_std_string((new Int8Array([65, 66, 67, 68])).buffer);
+ assert.equal('ABCD', e);
+ });
+
+ test("non-ascii wstrings", function() {
+ var expected = String.fromCharCode(10) +
+ String.fromCharCode(1234) +
+ String.fromCharCode(2345) +
+ String.fromCharCode(65535);
+ assert.equal(expected, cm.get_non_ascii_wstring());
+ });
+
+ test("passing unicode string into C++", function() {
+ var expected = String.fromCharCode(10) +
+ String.fromCharCode(1234) +
+ String.fromCharCode(2345) +
+ String.fromCharCode(65535);
+ assert.equal(expected, cm.take_and_return_std_wstring(expected));
+ });
+ });
+
BaseFixture.extend("embind", function() {
test("value creation", function() {
assert.equal(15, cm.emval_test_new_integer());
@@ -837,6 +906,37 @@ module({
assert.equal(0, cm.count_emval_handles());
});
+ test("class properties can be methods", function() {
+ var a = {};
+ var b = {foo: 'foo'};
+ var c = new cm.ValHolder(a);
+ assert.equal(a, c.val);
+ c.val = b;
+ assert.equal(b, c.val);
+ c.delete();
+ });
+
+ test("class properties can be read-only", function() {
+ var a = {};
+ var h = new cm.ValHolder(a);
+ assert.equal(a, h.val_readonly);
+ var e = assert.throws(cm.BindingError, function() {
+ h.val_readonly = 10;
+ });
+ assert.equal('ValHolder.val_readonly is a read-only property', e.message);
+ h.delete();
+ });
+
+ test("read-only member field", function() {
+ var a = new cm.HasReadOnlyProperty(10);
+ assert.equal(10, a.i);
+ var e = assert.throws(cm.BindingError, function() {
+ a.i = 20;
+ });
+ assert.equal('HasReadOnlyProperty.i is a read-only property', e.message);
+ a.delete();
+ });
+
test("class instance $$ property is non-enumerable", function() {
var c = new cm.ValHolder(undefined);
assert.deepEqual([], Object.keys(c));
@@ -1415,24 +1515,6 @@ module({
});
});
- BaseFixture.extend("JavaScript interface", function() {
- this.setUp(function() {
- this.testobj = {
- "method1": function() { return 111; },
- "method2": function() { return 222; }
- };
- });
-
- test("pass js object to c++ and call its method", function() {
- var obj = new cm.JSInterfaceHolder(this.testobj);
- assert.equal(111, obj.callMethod("method1"));
- assert.equal(222, obj.callMethod("method2"));
- assert.equal(111, obj.callMethodUsingSharedPtr("method1"));
- assert.equal(222, obj.callMethodUsingSharedPtr("method2"));
- obj.delete();
- });
- });
-
BaseFixture.extend("abstract methods", function() {
test("can call abstract methods", function() {
var obj = cm.getAbstractClass();
@@ -1454,6 +1536,28 @@ module({
assert.equal(expected, cm.callAbstractMethod(impl));
impl.delete();
});
+
+ test("can implement optional methods in JavaScript", function() {
+ var expected = "my JS string";
+ function MyImplementation() {
+ this.rv = expected;
+ }
+ MyImplementation.prototype.optionalMethod = function() {
+ return this.rv;
+ };
+
+ var impl = cm.AbstractClass.implement(new MyImplementation);
+ assert.equal(expected, impl.optionalMethod(expected));
+ assert.equal(expected, cm.callOptionalMethod(impl, expected));
+ impl.delete();
+ });
+
+ test("if not implemented then optional method runs default", function() {
+ var impl = cm.AbstractClass.implement({});
+ assert.equal("optionalfoo", impl.optionalMethod("foo"));
+ assert.equal("optionalfoo", cm.callOptionalMethod(impl, "foo"));
+ impl.delete();
+ });
});
BaseFixture.extend("registration order", function() {
diff --git a/tests/embind/embind_benchmark.cpp b/tests/embind/embind_benchmark.cpp
new file mode 100644
index 00000000..80abc7e7
--- /dev/null
+++ b/tests/embind/embind_benchmark.cpp
@@ -0,0 +1,344 @@
+#include <stdio.h>
+#include <emscripten.h>
+#include <bind.h>
+#include <memory>
+
+int counter = 0;
+
+extern "C"
+{
+
+int __attribute__((noinline)) get_counter()
+{
+ return counter;
+}
+
+void __attribute__((noinline)) increment_counter()
+{
+ ++counter;
+}
+
+int __attribute__((noinline)) sum_int(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9)
+{
+ return v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9;
+}
+
+float __attribute__((noinline)) sum_float(float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8, float v9)
+{
+ return v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9;
+}
+
+int __attribute__((noinline)) returns_input(int i)
+{
+ return i;
+}
+
+extern void increment_counter_benchmark_js(int N);
+extern void returns_input_benchmark_js();
+extern void sum_int_benchmark_js();
+extern void sum_float_benchmark_js();
+
+extern void increment_counter_benchmark_embind_js(int N);
+extern void returns_input_benchmark_embind_js();
+extern void sum_int_benchmark_embind_js();
+extern void sum_float_benchmark_embind_js();
+
+extern void increment_class_counter_benchmark_embind_js(int N);
+extern void move_gameobjects_benchmark_embind_js();
+}
+
+class Vec3
+{
+public:
+ Vec3():x(0),y(0),z(0) {}
+ Vec3(float x_, float y_, float z_):x(x_),y(y_),z(z_) {}
+ float x,y,z;
+};
+
+Vec3 add(const Vec3 &lhs, const Vec3 &rhs) { return Vec3(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z); }
+
+class Transform
+{
+public:
+ Transform():scale(1) {}
+
+ Vec3 pos;
+ Vec3 rot;
+ float scale;
+
+ Vec3 __attribute__((noinline)) GetPosition() const { return pos; }
+ Vec3 __attribute__((noinline)) GetRotation() const { return rot; }
+ float __attribute__((noinline)) GetScale() const { return scale; }
+
+ void __attribute__((noinline)) SetPosition(const Vec3 &pos_) { pos = pos_; }
+ void __attribute__((noinline)) SetRotation(const Vec3 &rot_) { rot = rot_; }
+ void __attribute__((noinline)) SetScale(float scale_) { scale = scale_; }
+};
+typedef std::shared_ptr<Transform> TransformPtr;
+
+class GameObject
+{
+public:
+ GameObject()
+ {
+ transform = std::make_shared<Transform>();
+ }
+ std::shared_ptr<Transform> transform;
+
+ TransformPtr __attribute__((noinline)) GetTransform() const { return transform; }
+};
+typedef std::shared_ptr<GameObject> GameObjectPtr;
+
+GameObjectPtr create_game_object()
+{
+ return std::make_shared<GameObject>();
+}
+
+class Foo
+{
+public:
+ Foo()
+ :class_counter(0)
+ {
+ }
+
+ void __attribute__((noinline)) incr_global_counter()
+ {
+ ++counter;
+ }
+
+ void __attribute__((noinline)) incr_class_counter()
+ {
+ ++class_counter;
+ }
+
+ int class_counter_val() const
+ {
+ return class_counter;
+ }
+
+ int class_counter;
+};
+
+EMSCRIPTEN_BINDINGS(benchmark)
+{
+ using namespace emscripten;
+
+ class_<GameObject>("GameObject")
+ .smart_ptr<GameObjectPtr>()
+ .function("GetTransform", &GameObject::GetTransform);
+
+ class_<Transform>("Transform")
+ .smart_ptr<TransformPtr>()
+ .function("GetPosition", &Transform::GetPosition)
+ .function("GetRotation", &Transform::GetRotation)
+ .function("GetScale", &Transform::GetScale)
+ .function("SetPosition", &Transform::SetPosition)
+ .function("SetRotation", &Transform::SetRotation)
+ .function("SetScale", &Transform::SetScale);
+
+ value_tuple<Vec3>("Vec3")
+ .element(&Vec3::x)
+ .element(&Vec3::y)
+ .element(&Vec3::z);
+
+ function("create_game_object", &create_game_object);
+ function("add", &add);
+
+ function("get_counter", &get_counter);
+ function("increment_counter", &increment_counter);
+ function("returns_input", &returns_input);
+ function("sum_int", &sum_int);
+ function("sum_float", &sum_float);
+
+ class_<Foo>("Foo")
+ .constructor<>()
+ .function("incr_global_counter", &Foo::incr_global_counter)
+ .function("incr_class_counter", &Foo::incr_class_counter)
+ .function("class_counter_val", &Foo::class_counter_val);
+}
+
+void __attribute__((noinline)) emscripten_get_now_benchmark(int N)
+{
+ volatile float t = emscripten_get_now();
+ for(int i = 0; i < N; ++i)
+ {
+ emscripten_get_now();
+ emscripten_get_now();
+ emscripten_get_now();
+ emscripten_get_now();
+ emscripten_get_now();
+ emscripten_get_now();
+ emscripten_get_now();
+ emscripten_get_now();
+ emscripten_get_now();
+ emscripten_get_now();
+ }
+ volatile float t2 = emscripten_get_now();
+ printf("C++ emscripten_get_now %d iters: %f msecs.\n", N, (t2-t));
+}
+
+void __attribute__((noinline)) increment_counter_benchmark(int N)
+{
+ volatile float t = emscripten_get_now();
+ for(int i = 0; i < N; ++i)
+ {
+ increment_counter();
+ increment_counter();
+ increment_counter();
+ increment_counter();
+ increment_counter();
+ increment_counter();
+ increment_counter();
+ increment_counter();
+ increment_counter();
+ increment_counter();
+ }
+ volatile float t2 = emscripten_get_now();
+ printf("C++ increment_counter %d iters: %f msecs.\n", N, (t2-t));
+}
+
+void __attribute__((noinline)) increment_class_counter_benchmark(int N)
+{
+ Foo foo;
+ volatile float t = emscripten_get_now();
+ for(int i = 0; i < N; ++i)
+ {
+ foo.incr_class_counter();
+ foo.incr_class_counter();
+ foo.incr_class_counter();
+ foo.incr_class_counter();
+ foo.incr_class_counter();
+ foo.incr_class_counter();
+ foo.incr_class_counter();
+ foo.incr_class_counter();
+ foo.incr_class_counter();
+ foo.incr_class_counter();
+ }
+ volatile float t2 = emscripten_get_now();
+ printf("C++ increment_class_counter %d iters: %f msecs. result: %d\n", N, (t2-t), foo.class_counter);
+}
+
+void __attribute__((noinline)) returns_input_benchmark()
+{
+ volatile int r = 0;
+ volatile float t = emscripten_get_now();
+ for(int i = 0; i < 100000; ++i)
+ {
+ r += returns_input(i);
+ r += returns_input(i);
+ r += returns_input(i);
+ r += returns_input(i);
+ r += returns_input(i);
+ r += returns_input(i);
+ r += returns_input(i);
+ r += returns_input(i);
+ r += returns_input(i);
+ r += returns_input(i);
+ }
+ volatile float t2 = emscripten_get_now();
+ printf("C++ returns_input 100000 iters: %f msecs.\n", (t2-t));
+}
+
+void __attribute__((noinline)) sum_int_benchmark()
+{
+ volatile float t = emscripten_get_now();
+ volatile int r = 0;
+ for(int i = 0; i < 100000; ++i)
+ {
+ r += sum_int(i,2,3,4,5,6,7,8,9);
+ r += sum_int(i,2,3,4,5,6,7,8,9);
+ r += sum_int(i,2,3,4,5,6,7,8,9);
+ r += sum_int(i,2,3,4,5,6,7,8,9);
+ r += sum_int(i,2,3,4,5,6,7,8,9);
+ r += sum_int(i,2,3,4,5,6,7,8,9);
+ r += sum_int(i,2,3,4,5,6,7,8,9);
+ r += sum_int(i,2,3,4,5,6,7,8,9);
+ r += sum_int(i,2,3,4,5,6,7,8,9);
+ r += sum_int(i,2,3,4,5,6,7,8,9);
+ }
+ volatile float t2 = emscripten_get_now();
+ printf("C++ sum_int 100000 iters: %f msecs.\n", (t2-t));
+}
+
+void __attribute__((noinline)) sum_float_benchmark()
+{
+ volatile float f = 0.f;
+ volatile float t = emscripten_get_now();
+ for(int i = 0; i < 100000; ++i)
+ {
+ f += sum_float((float)i,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f);
+ f += sum_float((float)i,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f);
+ f += sum_float((float)i,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f);
+ f += sum_float((float)i,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f);
+ f += sum_float((float)i,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f);
+ f += sum_float((float)i,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f);
+ f += sum_float((float)i,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f);
+ f += sum_float((float)i,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f);
+ f += sum_float((float)i,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f);
+ f += sum_float((float)i,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f);
+ }
+ volatile float t2 = emscripten_get_now();
+ printf("C++ sum_float 100000 iters: %f msecs.\n", (t2-t));
+}
+
+void __attribute__((noinline)) move_gameobjects_benchmark()
+{
+ const int N = 10000;
+ GameObjectPtr objects[N];
+ for(int i = 0; i < N; ++i)
+ objects[i] = create_game_object();
+
+ volatile float t = emscripten_get_now();
+ for(int i = 0; i < N; ++i)
+ {
+ TransformPtr t = objects[i]->GetTransform();
+ Vec3 pos = add(t->GetPosition(), Vec3(2.f, 0.f, 1.f));
+ Vec3 rot = add(t->GetRotation(), Vec3(0.1f, 0.2f, 0.3f));
+ t->SetPosition(pos);
+ t->SetRotation(rot);
+ }
+ volatile float t2 = emscripten_get_now();
+
+ Vec3 accum;
+ for(int i = 0; i < N; ++i)
+ accum = add(add(accum, objects[i]->GetTransform()->GetPosition()), objects[i]->GetTransform()->GetRotation());
+ printf("C++ move_gameobjects %d iters: %f msecs. Result: %f\n", N, (t2-t), accum.x+accum.y+accum.z);
+}
+
+int main()
+{
+ for(int i = 1000; i <= 100000; i *= 10)
+ emscripten_get_now_benchmark(i);
+
+ printf("\n");
+ for(int i = 1000; i <= 100000; i *= 10)
+ {
+ increment_counter_benchmark(i);
+ increment_counter_benchmark_js(i);
+ increment_counter_benchmark_embind_js(i);
+ printf("\n");
+ }
+
+ for(int i = 1000; i <= 100000; i *= 10)
+ {
+ increment_class_counter_benchmark(i);
+ increment_class_counter_benchmark_embind_js(i);
+ printf("\n");
+ }
+
+ returns_input_benchmark();
+ returns_input_benchmark_js();
+ returns_input_benchmark_embind_js();
+ printf("\n");
+ sum_int_benchmark();
+ sum_int_benchmark_js();
+ sum_int_benchmark_embind_js();
+ printf("\n");
+ sum_float_benchmark();
+ sum_float_benchmark_js();
+ sum_float_benchmark_embind_js();
+ printf("\n");
+ move_gameobjects_benchmark();
+ move_gameobjects_benchmark_embind_js();
+}
diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp
index 1384406a..f2359955 100644
--- a/tests/embind/embind_test.cpp
+++ b/tests/embind/embind_test.cpp
@@ -79,6 +79,24 @@ unsigned emval_test_sum(val v) {
return rv;
}
+std::string get_non_ascii_string() {
+ char c[128 + 1];
+ c[128] = 0;
+ for (int i = 0; i < 128; ++i) {
+ c[i] = 128 + i;
+ }
+ return c;
+}
+
+std::wstring get_non_ascii_wstring() {
+ std::wstring ws(4, 0);
+ ws[0] = 10;
+ ws[1] = 1234;
+ ws[2] = 2345;
+ ws[3] = 65535;
+ return ws;
+}
+
std::string emval_test_take_and_return_const_char_star(const char* str) {
return str;
}
@@ -91,6 +109,10 @@ std::string emval_test_take_and_return_std_string_const_ref(const std::string& s