diff options
author | Chad Austin <caustin@gmail.com> | 2014-03-22 23:52:57 -0700 |
---|---|---|
committer | Chad Austin <chad@chadaustin.me> | 2014-03-28 23:56:40 -0700 |
commit | 6291f97039f94eb2eaeae7535a7dbe9c6ff8bbe5 (patch) | |
tree | 2c6eb2deb474a78bff5410953e19eb96d07f141e | |
parent | 464f4a3cace3eba27c145d347d031930b9630a51 (diff) |
make val::new_ compatible with asm.js
-rw-r--r-- | src/embind/embind.js | 52 | ||||
-rw-r--r-- | src/embind/emval.js | 50 | ||||
-rw-r--r-- | system/include/emscripten/val.h | 12 | ||||
-rw-r--r-- | tests/embind/embind.test.js | 12 | ||||
-rw-r--r-- | tests/embind/embind_test.cpp | 16 |
5 files changed, 98 insertions, 44 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js index 45d48f12..660f7ad4 100644 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -292,7 +292,22 @@ function __embind_register_bool(rawType, name, size, trueValue, falseValue) { 'toWireType': function(destructors, o) { return o ? trueValue : falseValue; }, + 'readValueFromPointer': function(pointer) { + // TODO: if heap is fixed (like in asm.js) this could be executed outside + var heap; + if (size === 1) { + heap = HEAP8; + } else if (size === 2) { + heap = HEAP16; + } else if (size === 4) { + heap = HEAP32; + } else { + throw new TypeError("Unknown boolean type size: " + name); + } + return this['fromWireType'](heap[pointer >> shift]); + }, writeValueToPointer: function(value, pointer, _destructors) { + // TODO: if heap is fixed (like in asm.js) this could be executed outside var heap; if (size === 1) { heap = HEAP8; @@ -323,6 +338,27 @@ function getShiftFromSize(size) { } } +function integerReadValueFromPointer(shift, signed) { + if (shift === 0) { + return function(pointer) { + var heap = signed ? HEAP8 : HEAPU8; + return this['fromWireType'](heap[pointer]); + }; + } else if (shift === 1) { + return function(pointer) { + var heap = signed ? HEAP16 : HEAPU16; + return this['fromWireType'](heap[pointer >> 1]); + }; + } else if (shift === 2) { + return function(pointer) { + var heap = signed ? HEAP32 : HEAPU32; + return this['fromWireType'](heap[pointer >> 2]); + }; + } else { + throw new TypeError("Unknown integer type: " + name); + } +} + function integerWriteValueToPointer(shift, signed) { if (shift === 0) { return function(value, pointer, _destructors) { @@ -370,6 +406,7 @@ function __embind_register_integer(primitiveType, name, size, minRange, maxRange } return value | 0; }, + 'readValueFromPointer': integerReadValueFromPointer(shift, minRange !== 0), writeValueToPointer: integerWriteValueToPointer(shift, minRange !== 0), destructorFunction: null, // This type does not need a destructor }); @@ -391,6 +428,10 @@ function __embind_register_float(rawType, name, size) { } return value; }, + 'readValueFromPointer': function(pointer) { + var heap = (shift === 2) ? HEAPF32 : HEAPF64; + return this['fromWireType'](heap[pointer >> shift]); + }, writeValueToPointer: function(value, pointer, _destructors) { var heap = (shift === 2) ? HEAPF32 : HEAPF64; heap[pointer >> shift] = this['toWireType'](_destructors, value); @@ -400,6 +441,9 @@ function __embind_register_float(rawType, name, size) { } // For types whose wire types are 32-bit pointers. +function simpleReadValueFromPointer(pointer) { + return this['fromWireType'](HEAPU32[pointer >> 2]); +} function simpleWriteValueToPointer(value, pointer, destructors) { var wt = this['toWireType'](destructors, value); HEAPU32[pointer >> 2] = wt; @@ -457,6 +501,7 @@ function __embind_register_std_string(rawType, name) { } return ptr; }, + 'readValueFromPointer': simpleReadValueFromPointer, writeValueToPointer: simpleWriteValueToPointer, destructorFunction: function(ptr) { _free(ptr); }, }); @@ -498,6 +543,7 @@ function __embind_register_std_wstring(rawType, charSize, name) { } return ptr; }, + 'readValueFromPointer': simpleReadValueFromPointer, writeValueToPointer: simpleWriteValueToPointer, destructorFunction: function(ptr) { _free(ptr); }, }); @@ -515,6 +561,7 @@ function __embind_register_emval(rawType, name) { 'toWireType': function(destructors, value) { return __emval_register(value); }, + 'readValueFromPointer': simpleReadValueFromPointer, writeValueToPointer: simpleWriteValueToPointer, destructorFunction: null, // This type does not need a destructor }); @@ -784,6 +831,7 @@ function __embind_finalize_value_array(rawTupleType) { } return ptr; }, + 'readValueFromPointer': simpleReadValueFromPointer, writeValueToPointer: simpleWriteValueToPointer, destructorFunction: rawDestructor, }]; @@ -886,6 +934,7 @@ function __embind_finalize_value_object(structType) { } return ptr; }, + 'readValueFromPointer': simpleReadValueFromPointer, writeValueToPointer: simpleWriteValueToPointer, destructorFunction: rawDestructor, }]; @@ -1071,6 +1120,8 @@ RegisteredPointer.prototype.destructor = function(ptr) { } }; +RegisteredPointer.prototype['readValueFromPointer'] = simpleReadValueFromPointer; + RegisteredPointer.prototype.writeValueToPointer = simpleWriteValueToPointer; RegisteredPointer.prototype['fromWireType'] = function(ptr) { @@ -1717,6 +1768,7 @@ function __embind_register_enum( 'toWireType': function(destructors, c) { return c.value; }, + 'readValueFromPointer': integerReadValueFromPointer(shift, isSigned), writeValueToPointer: integerWriteValueToPointer(shift, isSigned), destructorFunction: null, }); diff --git a/src/embind/emval.js b/src/embind/emval.js index 6236a32d..96d477c1 100644 --- a/src/embind/emval.js +++ b/src/embind/emval.js @@ -116,48 +116,43 @@ var __newers = {}; // arity -> function function craftEmvalAllocator(argCount) { /*This function returns a new function that looks like this: - function emval_allocator_3(handle, argTypes, arg0Wired, arg1Wired, arg2Wired) { + function emval_allocator_3(handle, argTypes, args) { var argType0 = requireRegisteredType(HEAP32[(argTypes >> 2)], "parameter 0"); - var arg0 = argType0.fromWireType(arg0Wired); + var arg0 = argType0.readValueFromPointer(args); var argType1 = requireRegisteredType(HEAP32[(argTypes >> 2) + 1], "parameter 1"); - var arg1 = argType1.fromWireType(arg1Wired); + var arg1 = argType1.readValueFromPointer(args + 8); var argType2 = requireRegisteredType(HEAP32[(argTypes >> 2) + 2], "parameter 2"); - var arg2 = argType2.fromWireType(arg2Wired); + var arg2 = argType2.readValueFromPointer(args + 16); var constructor = _emval_handle_array[handle].value; - var emval = new constructor(arg0, arg1, arg2); - return emval; + var obj = new constructor(arg0, arg1, arg2); + return __emval_register(obj); } */ - var args1 = ["requireRegisteredType", "HEAP32", "_emval_handle_array", "__emval_register"]; - var args2 = [requireRegisteredType, HEAP32, _emval_handle_array, __emval_register]; - var argsList = ""; - var argsListWired = ""; for(var i = 0; i < argCount; ++i) { argsList += (i!==0?", ":"")+"arg"+i; // 'arg0, arg1, ..., argn' - argsListWired += ", arg"+i+"Wired"; // ', arg0Wired, arg1Wired, ..., argnWired' } - var invokerFnBody = - "return function emval_allocator_"+argCount+"(handle, argTypes " + argsListWired + ") {\n"; + var functionBody = + "return function emval_allocator_"+argCount+"(handle, argTypes, args) {\n"; for(var i = 0; i < argCount; ++i) { - invokerFnBody += + functionBody += "var argType"+i+" = requireRegisteredType(HEAP32[(argTypes >> 2) + "+i+"], \"parameter "+i+"\");\n" + - "var arg"+i+" = argType"+i+".fromWireType(arg"+i+"Wired);\n"; + "var arg"+i+" = argType"+i+".readValueFromPointer(args + " + i * 8 + ");\n"; } - invokerFnBody += + functionBody += "var constructor = _emval_handle_array[handle].value;\n" + "var obj = new constructor("+argsList+");\n" + "return __emval_register(obj);\n" + "}\n"; - args1.push(invokerFnBody); - var invokerFunction = new_(Function, args1).apply(null, args2); - return invokerFunction; + /*jshint evil:true*/ + return (new Function("requireRegisteredType", "HEAP32", "_emval_handle_array", "__emval_register", functionBody))( + requireRegisteredType, HEAP32, _emval_handle_array, __emval_register); } -function __emval_new(handle, argCount, argTypes) { +function __emval_new(handle, argCount, argTypes, args) { requireHandle(handle); var newer = __newers[argCount]; @@ -166,20 +161,7 @@ function __emval_new(handle, argCount, argTypes) { __newers[argCount] = newer; } - if (argCount === 0) { - return newer(handle, argTypes); - } else if (argCount === 1) { - return newer(handle, argTypes, arguments[3]); - } else if (argCount === 2) { - return newer(handle, argTypes, arguments[3], arguments[4]); - } else if (argCount === 3) { - return newer(handle, argTypes, arguments[3], arguments[4], arguments[5]); - } else if (argCount === 4) { - return newer(handle, argTypes, arguments[3], arguments[4], arguments[5], arguments[6]); - } else { - // This is a slow path! (.apply and .splice are slow), so a few specializations are present above. - return newer.apply(null, arguments.splice(1)); - } + return newer(handle, argTypes, args); } // appease jshint (technically this code uses eval) diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h index 49b143c1..501e927d 100644 --- a/system/include/emscripten/val.h +++ b/system/include/emscripten/val.h @@ -28,8 +28,8 @@ namespace emscripten { EM_VAL _emval_new( EM_VAL value, unsigned argCount, - internal::TYPEID argTypes[] - /*, ... */); + internal::TYPEID argTypes[], + ...); EM_VAL _emval_get_global(const char* name); EM_VAL _emval_get_module_property(const char* name); @@ -232,14 +232,8 @@ namespace emscripten { WithPolicies<>::ArgTypeList<Args...> argList; // todo: this is awfully similar to operator(), can we // merge them somehow? - typedef EM_VAL (*TypedNew)( - EM_VAL, - unsigned, - TYPEID argTypes[], - typename BindingType<Args>::WireType...); - TypedNew typedNew = reinterpret_cast<TypedNew>(&_emval_new); return val( - typedNew( + _emval_new( handle, argList.count, argList.types, diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js index 64b3e889..b303d51c 100644 --- a/tests/embind/embind.test.js +++ b/tests/embind/embind.test.js @@ -1973,6 +1973,18 @@ module({ assert.equal(cm.Enum.ONE, cm.val_as_enum(cm.Enum.ONE)); }); }); + + BaseFixture.extend("val::new_", function() { + test("variety of types", function() { + function factory() { + this.arguments = Array.prototype.slice.call(arguments, 0); + } + var instance = cm.construct_with_6_arguments(factory); + assert.deepEqual( + [6, -12.5, "a3", {x: 1, y: 2, z: 3, w: 4}, cm.EnumClass.TWO, [-1, -2, -3, -4]], + instance.arguments); + }); + }); }); /* global run_all_tests */ diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp index 2f78fa2f..8dab6ec7 100644 --- a/tests/embind/embind_test.cpp +++ b/tests/embind/embind_test.cpp @@ -842,7 +842,7 @@ Enum emval_test_take_and_return_Enum(Enum e) { return e; } -enum class EnumClass { ONE, TWO }; +enum class EnumClass : char { ONE, TWO }; EnumClass emval_test_take_and_return_EnumClass(EnumClass e) { return e; @@ -2332,3 +2332,17 @@ EMSCRIPTEN_BINDINGS(val_as) { // memory_view is always JS -> C++ //function("val_as_memory_view", &val_as<memory_view>); } + +val construct_with_6(val factory) { + unsigned char a1 = 6; + double a2 = -12.5; + std::string a3("a3"); + StructVector a4(1, 2, 3, 4); + EnumClass a5 = EnumClass::TWO; + TupleVector a6(-1, -2, -3, -4); + return factory.new_(a1, a2, a3, a4, a5, a6); +} + +EMSCRIPTEN_BINDINGS(val_new_) { + function("construct_with_6_arguments", &construct_with_6); +} |