aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChad Austin <chad@imvu.com>2013-04-01 15:21:08 -0700
committerJukka Jylänki <jujjyl@gmail.com>2013-04-12 14:26:57 +0300
commit8b1b35d8e34496a81967b2d08e2f7900111bba5e (patch)
treed78d0230d3b7747c727ad5330bc829f993ea35bb
parent92dee924425cb3ee1b7a266ab7a280f94baf33be (diff)
Move context generation/copying out of JavaScript and into C++, where we'll be able to do some cool things in the future.
-rwxr-xr-xsrc/embind/embind.js53
-rwxr-xr-xsystem/include/emscripten/bind.h167
2 files changed, 98 insertions, 122 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js
index e0abe6f1..f850c73f 100755
--- a/src/embind/embind.js
+++ b/src/embind/embind.js
@@ -386,26 +386,15 @@ function __embind_register_tuple(rawType, name, rawConstructor, rawDestructor) {
});
}
-function copyMemberPointer(memberPointer, memberPointerSize) {
- var copy = _malloc(memberPointerSize);
- if (!copy) {
- throw new Error('Failed to allocate member pointer copy');
- }
- _memcpy(copy, memberPointer, memberPointerSize);
- return copy;
-}
-
function __embind_register_tuple_element(
rawTupleType,
rawType,
getter,
setter,
- memberPointerSize,
- memberPointer
+ context
) {
getter = FUNCTION_TABLE[getter];
setter = FUNCTION_TABLE[setter];
- memberPointer = copyMemberPointer(memberPointer, memberPointerSize);
var tupleType = requireRegisteredType(rawTupleType, 'tuple');
var index = tupleType.elements.length;
@@ -416,11 +405,11 @@ function __embind_register_tuple_element(
type = type[0];
tupleType.elements[index] = {
read: function(ptr) {
- return type.fromWireType(getter(ptr, memberPointer));
+ return type.fromWireType(getter(context, ptr));
},
write: function(ptr, o) {
var destructors = [];
- setter(ptr, memberPointer, type.toWireType(destructors, o));
+ setter(context, ptr, type.toWireType(destructors, o));
runDestructors(destructors);
}
};
@@ -432,29 +421,27 @@ function __embind_register_tuple_element_accessor(
rawTupleType,
rawElementType,
rawStaticGetter,
- getterSize,
- getter,
+ getterContext,
rawStaticSetter,
- setterSize,
- setter
+ setterContext
) {
var tupleType = requireRegisteredType(rawTupleType, 'tuple');
rawStaticGetter = FUNCTION_TABLE[rawStaticGetter];
- getter = copyMemberPointer(getter, getterSize);
rawStaticSetter = FUNCTION_TABLE[rawStaticSetter];
- setter = copyMemberPointer(setter, setterSize);
whenDependentTypesAreResolved([], [rawElementType], function(elementType) {
elementType = elementType[0];
tupleType.elements.push({
read: function(ptr) {
- return elementType.fromWireType(rawStaticGetter(ptr, HEAP32[getter >> 2]));
+ return elementType.fromWireType(rawStaticGetter(
+ getterContext,
+ ptr));
},
write: function(ptr, o) {
var destructors = [];
rawStaticSetter(
+ setterContext,
ptr,
- HEAP32[setter >> 2],
elementType.toWireType(destructors, o));
runDestructors(destructors);
}
@@ -512,24 +499,22 @@ function __embind_register_struct_field(
rawFieldType,
rawGetter,
rawSetter,
- memberPointerSize,
- memberPointer
+ context
) {
var structType = requireRegisteredType(rawStructType, 'struct');
fieldName = Pointer_stringify(fieldName);
rawGetter = FUNCTION_TABLE[rawGetter];
rawSetter = FUNCTION_TABLE[rawSetter];
- memberPointer = copyMemberPointer(memberPointer, memberPointerSize);
// TODO: test incomplete registration of value structs
whenDependentTypesAreResolved([], [rawFieldType], function(fieldType) {
fieldType = fieldType[0];
structType.fields[fieldName] = {
read: function(ptr) {
- return fieldType.fromWireType(rawGetter(ptr, memberPointer));
+ return fieldType.fromWireType(rawGetter(context, ptr));
},
write: function(ptr, o) {
var destructors = [];
- rawSetter(ptr, memberPointer, fieldType.toWireType(destructors, o));
+ rawSetter(context, ptr, fieldType.toWireType(destructors, o));
runDestructors(destructors);
}
};
@@ -989,13 +974,11 @@ function __embind_register_class_function(
argCount,
rawArgTypesAddr, // [ReturnType, ThisType, Args...]
rawInvoker,
- memberFunctionSize,
- memberFunction
+ context
) {
var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
methodName = Pointer_stringify(methodName);
rawInvoker = FUNCTION_TABLE[rawInvoker];
- memberFunction = copyMemberPointer(memberFunction, memberFunctionSize);
whenDependentTypesAreResolved([], [rawClassType], function(classType) {
classType = classType[0];
@@ -1015,7 +998,7 @@ function __embind_register_class_function(
var destructors = [];
var args = new Array(argCount + 1);
- args[0] = memberFunction;
+ args[0] = context;
args[1] = argTypes[1].toWireType(destructors, this);
for (var i = 2; i < argCount; ++i) {
args[i] = argTypes[i].toWireType(destructors, arguments[i - 2]);
@@ -1064,13 +1047,11 @@ function __embind_register_class_property(
rawFieldType,
getter,
setter,
- memberPointerSize,
- memberPointer
+ context
) {
fieldName = Pointer_stringify(fieldName);
getter = FUNCTION_TABLE[getter];
setter = FUNCTION_TABLE[setter];
- memberPointer = copyMemberPointer(memberPointer, memberPointerSize);
whenDependentTypesAreResolved([], [rawClassType], function(classType) {
classType = classType[0];
var humanName = classType.name + '.' + fieldName;
@@ -1091,12 +1072,12 @@ function __embind_register_class_property(
Object.defineProperty(classType.registeredClass.instancePrototype, fieldName, {
get: function() {
var ptr = validateThis(this, classType, humanName + ' getter');
- return fieldType.fromWireType(getter(ptr, memberPointer));
+ return fieldType.fromWireType(getter(context, ptr));
},
set: function(v) {
var ptr = validateThis(this, classType, humanName + ' setter');
var destructors = [];
- setter(ptr, memberPointer, fieldType.toWireType(destructors, v));
+ setter(context, ptr, fieldType.toWireType(destructors, v));
runDestructors(destructors);
},
enumerable: true
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h
index 211c67c0..947f0b30 100755
--- a/system/include/emscripten/bind.h
+++ b/system/include/emscripten/bind.h
@@ -73,18 +73,15 @@ namespace emscripten {
TYPEID elementType,
GenericFunction getter,
GenericFunction setter,
- size_t memberPointerSize,
- void* memberPointer);
+ void* context);
void _embind_register_tuple_element_accessor(
TYPEID tupleType,
TYPEID elementType,
GenericFunction staticGetter,
- size_t getterSize,
- void* getter,
+ void* getterContext,
GenericFunction staticSetter,
- size_t setterSize,
- void* setter);
+ void* setterContext);
void _embind_register_struct(
TYPEID structType,
@@ -98,8 +95,7 @@ namespace emscripten {
TYPEID fieldType,
GenericFunction getter,
GenericFunction setter,
- size_t memberPointerSize,
- void* memberPointer);
+ void* context);
void _embind_register_smart_ptr(
TYPEID pointerType,
@@ -135,8 +131,7 @@ namespace emscripten {
unsigned argCount,
TYPEID argTypes[],
GenericFunction invoker,
- size_t memberFunctionSize,
- void* memberFunction);
+ void* context);
void _embind_register_class_property(
TYPEID classType,
@@ -144,8 +139,7 @@ namespace emscripten {
TYPEID fieldType,
GenericFunction getter,
GenericFunction setter,
- size_t memberPointerSize,
- void* memberPointer);
+ void* context);
void _embind_register_class_class_function(
TYPEID classType,
@@ -354,15 +348,15 @@ namespace emscripten {
typedef typename MemberBinding::WireType WireType;
static WireType getWire(
- const ClassType& ptr,
- const MemberPointer& field
+ const MemberPointer& field,
+ const ClassType& ptr
) {
return MemberBinding::toWireType(ptr.*field);
}
static void setWire(
- ClassType& ptr,
const MemberPointer& field,
+ ClassType& ptr,
WireType value
) {
ptr.*field = MemberBinding::fromWireType(value);
@@ -370,22 +364,31 @@ namespace emscripten {
template<typename Getter>
static WireType propertyGet(
- const ClassType& ptr,
- const Getter& getter
+ const Getter& getter,
+ const ClassType& ptr
) {
return MemberBinding::toWireType(getter(ptr));
}
template<typename Setter>
static void propertySet(
- ClassType& ptr,
const Setter& setter,
+ ClassType& ptr,
WireType value
) {
setter(ptr, MemberBinding::fromWireType(value));
}
};
+ // TODO: This could do a reinterpret-cast if sizeof(T) === sizeof(void*)
+ template<typename T>
+ inline void* getContext(const T& t) {
+ // not a leak because this is called once per binding
+ void* p = malloc(sizeof(T));
+ assert(p);
+ memcpy(p, &t, sizeof(T));
+ return p;
+ }
}
////////////////////////////////////////////////////////////////////////////////
@@ -396,79 +399,75 @@ namespace emscripten {
class value_tuple {
public:
value_tuple(const char* name) {
- internal::_embind_register_tuple(
- internal::TypeID<ClassType>::get(),
+ using namespace internal;
+ _embind_register_tuple(
+ TypeID<ClassType>::get(),
name,
- reinterpret_cast<internal::GenericFunction>(&internal::raw_constructor<ClassType>),
- reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<ClassType>));
+ reinterpret_cast<GenericFunction>(&raw_constructor<ClassType>),
+ reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>));
}
template<typename ElementType>
value_tuple& element(ElementType ClassType::*field) {
- internal::_embind_register_tuple_element(
- internal::TypeID<ClassType>::get(),
- internal::TypeID<ElementType>::get(),
- reinterpret_cast<internal::GenericFunction>(&internal::MemberAccess<ClassType, ElementType>::getWire),
- reinterpret_cast<internal::GenericFunction>(&internal::MemberAccess<ClassType, ElementType>::setWire),
- sizeof(field),
- &field);
-
+ using namespace internal;
+ _embind_register_tuple_element(
+ TypeID<ClassType>::get(),
+ TypeID<ElementType>::get(),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, ElementType>::getWire),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, ElementType>::setWire),
+ getContext(field));
return *this;
}
template<typename ElementType>
value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, ElementType)) {
- internal::_embind_register_tuple_element_accessor(
- internal::TypeID<ClassType>::get(),
- internal::TypeID<ElementType>::get(),
- reinterpret_cast<internal::GenericFunction>(&internal::MemberAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>),
- sizeof(getter),
- &getter,
- reinterpret_cast<internal::GenericFunction>(&internal::MemberAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>),
- sizeof(setter),
- &setter);
+ using namespace internal;
+ _embind_register_tuple_element_accessor(
+ TypeID<ClassType>::get(),
+ TypeID<ElementType>::get(),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, ElementType>::template propertyGet<ElementType(*)(const ClassType&)>),
+ getContext(getter),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, ElementType>::template propertySet<void(*)(ClassType&, ElementType)>),
+ getContext(setter));
return *this;
}
template<typename ElementType>
value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, const ElementType&)) {
- internal::_embind_register_tuple_element_accessor(
- internal::TypeID<ClassType>::get(),
- internal::TypeID<ElementType>::get(),
- reinterpret_cast<internal::GenericFunction>(&internal::MemberAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>),
- sizeof(getter),
- &getter,
- reinterpret_cast<internal::GenericFunction>(&internal::MemberAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>),
- sizeof(setter),
- &setter);
+ using namespace internal;
+ _embind_register_tuple_element_accessor(
+ TypeID<ClassType>::get(),
+ TypeID<ElementType>::get(),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, ElementType>::template propertyGet<ElementType(*)(const ClassType&)>),
+ getContext(getter),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, ElementType>::template propertySet<void(*)(ClassType&, ElementType)>),
+ getContext(setter));
return *this;
}
template<typename ElementType>
value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, const ElementType&&)) {
- internal::_embind_register_tuple_element_accessor(
- internal::TypeID<ClassType>::get(),
- internal::TypeID<ElementType>::get(),
- reinterpret_cast<internal::GenericFunction>(&internal::MemberAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>),
- sizeof(getter),
- &getter,
- reinterpret_cast<internal::GenericFunction>(&internal::MemberAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>),
- sizeof(setter),
- &setter);
+ using namespace internal;
+ _embind_register_tuple_element_accessor(
+ TypeID<ClassType>::get(),
+ TypeID<ElementType>::get(),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, ElementType>::template propertyGet<ElementType(*)(const ClassType&)>),
+ getContext(getter),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, ElementType>::template propertySet<void(*)(ClassType&, ElementType)>),
+ getContext(setter));
return *this;
}
template<typename ElementType>
value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, ElementType&)) {
- internal::_embind_register_tuple_element_accessor(
- internal::TypeID<ClassType>::get(),
- internal::TypeID<ElementType>::get(),
- reinterpret_cast<internal::GenericFunction>(&internal::MemberAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>),
- sizeof(getter),
- &getter,
- reinterpret_cast<internal::GenericFunction>(&internal::MemberAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>),
- sizeof(setter),
- &setter);
+ using namespace internal;
+ _embind_register_tuple_element_accessor(
+ TypeID<ClassType>::get(),
+ TypeID<ElementType>::get(),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, ElementType>::template propertyGet<ElementType(*)(const ClassType&)>),
+ getContext(getter),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, ElementType>::template propertySet<void(*)(ClassType&, ElementType)>),
+ getContext(setter));
return *this;
}
};
@@ -481,24 +480,24 @@ namespace emscripten {
class value_struct {
public:
value_struct(const char* name) {
- internal::_embind_register_struct(
- internal::TypeID<ClassType>::get(),
+ using namespace internal;
+ _embind_register_struct(
+ TypeID<ClassType>::get(),
name,
- reinterpret_cast<internal::GenericFunction>(&internal::raw_constructor<ClassType>),
- reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<ClassType>));
+ reinterpret_cast<GenericFunction>(&raw_constructor<ClassType>),
+ reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>));
}
template<typename FieldType>
value_struct& field(const char* fieldName, FieldType ClassType::*field) {
- internal::_embind_register_struct_field(
- internal::TypeID<ClassType>::get(),
+ using namespace internal;
+ _embind_register_struct_field(
+ TypeID<ClassType>::get(),
fieldName,
- internal::TypeID<FieldType>::get(),
- reinterpret_cast<internal::GenericFunction>(&internal::MemberAccess<ClassType, FieldType>::getWire),
- reinterpret_cast<internal::GenericFunction>(&internal::MemberAccess<ClassType, FieldType>::setWire),
- sizeof(field),
- &field);
-
+ TypeID<FieldType>::get(),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::getWire),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::setWire),
+ getContext(field));
return *this;
}
};
@@ -783,8 +782,7 @@ namespace emscripten {
args.count,
args.types,
reinterpret_cast<GenericFunction>(&MethodInvoker<decltype(memberFunction), ReturnType, ClassType*, Args...>::invoke),
- sizeof(memberFunction),
- &memberFunction);
+ getContext(memberFunction));
return *this;
}
@@ -799,8 +797,7 @@ namespace emscripten {
args.count,
args.types,
reinterpret_cast<GenericFunction>(&MethodInvoker<decltype(memberFunction), ReturnType, const ClassType*, Args...>::invoke),
- sizeof(memberFunction),
- &memberFunction);
+ getContext(memberFunction));
return *this;
}
@@ -815,8 +812,7 @@ namespace emscripten {
args.count,
args.types,
reinterpret_cast<GenericFunction>(&FunctionInvoker<decltype(function), ReturnType, ThisType, Args...>::invoke),
- sizeof(function),
- &function);
+ getContext(function));
return *this;
}
@@ -830,8 +826,7 @@ namespace emscripten {
TypeID<FieldType>::get(),
reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::getWire),
reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::setWire),
- sizeof(field),
- &field);
+ getContext(field));
return *this;
}