diff options
-rwxr-xr-x | emcc | 2 | ||||
-rwxr-xr-x | emscripten.py | 12 | ||||
-rw-r--r-- | src/analyzer.js | 16 | ||||
-rwxr-xr-x | src/embind/embind.js | 631 | ||||
-rwxr-xr-x | src/embind/emval.js | 60 | ||||
-rw-r--r-- | src/jsifier.js | 60 | ||||
-rw-r--r-- | src/library.js | 63 | ||||
-rw-r--r-- | src/library_browser.js | 6 | ||||
-rw-r--r-- | src/library_gl.js | 8 | ||||
-rw-r--r-- | src/preamble.js | 2 | ||||
-rw-r--r-- | src/settings.js | 1 | ||||
-rwxr-xr-x | system/include/emscripten/bind.h | 192 | ||||
-rw-r--r-- | system/include/emscripten/val.h | 57 | ||||
-rwxr-xr-x | system/include/emscripten/wire.h | 34 | ||||
-rwxr-xr-x | system/lib/embind/bind.cpp | 23 | ||||
-rw-r--r-- | tests/cases/legalizer_ta2.ll | 1 | ||||
-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.js | 201 | ||||
-rwxr-xr-x | tests/embind/embind.test.js | 164 | ||||
-rw-r--r-- | tests/embind/embind_benchmark.cpp | 344 | ||||
-rw-r--r-- | tests/embind/embind_test.cpp | 124 | ||||
-rw-r--r-- | tests/embind/shell.html | 94 | ||||
-rw-r--r-- | tests/gl_stride.c | 152 | ||||
-rw-r--r-- | tests/gl_stride.png | bin | 0 -> 345620 bytes | |||
-rwxr-xr-x | tests/runner.py | 24 | ||||
-rw-r--r-- | tools/eliminator/asm-eliminator-test-output.js | 15 | ||||
-rw-r--r-- | tools/eliminator/asm-eliminator-test.js | 15 | ||||
-rw-r--r-- | tools/js-optimizer.js | 13 | ||||
-rw-r--r-- | tools/shared.py | 4 |
36 files changed, 1879 insertions, 439 deletions
@@ -1002,7 +1002,7 @@ try: # Apply effects from settings if shared.Settings.ASM_JS: - assert opt_level == 2, 'asm.js requires -O2' + assert opt_level >= 1, 'asm.js requires -O1 or above' if closure: print >> sys.stderr, 'emcc: warning: disabling closure because it is not compatible with asm.js code generation' diff --git a/emscripten.py b/emscripten.py index 6e5f1e7c..6d384a96 100755 --- a/emscripten.py +++ b/emscripten.py @@ -426,7 +426,7 @@ function invoke_%s(%s) { try { %sModule.dynCall_%s(%s); } catch(e) { - asm.setThrew(1); + asm.setThrew(1, 0); } } ''' % (sig, args, 'return ' if sig[0] != 'v' else '', sig, args) @@ -489,6 +489,8 @@ var asm = (function(global, env, buffer) { var HEAPF64 = new global.Float64Array(buffer); ''' % (asm_setup,) + '\n' + asm_global_vars + ''' var __THREW__ = 0; + var threwValue = 0; + var setjmpId = 0; var undef = 0; var tempInt = 0, tempBigInt = 0, tempBigIntP = 0, tempBigIntS = 0, tempBigIntR = 0.0, tempBigIntI = 0, tempBigIntD = 0, tempValue = 0, tempDouble = 0.0; ''' + ''.join([''' @@ -509,9 +511,13 @@ var asm = (function(global, env, buffer) { top = top|0; STACKTOP = top; } - function setThrew(threw) { + function setThrew(threw, value) { threw = threw|0; - __THREW__ = threw; + value = value|0; + if ((__THREW__|0) == 0) { + __THREW__ = threw; + threwValue = value; + } } ''' + ''.join([''' function setTempRet%d(value) { diff --git a/src/analyzer.js b/src/analyzer.js index df5a435e..3278139b 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -1389,21 +1389,21 @@ function analyzer(data, sidePass) { var line = label.lines[j]; if ((line.intertype == 'call' || line.intertype == 'invoke') && line.ident == setjmp) { // Add a new label - var oldIdent = label.ident; - var newIdent = func.labelIdCounter++; + var oldLabel = label.ident; + var newLabel = func.labelIdCounter++; if (!func.setjmpTable) func.setjmpTable = []; - func.setjmpTable.push([oldIdent, newIdent, line.assignTo]); + func.setjmpTable.push({ oldLabel: oldLabel, newLabel: newLabel, assignTo: line.assignTo }); func.labels.splice(i+1, 0, { intertype: 'label', - ident: newIdent, + ident: newLabel, lineNum: label.lineNum + 0.5, lines: label.lines.slice(j+1) }); - func.labelsDict[newIdent] = func.labels[i+1]; + func.labelsDict[newLabel] = func.labels[i+1]; label.lines = label.lines.slice(0, j+1); label.lines.push({ intertype: 'branch', - label: toNiceIdent(newIdent), + label: toNiceIdent(newLabel), lineNum: line.lineNum + 0.01, // XXX legalizing might confuse this }); // Correct phis @@ -1412,8 +1412,8 @@ function analyzer(data, sidePass) { if (phi.intertype == 'phi') { for (var i = 0; i < phi.params.length; i++) { var sourceLabelId = getActualLabelId(phi.params[i].label); - if (sourceLabelId == oldIdent) { - phi.params[i].label = newIdent; + if (sourceLabelId == oldLabel) { + phi.params[i].label = newLabel; } } } diff --git a/src/embind/embind.js b/src/embind/embind.js index ee717f4b..988526b4 100755 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -1,10 +1,10 @@ /*global Module*/ /*global _malloc, _free, _memcpy*/ -/*global FUNCTION_TABLE, HEAP32, HEAPU8*/ -/*global Pointer_stringify*/ +/*global FUNCTION_TABLE, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32*/ +/*global readLatin1String*/ /*global __emval_register, _emval_handle_array, __emval_decref*/ /*global ___getTypeName*/ - +/*jslint sub:true*/ /* The symbols 'fromWireType' and 'toWireType' must be accessed via array notation to be closure-safe since craftInvokerFunction crafts functions as strings that can't be closured. */ var InternalError = Module.InternalError = extendError(Error, 'InternalError'); var BindingError = Module.BindingError = extendError(Error, 'BindingError'); var UnboundTypeError = Module.UnboundTypeError = extendError(BindingError, 'UnboundTypeError'); @@ -223,9 +223,26 @@ function whenDependentTypesAreResolved(myTypes, dependentTypes, getTypeConverter } } +var __charCodes = (function() { + var codes = new Array(256); + for (var i = 0; i < 256; ++i) { + codes[i] = String.fromCharCode(i); + } + return codes; +})(); + +function readLatin1String(ptr) { + var ret = ""; + var c = ptr; + while (HEAPU8[c]) { + ret += __charCodes[HEAPU8[c++]]; + } + return ret; +} + function getTypeName(type) { var ptr = ___getTypeName(type); - var rv = Pointer_stringify(ptr); + var rv = readLatin1String(ptr); _free(ptr); return rv; } @@ -247,34 +264,35 @@ function requireRegisteredType(rawType, humanName) { } function __embind_register_void(rawType, name) { - name = Pointer_stringify(name); + name = readLatin1String(name); registerType(rawType, { name: name, - fromWireType: function() { + 'fromWireType': function() { return undefined; }, }); } function __embind_register_bool(rawType, name, trueValue, falseValue) { - name = Pointer_stringify(name); + name = readLatin1String(name); registerType(rawType, { name: name, - fromWireType: function(wt) { + 'fromWireType': function(wt) { // ambiguous emscripten ABI: sometimes return values are // true or false, and sometimes integers (0 or 1) return !!wt; }, - toWireType: function(destructors, o) { + 'toWireType': function(destructors, o) { return o ? trueValue : falseValue; }, + destructorFunction: null, // This type does not need a destructor }); } // When converting a number from JS to C++ side, the valid range of the number is // [minRange, maxRange], inclusive. function __embind_register_integer(primitiveType, name, minRange, maxRange) { - name = Pointer_stringify(name); + name = readLatin1String(name); if (maxRange === -1) { // LLVM doesn't have signed and unsigned 32-bit types, so u32 literals come out as 'i32 -1'. Always treat those as max u32. maxRange = 4294967295; } @@ -282,10 +300,10 @@ function __embind_register_integer(primitiveType, name, minRange, maxRange) { name: name, minRange: minRange, maxRange: maxRange, - fromWireType: function(value) { + 'fromWireType': function(value) { return value; }, - toWireType: function(destructors, value) { + 'toWireType': function(destructors, value) { // todo: Here we have an opportunity for -O3 level "unsafe" optimizations: we could // avoid the following two if()s and assume value is of proper type. if (typeof value !== "number") { @@ -296,17 +314,18 @@ function __embind_register_integer(primitiveType, name, minRange, maxRange) { } return value | 0; }, + destructorFunction: null, // This type does not need a destructor }); } function __embind_register_float(rawType, name) { - name = Pointer_stringify(name); + name = readLatin1String(name); registerType(rawType, { name: name, - fromWireType: function(value) { + 'fromWireType': function(value) { return value; }, - toWireType: function(destructors, value) { + 'toWireType': function(destructors, value) { // todo: Here we have an opportunity for -O3 level "unsafe" optimizations: we could // avoid the following if() and assume value is of proper type. if (typeof value !== "number") { @@ -314,15 +333,16 @@ function __embind_register_float(rawType, name) { } return value; }, + destructorFunction: null, // This type does not need a destructor }); } -function __embind_register_cstring(rawType, name) { - name = Pointer_stringify(name); +function __embind_register_std_string(rawType, name) { + name = readLatin1String(name); registerType(rawType, { name: name, - fromWireType: function(value) { - var length = HEAP32[value >> 2]; + 'fromWireType': function(value) { + var length = HEAPU32[value >> 2]; var a = new Array(length); for (var i = 0; i < length; ++i) { a[i] = String.fromCharCode(HEAPU8[value + 4 + i]); @@ -330,32 +350,102 @@ function __embind_register_cstring(rawType, name) { _free(value); return a.join(''); }, - toWireType: function(destructors, value) { + 'toWireType': function(destructors, value) { + if (value instanceof ArrayBuffer) { + value = new Uint8Array(value); + } + + function getTAElement(ta, index) { + return ta[index]; + } + function getStringElement(string, index) { + return string.charCodeAt(index); + } + var getElement; + if (value instanceof Uint8Array) { + getElement = getTAElement; + } else if (value instanceof Int8Array) { + getElement = getTAElement; + } else if (typeof value === 'string') { + getElement = getStringElement; + } else { + throwBindingError('Cannot pass non-string to std::string'); + } + // assumes 4-byte alignment var length = value.length; var ptr = _malloc(4 + length); - HEAP32[ptr >> 2] = length; + HEAPU32[ptr >> 2] = length; + for (var i = 0; i < length; ++i) { + var charCode = getElement(value, i); + if (charCode > 255) { + _free(ptr); + throwBindingError('String has UTF-16 code units that do not fit in 8 bits'); + } + HEAPU8[ptr + 4 + i] = charCode; + } + if (destructors !== null) { + destructors.push(_free, ptr); + } + return ptr; + }, + destructorFunction: function(ptr) { _free(ptr); }, + }); +} + +function __embind_register_std_wstring(rawType, charSize, name) { + name = readLatin1String(name); + var HEAP, shift; + if (charSize === 2) { + HEAP = HEAPU16; + shift = 1; + } else if (charSize === 4) { + HEAP = HEAPU32; + shift = 2; + } + registerType(rawType, { + name: name, + 'fromWireType': function(value) { + var length = HEAPU32[value >> 2]; + var a = new Array(length); + var start = (value + 4) >> shift; + for (var i = 0; i < length; ++i) { + a[i] = String.fromCharCode(HEAP[start + i]); + } + _free(value); + return a.join(''); + }, + 'toWireType': function(destructors, value) { + // assumes 4-byte alignment + var length = value.length; + var ptr = _malloc(4 + length * charSize); + HEAPU32[ptr >> 2] = length; + var start = (ptr + 4) >> shift; for (var i = 0; i < length; ++i) { - HEAPU8[ptr + 4 + i] = value.charCodeAt(i); + HEAP[start + i] = value.charCodeAt(i); + } + if (destructors !== null) { + destructors.push(_free, ptr); } - destructors.push(_free, ptr); return ptr; }, + destructorFunction: function(ptr) { _free(ptr); }, }); } function __embind_register_emval(rawType, name) { - name = Pointer_stringify(name); + name = readLatin1String(name); registerType(rawType, { name: name, - fromWireType: function(handle) { + 'fromWireType': function(handle) { var rv = _emval_handle_array[handle].value; __emval_decref(handle); return rv; }, - toWireType: function(destructors, value) { + 'toWireType': function(destructors, value) { return __emval_register(value); }, + destructorFunction: null, // This type does not need a destructor }); } @@ -367,30 +457,142 @@ function runDestructors(destructors) { } } -function makeInvoker(name, argCount, argTypes, invoker, fn) { - if (!FUNCTION_TABLE[fn]) { - throwBindingError('function '+name+' is not defined'); +// Function implementation of operator new, per +// http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf +// 13.2.2 +// ES3 +function new_(constructor, argumentList) { + if (!(constructor instanceof Function)) { + throw new TypeError('new_ called with constructor type ' + typeof(constructor) + " which is not a function"); + } + + /* + * Previously, the following line was just: + + function dummy() {}; + + * Unfortunately, Chrome was preserving 'dummy' as the object's name, even though at creation, the 'dummy' has the + * correct constructor name. Thus, objects created with IMVU.new would show up in the debugger as 'dummy', which + * isn't very helpful. Using IMVU.createNamedFunction addresses the issue. Doublely-unfortunately, there's no way + * to write a test for this behavior. -NRD 2013.02.22 + */ + var dummy = createNamedFunction(constructor.name, function(){}); + dummy.prototype = constructor.prototype; + var obj = new dummy; + + var r = constructor.apply(obj, argumentList); + return (r instanceof Object) ? r : obj; +} + +// The path to interop from JS code to C++ code: +// (hand-written JS code) -> (autogenerated JS invoker) -> (template-generated C++ invoker) -> (target C++ function) +// craftInvokerFunction generates the JS invoker function for each function exposed to JS through embind. +function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cppTargetFunc) { + // humanName: a human-readable string name for the function to be generated. + // argTypes: An array that contains the embind type objects for all types in the function signature. + // argTypes[0] is the type object for the function return value. + // argTypes[1] is the type object for function this object/class type, or null if not crafting an invoker for a class method. + // argTypes[2...] are the actual function parameters. + // classType: The embind type object for the class to be bound, or null if this is not a method of a class. + // cppInvokerFunc: JS Function object to the C++-side function that interops into C++ code. + // cppTargetFunc: Function pointer (an integer to FUNCTION_TABLE) to the target C++ function the cppInvokerFunc will end up calling. + var argCount = argTypes.length; + + if (argCount < 2) { + throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!"); + } + + var isClassMethodFunc = (argTypes[1] !== null && classType !== null); + + if (!isClassMethodFunc && !FUNCTION_TABLE[cppTargetFunc]) { + throwBindingError('Global function '+humanName+' is not defined!'); + } + + // Free functions with signature "void function()" do not need an invoker that marshalls between wire types. +// TODO: This omits argument count check - enable only at -O3 or similar. +// if (ENABLE_UNSAFE_OPTS && argCount == 2 && argTypes[0].name == "void" && !isClassMethodFunc) { +// return FUNCTION_TABLE[fn]; +// } + + var argsList = ""; + var argsListWired = ""; + for(var i = 0; i < argCount-2; ++i) { + argsList += (i!==0?", ":"")+"arg"+i; + argsListWired += (i!==0?", ":"")+"arg"+i+"Wired"; } - return createNamedFunction(makeLegalFunctionName(name), function() { - if (arguments.length !== argCount - 1) { - throwBindingError('function ' + name + ' called with ' + arguments.length + ' arguments, expected ' + (argCount - 1)); + + var invokerFnBody = + "return function "+makeLegalFunctionName(humanName)+"("+argsList+") {\n" + + "if (arguments.length !== "+(argCount - 2)+") {\n" + + "throwBindingError('function "+humanName+" called with ' + arguments.length + ' arguments, expected "+(argCount - 2)+" args!');\n" + + "}\n"; + + // Determine if we need to use a dynamic stack to store the destructors for the function parameters. + // TODO: Remove this completely once all function invokers are being dynamically generated. + var needsDestructorStack = false; + + for(var i = 1; i < argTypes.length; ++i) { // Skip return value at index 0 - it's not deleted here. + if (argTypes[i] !== null && argTypes[i].destructorFunction === undefined) { // The type does not define a destructor function - must use dynamic stack + needsDestructorStack = true; + break; } - var destructors = []; - var args = new Array(argCount); - args[0] = fn; - for (var i = 1; i < argCount; ++i) { - args[i] = argTypes[i].toWireType(destructors, arguments[i - 1]); + } + + if (needsDestructorStack) { + invokerFnBody += + "var destructors = [];\n"; + } + + var dtorStack = needsDestructorStack ? "destructors" : "null"; + var args1 = ["throwBindingError", "classType", "invoker", "fn", "runDestructors", "retType", "classParam"]; + var args2 = [throwBindingError, classType, cppInvokerFunc, cppTargetFunc, runDestructors, argTypes[0], argTypes[1]]; + + if (isClassMethodFunc) { + invokerFnBody += "var thisWired = classParam.toWireType("+dtorStack+", this);\n"; + } + + for(var i = 0; i < argCount-2; ++i) { + invokerFnBody += "var arg"+i+"Wired = argType"+i+".toWireType("+dtorStack+", arg"+i+"); // "+argTypes[i+2].name+"\n"; + args1.push("argType"+i); + args2.push(argTypes[i+2]); + } + + if (isClassMethodFunc) { + argsListWired = "thisWired" + (argsListWired.length > 0 ? ", " : "") + argsListWired; + } + + var returns = (argTypes[0].name !== "void"); + + invokerFnBody += + (returns?"var rv = ":"") + "invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n"; + + if (needsDestructorStack) { + invokerFnBody += "runDestructors(destructors);\n"; + } else { + for(var i = isClassMethodFunc?1:2; i < argTypes.length; ++i) { // Skip return value at index 0 - it's not deleted here. Also skip class type if not a method. + var paramName = (i === 1 ? "thisWired" : ("arg"+(i-2)+"Wired")); + if (argTypes[i].destructorFunction !== null) { + invokerFnBody += paramName+"_dtor("+paramName+"); // "+argTypes[i].name+"\n"; + args1.push(paramName+"_dtor"); + args2.push(argTypes[i].destructorFunction); + } } - var rv = invoker.apply(null, args); - rv = argTypes[0].fromWireType(rv); - runDestructors(destructors); - return rv; - }); + } + + if (returns) { + invokerFnBody += "return retType.fromWireType(rv);\n"; + } + invokerFnBody += "}\n"; + + args1.push(invokerFnBody); + + var invokerFunction = new_(Function, args1).apply(null, args2); + return invokerFunction; } function __embind_register_function(name, argCount, rawArgTypesAddr, rawInvoker, fn) { var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr); - name = Pointer_stringify(name); + name = readLatin1String(name); rawInvoker = FUNCTION_TABLE[rawInvoker]; exposePublicSymbol(name, function() { @@ -398,7 +600,8 @@ function __embind_register_function(name, argCount, rawArgTypesAddr, rawInvoker, }, argCount - 1); whenDependentTypesAreResolved([], argTypes, function(argTypes) { - replacePublicSymbol(name, makeInvoker(name, argCount, argTypes, rawInvoker, fn), argCount - 1); + var invokerArgsArray = [argTypes[0] /* return value */, null /* no class 'this'*/].concat(argTypes.slice(1) /* actual params */); + replacePublicSymbol(name, craftInvokerFunction(name, invokerArgsArray, null /* no class 'this'*/, rawInvoker, fn), argCount - 1); return []; }); } @@ -407,7 +610,7 @@ var tupleRegistrations = {}; function __embind_register_tuple(rawType, name, rawConstructor, rawDestructor) { tupleRegistrations[rawType] = { - name: Pointer_stringify(name), + name: readLatin1String(name), rawConstructor: FUNCTION_TABLE[rawConstructor], rawDestructor: FUNCTION_TABLE[rawDestructor], elements: [], @@ -453,18 +656,18 @@ function __embind_finalize_tuple(rawTupleType) { var setter = elt.setter; var setterContext = elt.setterContext; elt.read = function(ptr) { - return getterReturnType.fromWireType(getter(getterContext, ptr)); + return getterReturnType['fromWireType'](getter(getterContext, ptr)); }; elt.write = function(ptr, o) { var destructors = []; - setter(setterContext, ptr, setterArgumentType.toWireType(destructors, o)); + setter(setterContext, ptr, setterArgumentType['toWireType'](destructors, o)); runDestructors(destructors); }; }); return [{ name: reg.name, - fromWireType: function(ptr) { + 'fromWireType': function(ptr) { var rv = new Array(elementsLength); for (var i = 0; i < elementsLength; ++i) { rv[i] = elements[i].read(ptr); @@ -472,7 +675,7 @@ function __embind_finalize_tuple(rawTupleType) { rawDestructor(ptr); return rv; }, - toWireType: function(destructors, o) { + 'toWireType': function(destructors, o) { if (elementsLength !== o.length) { throw new TypeError("Incorrect number of tuple elements"); } @@ -480,9 +683,12 @@ function __embind_finalize_tuple(rawTupleType) { for (var i = 0; i < elementsLength; ++i) { elements[i].write(ptr, o[i]); } - destructors.push(rawDestructor, ptr); + if (destructors !== null) { + destructors.push(rawDestructor, ptr); + } return ptr; }, + destructorFunction: rawDestructor, }]; }); } @@ -496,7 +702,7 @@ function __embind_register_struct( rawDestructor ) { structRegistrations[rawType] = { - name: Pointer_stringify(name), + name: readLatin1String(name), rawConstructor: FUNCTION_TABLE[rawConstructor], rawDestructor: FUNCTION_TABLE[rawDestructor], fields: [], @@ -514,7 +720,7 @@ function __embind_register_struct_field( setterContext ) { structRegistrations[structType].fields.push({ - fieldName: Pointer_stringify(fieldName), + fieldName: readLatin1String(fieldName), getterReturnType: getterReturnType, getter: FUNCTION_TABLE[getter], getterContext: getterContext, @@ -545,12 +751,12 @@ function __embind_finalize_struct(structType) { var setterContext = field.setterContext; fields[fieldName] = { read: function(ptr) { - return getterReturnType.fromWireType( + return getterReturnType['fromWireType']( getter(getterContext, ptr)); }, write: function(ptr, o) { var destructors = []; - setter(setterContext, ptr, setterArgumentType.toWireType(destructors, o)); + setter(setterContext, ptr, setterArgumentType['toWireType'](destructors, o)); runDestructors(destructors); } }; @@ -558,7 +764,7 @@ function __embind_finalize_struct(structType) { return [{ name: reg.name, - fromWireType: function(ptr) { + 'fromWireType': function(ptr) { var rv = {}; for (var i in fields) { rv[i] = fields[i].read(ptr); @@ -566,7 +772,7 @@ function __embind_finalize_struct(structType) { rawDestructor(ptr); return rv; }, - toWireType: function(destructors, o) { + 'toWireType': function(destructors, o) { // todo: Here we have an opportunity for -O3 level "unsafe" optimizations: // assume all fields are present without checking. for (var fieldName in fields) { @@ -578,55 +784,17 @@ function __embind_finalize_struct(structType) { for (fieldName in fields) { fields[fieldName].write(ptr, o[fieldName]); } - destructors.push(rawDestructor, ptr); + if (destructors !== null) { + destructors.push(rawDestructor, ptr); + } return ptr; }, + destructorFunction: rawDestructor, }]; }); } -function RegisteredPointer( - name, - registeredClass, - isReference, - isConst, - - // smart pointer properties - isSmartPointer, - pointeeType, - sharingPolicy, - rawGetPointee, - rawConstructor, - rawShare, - rawDestructor -) { - this.name = name; - this.registeredClass = registeredClass; - this.isReference = isReference; - this.isConst = isConst; - - // smart pointer properties - this.isSmartPointer = isSmartPointer; - this.pointeeType = pointeeType; - this.sharingPolicy = sharingPolicy; - this.rawGetPointee = rawGetPointee; - this.rawConstructor = rawConstructor; - this.rawShare = rawShare; - this.rawDestructor = rawDestructor; -} - -RegisteredPointer.prototype.toWireType = function(destructors, handle) { - var self = this; - function throwCannotConvert() { - var name; - if (handle.$$.smartPtrType) { - name = handle.$$.smartPtrType.name; - } else { - name = handle.$$.ptrType.name; - } - throwBindingError('Cannot convert argument of type ' + name + ' to parameter type ' + self.name); - } - +var genericPointerToWireType = function(destructors, handle) { if (handle === null) { if (this.isReference) { |