-
Notifications
You must be signed in to change notification settings - Fork 3.4k
[Wasm64] Initial work for get parts of embind working #17239
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,7 @@ | |
|
||
// -- jshint doesn't understand library syntax, so we need to mark the symbols exposed here | ||
/*global getStringOrSymbol, emval_handle_array, Emval, __emval_unregister, count_emval_handles, emval_symbols, emval_free_list, get_first_emval, __emval_decref, emval_newers*/ | ||
/*global craftEmvalAllocator, __emval_addMethodCaller, emval_methodCallers, LibraryManager, mergeInto, __emval_allocateDestructors, global, __emval_lookupTypes, makeLegalFunctionName*/ | ||
/*global craftEmvalAllocator, emval_addMethodCaller, emval_methodCallers, LibraryManager, mergeInto, emval_allocateDestructors, global, emval_lookupTypes, makeLegalFunctionName*/ | ||
/*global emval_get_global*/ | ||
|
||
var LibraryEmVal = { | ||
|
@@ -261,7 +261,7 @@ var LibraryEmVal = { | |
})()('return this')(); | ||
}, | ||
#endif | ||
_emval_get_global__sig: 'ii', | ||
_emval_get_global__sig: 'pp', | ||
_emval_get_global__deps: ['$Emval', '$getStringOrSymbol', '$emval_get_global'], | ||
_emval_get_global: function(name) { | ||
if (name===0) { | ||
|
@@ -279,7 +279,7 @@ var LibraryEmVal = { | |
return Emval.toHandle(Module[name]); | ||
}, | ||
|
||
_emval_get_property__sig: 'iii', | ||
_emval_get_property__sig: 'ppp', | ||
_emval_get_property__deps: ['$Emval'], | ||
_emval_get_property: function(handle, key) { | ||
handle = Emval.toValue(handle); | ||
|
@@ -296,7 +296,7 @@ var LibraryEmVal = { | |
handle[key] = value; | ||
}, | ||
|
||
_emval_as__sig: 'iiii', | ||
_emval_as__sig: 'dppp', | ||
_emval_as__deps: ['$Emval', '$requireRegisteredType'], | ||
_emval_as: function(handle, returnType, destructorsRef) { | ||
handle = Emval.toValue(handle); | ||
|
@@ -308,58 +308,65 @@ var LibraryEmVal = { | |
}, | ||
|
||
_emval_as_int64__deps: ['$Emval', '$requireRegisteredType'], | ||
_emval_as_int64__sig: 'dppp', | ||
_emval_as_int64: function(handle, returnType, destructorsRef) { | ||
handle = Emval.toValue(handle); | ||
returnType = requireRegisteredType(returnType, 'emval::as'); | ||
return returnType['toWireType'](null, handle); | ||
}, | ||
|
||
_emval_as_uint64__deps: ['$Emval', '$requireRegisteredType'], | ||
_emval_as_uint64__sig: 'dppp', | ||
_emval_as_uint64: function(handle, returnType, destructorsRef) { | ||
handle = Emval.toValue(handle); | ||
returnType = requireRegisteredType(returnType, 'emval::as'); | ||
return returnType['toWireType'](null, handle); | ||
}, | ||
|
||
_emval_equals__deps: ['$Emval'], | ||
_emval_equals__sig: 'ipp', | ||
_emval_equals: function(first, second) { | ||
first = Emval.toValue(first); | ||
second = Emval.toValue(second); | ||
return first == second; | ||
}, | ||
|
||
_emval_strictly_equals__deps: ['$Emval'], | ||
_emval_strictly_equals__sig: 'ipp', | ||
_emval_strictly_equals: function(first, second) { | ||
first = Emval.toValue(first); | ||
second = Emval.toValue(second); | ||
return first === second; | ||
}, | ||
|
||
_emval_greater_than__deps: ['$Emval'], | ||
_emval_greater_than__sig: 'ipp', | ||
_emval_greater_than: function(first, second) { | ||
first = Emval.toValue(first); | ||
second = Emval.toValue(second); | ||
return first > second; | ||
}, | ||
|
||
_emval_less_than__deps: ['$Emval'], | ||
_emval_less_than__sig: 'ipp', | ||
_emval_less_than: function(first, second) { | ||
first = Emval.toValue(first); | ||
second = Emval.toValue(second); | ||
return first < second; | ||
}, | ||
|
||
_emval_not__deps: ['$Emval'], | ||
_emval_not__sig: 'ip', | ||
_emval_not: function(object) { | ||
object = Emval.toValue(object); | ||
return !object; | ||
}, | ||
|
||
_emval_call__sig: 'iiiii', | ||
_emval_call__deps: ['_emval_lookupTypes', '$Emval'], | ||
_emval_call__sig: 'ppppp', | ||
_emval_call__deps: ['$emval_lookupTypes', '$Emval'], | ||
_emval_call: function(handle, argCount, argTypes, argv) { | ||
handle = Emval.toValue(handle); | ||
var types = __emval_lookupTypes(argCount, argTypes); | ||
var types = emval_lookupTypes(argCount, argTypes); | ||
|
||
var args = new Array(argCount); | ||
for (var i = 0; i < argCount; ++i) { | ||
|
@@ -372,18 +379,18 @@ var LibraryEmVal = { | |
return Emval.toHandle(rv); | ||
}, | ||
|
||
_emval_lookupTypes__deps: ['$requireRegisteredType'], | ||
_emval_lookupTypes: function(argCount, argTypes) { | ||
$emval_lookupTypes__deps: ['$requireRegisteredType'], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what's the difference between the $-prefixed and the _-prefixed function names? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
$emval_lookupTypes: function(argCount, argTypes) { | ||
var a = new Array(argCount); | ||
for (var i = 0; i < argCount; ++i) { | ||
a[i] = requireRegisteredType(HEAP32[(argTypes >> 2) + i], | ||
a[i] = requireRegisteredType({{{ makeGetValue('argTypes', 'i * POINTER_SIZE', '*') }}}, | ||
"parameter " + i); | ||
} | ||
return a; | ||
}, | ||
|
||
_emval_allocateDestructors__deps: ['$Emval'], | ||
_emval_allocateDestructors: function(destructorsRef) { | ||
$emval_allocateDestructors__deps: ['$Emval'], | ||
$emval_allocateDestructors: function(destructorsRef) { | ||
var destructors = []; | ||
HEAP32[destructorsRef >> 2] = Emval.toHandle(destructors); | ||
return destructors; | ||
|
@@ -393,18 +400,18 @@ var LibraryEmVal = { | |
// to have null be a valid method caller. | ||
$emval_methodCallers: [undefined], | ||
|
||
_emval_addMethodCaller__deps: ['$emval_methodCallers'], | ||
_emval_addMethodCaller: function(caller) { | ||
$emval_addMethodCaller__deps: ['$emval_methodCallers'], | ||
$emval_addMethodCaller: function(caller) { | ||
var id = emval_methodCallers.length; | ||
emval_methodCallers.push(caller); | ||
return id; | ||
}, | ||
|
||
$emval_registeredMethods: [], | ||
_emval_get_method_caller__sig: 'iii', | ||
_emval_get_method_caller__deps: ['_emval_addMethodCaller', '_emval_lookupTypes', '$new_', '$makeLegalFunctionName', '$emval_registeredMethods'], | ||
_emval_get_method_caller__sig: 'ppp', | ||
_emval_get_method_caller__deps: ['$emval_addMethodCaller', '$emval_lookupTypes', '$new_', '$makeLegalFunctionName', '$emval_registeredMethods'], | ||
_emval_get_method_caller: function(argCount, argTypes) { | ||
var types = __emval_lookupTypes(argCount, argTypes); | ||
var types = emval_lookupTypes(argCount, argTypes); | ||
var retType = types[0]; | ||
var signatureName = retType.name + "_$" + types.slice(1).map(function (t) { return t.name; }).join("_") + "$"; | ||
var returnId = emval_registeredMethods[signatureName]; | ||
|
@@ -469,69 +476,76 @@ var LibraryEmVal = { | |
params.push(functionBody); | ||
var invokerFunction = new_(Function, params).apply(null, args); | ||
#endif | ||
returnId = __emval_addMethodCaller(invokerFunction); | ||
returnId = emval_addMethodCaller(invokerFunction); | ||
emval_registeredMethods[signatureName] = returnId; | ||
return returnId; | ||
}, | ||
|
||
_emval_call_method__deps: ['_emval_allocateDestructors', '$getStringOrSymbol', '$emval_methodCallers', '$Emval'], | ||
_emval_call_method__deps: ['$emval_allocateDestructors', '$getStringOrSymbol', '$emval_methodCallers', '$Emval'], | ||
_emval_call_method__sig: 'dppppp', | ||
_emval_call_method: function(caller, handle, methodName, destructorsRef, args) { | ||
caller = emval_methodCallers[caller]; | ||
handle = Emval.toValue(handle); | ||
methodName = getStringOrSymbol(methodName); | ||
return caller(handle, methodName, __emval_allocateDestructors(destructorsRef), args); | ||
return caller(handle, methodName, emval_allocateDestructors(destructorsRef), args); | ||
}, | ||
|
||
_emval_call_void_method__sig: 'viiii', | ||
_emval_call_void_method__deps: ['_emval_allocateDestructors', '$getStringOrSymbol', '$emval_methodCallers', '$Emval'], | ||
_emval_call_void_method__sig: 'vpppp', | ||
_emval_call_void_method__deps: ['$emval_allocateDestructors', '$getStringOrSymbol', '$emval_methodCallers', '$Emval'], | ||
_emval_call_void_method: function(caller, handle, methodName, args) { | ||
caller = emval_methodCallers[caller]; | ||
handle = Emval.toValue(handle); | ||
methodName = getStringOrSymbol(methodName); | ||
caller(handle, methodName, null, args); | ||
}, | ||
|
||
_emval_typeof__sig: 'ii', | ||
_emval_typeof__sig: 'pp', | ||
_emval_typeof__deps: ['$Emval'], | ||
_emval_typeof: function(handle) { | ||
handle = Emval.toValue(handle); | ||
return Emval.toHandle(typeof handle); | ||
}, | ||
|
||
_emval_instanceof__deps: ['$Emval'], | ||
_emval_instanceof__sig: 'ipp', | ||
_emval_instanceof: function(object, constructor) { | ||
object = Emval.toValue(object); | ||
constructor = Emval.toValue(constructor); | ||
return object instanceof constructor; | ||
}, | ||
|
||
_emval_is_number__deps: ['$Emval'], | ||
_emval_is_number__sig: 'ip', | ||
_emval_is_number: function(handle) { | ||
handle = Emval.toValue(handle); | ||
return typeof handle == 'number'; | ||
}, | ||
|
||
_emval_is_string__deps: ['$Emval'], | ||
_emval_is_string__sig: 'ip', | ||
_emval_is_string: function(handle) { | ||
handle = Emval.toValue(handle); | ||
return typeof handle == 'string'; | ||
}, | ||
|
||
_emval_in__deps: ['$Emval'], | ||
_emval_in__sig: 'ipp', | ||
_emval_in: function(item, object) { | ||
item = Emval.toValue(item); | ||
object = Emval.toValue(object); | ||
return item in object; | ||
}, | ||
|
||
_emval_delete__deps: ['$Emval'], | ||
_emval_delete__sig: 'ipp', | ||
_emval_delete: function(object, property) { | ||
object = Emval.toValue(object); | ||
property = Emval.toValue(property); | ||
return delete object[property]; | ||
}, | ||
|
||
_emval_throw__deps: ['$Emval'], | ||
_emval_throw__sig: 'vp', | ||
_emval_throw: function(object) { | ||
object = Emval.toValue(object); | ||
throw object; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ | |
#error Including <emscripten/val.h> requires building with -std=c++11 or newer! | ||
#endif | ||
|
||
#include <cassert> | ||
#include <array> | ||
#include <climits> | ||
#include <emscripten/wire.h> | ||
|
@@ -190,15 +191,14 @@ union GenericWireType { | |
union { | ||
unsigned u; | ||
float f; | ||
#if __ILP32__ | ||
const void* p; | ||
#endif | ||
// Use uint32_t for pointer values. This limits us, for now, to 32-bit | ||
// address ranges even on wasm64. This is enforced by assertions below. | ||
// TODO(sbc): Allow full 64-bit address range here under wasm64, most | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume if we updated this to 64-bit, we'd still want to use 53-bit ranges on the JS side though? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I think they are separate concerns. |
||
// likely by increasing the size of GenericWireType on wasm64. | ||
uint32_t p; | ||
} w[2]; | ||
double d; | ||
uint64_t u; | ||
#if __LP64__ | ||
const void* p; | ||
#endif | ||
}; | ||
static_assert(sizeof(GenericWireType) == 8, "GenericWireType must be 8 bytes"); | ||
static_assert(alignof(GenericWireType) == 8, "GenericWireType must be 8-byte-aligned"); | ||
|
@@ -225,29 +225,18 @@ inline void writeGenericWireType(GenericWireType*& cursor, uint64_t wt) { | |
|
||
template<typename T> | ||
void writeGenericWireType(GenericWireType*& cursor, T* wt) { | ||
#if __ILP32__ | ||
cursor->w[0].p = wt; | ||
#else | ||
cursor->p = wt; | ||
// FIXME: This requires the JS reading code to be audited to be compatible with it. | ||
assert(false); | ||
abort(); | ||
#endif | ||
uintptr_t short_ptr = reinterpret_cast<uintptr_t>(wt); | ||
assert(short_ptr <= UINT32_MAX); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this assert going to get compiled out in release builds? Should we maybe make it a "real" error, or is there some other code that will help the user if they happen to end up with a pointer outside this range? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its only going to fire for users of MEMORY64 + embind... which is hyper experiential config anyway, so I'm not too worried. |
||
cursor->w[0].p = short_ptr; | ||
++cursor; | ||
} | ||
|
||
template<typename ElementType> | ||
inline void writeGenericWireType(GenericWireType*& cursor, const memory_view<ElementType>& wt) { | ||
uintptr_t short_ptr = reinterpret_cast<uintptr_t>(wt.data); | ||
assert(short_ptr <= UINT32_MAX); | ||
cursor->w[0].u = wt.size; | ||
#if __ILP32__ | ||
cursor->w[1].p = wt.data; | ||
#else | ||
// FIXME: need to change GenericWireType such that it can store a 64-bit pointer? | ||
// This requires the JS reading code to be audited to be compatible with it. | ||
cursor->w[1].u = 0; | ||
assert(false); | ||
abort(); | ||
#endif | ||
cursor->w[1].p = short_ptr; | ||
++cursor; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's where I start asking
dumbbasic questions about JS libs.what happens when there's no signature on a JS lib function? What does adding them here accomplish?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a couple of different uses for these signatures.
In this case we need the signature so that we can generate automatic BigInt<->Number conversion wrapper at the boundary. The
p
here means pointer and is used for pointer/size_t things that we know assume won't exceed 53-bits..There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without these the JS code recieves BitInt values when running with MEMORY64.. which most of our JS code is not setup to receive.