diff options
author | Bill Welden <bwelden@imvu.com> | 2012-12-12 13:35:33 -0800 |
---|---|---|
committer | Jukka Jylänki <jujjyl@gmail.com> | 2013-04-12 14:22:33 +0300 |
commit | 50ba3a6ff9933cca9a3f1f893648162c9910d9fb (patch) | |
tree | 5cb5baa0abe411b04258ff90e1e06a5550957c68 | |
parent | 89299704617493eef217c68194053884e55a71f5 (diff) |
Benchmark work on pointer casting.
-rwxr-xr-x | src/embind/embind.js | 21 | ||||
-rwxr-xr-x | system/include/emscripten/bind.h | 4 | ||||
-rwxr-xr-x | system/lib/embind/bind.cpp | 60 |
3 files changed, 73 insertions, 12 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js index 5ceaf246..643ce728 100755 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -372,7 +372,7 @@ function __embind_register_smart_ptr( getPointee ) { name = Pointer_stringify(name); - pointeeType = requireRegisteredType(pointeeType, 'class'); + var pointeeTypeImpl = requireRegisteredType(pointeeType, 'class'); destructor = FUNCTION_TABLE[destructor]; getPointee = FUNCTION_TABLE[getPointee]; @@ -384,11 +384,11 @@ function __embind_register_smart_ptr( // TODO: test for SmartPtr.prototype.constructor property? // We likely want it distinct from pointeeType.prototype.constructor - Handle.prototype = Object.create(pointeeType.Handle.prototype); + Handle.prototype = Object.create(pointeeTypeImpl.Handle.prototype); Handle.prototype.clone = function() { if (!this.ptr) { - throw new BindingError(pointeeType.name + ' instance already deleted'); + throw new BindingError(pointeeTypeImpl.name + ' instance already deleted'); } var clone = Object.create(Handle.prototype); @@ -402,7 +402,7 @@ function __embind_register_smart_ptr( Handle.prototype['delete'] = function() { if (!this.ptr) { - throw new BindingError(pointeeType.name + ' instance already deleted'); + throw new BindingError(pointeeTypeImpl.name + ' instance already deleted'); } this.count.value -= 1; @@ -695,20 +695,21 @@ function __embind_register_class_method( }; } +/*global ___staticPointerCast: false*/ function __embind_register_cast_method( classType, methodName, returnType, invoker ) { - classType = requireRegisteredType(classType, 'class'); + var classTypeImpl = requireRegisteredType(classType, 'class'); methodName = Pointer_stringify(methodName); - var humanName = classType.name + '.' + methodName; + var humanName = classTypeImpl.name + '.' + methodName; - returnType = requireRegisteredType(returnType, 'method ' + humanName + ' return value'); + var returnTypeImpl = requireRegisteredType(returnType, 'method ' + humanName + ' return value'); invoker = FUNCTION_TABLE[invoker]; - classType.Handle.prototype[methodName] = function() { + classTypeImpl.Handle.prototype[methodName] = function() { if (!this.ptr) { throw new BindingError('cannot call emscripten binding method ' + humanName + ' on deleted object'); } @@ -718,7 +719,9 @@ function __embind_register_cast_method( var args = new Array(1); args[0] = this.ptr; - var rv = returnType.fromWireType(invoker.apply(null, args)); // in case ptr needs to be adjusted for multiple inheritance + var rv = returnTypeImpl.fromWireType(invoker.apply(null, args)); + rv.count = this.count; // the cast value shares the reference count of the original pointer, but does not increment it + this.count.value ++; return rv; }; } diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 48da7528..48a0fd58 100755 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -279,7 +279,7 @@ namespace emscripten { template<typename FromRawType, typename ToRawType> std::shared_ptr<ToRawType> performPointerCast(std::shared_ptr<FromRawType> from) { - return std::shared_ptr<ToRawType>(from, dynamic_cast<ToRawType*>(from.get())); + return std::shared_ptr<ToRawType>(from, static_cast<ToRawType*>(from.get())); }; template<typename ReturnType, typename... Args, typename... Policies> @@ -613,7 +613,7 @@ namespace emscripten { TypeID<PointerType>::get(), methodName, TypeID<ReturnType>::get(), - reinterpret_cast<GenericFunction>(&performPointerCast<PointeeType,ReturnPointeeType>)); + reinterpret_cast<GenericFunction>(&performPointerCast<PointeeType,ReturnPointeeType>)); return *this; } }; diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp index 9663ad51..de03052a 100755 --- a/system/lib/embind/bind.cpp +++ b/system/lib/embind/bind.cpp @@ -27,6 +27,21 @@ namespace __cxxabiv1 { return bases;
}
+ int __getBaseOffset(const __class_type_info* ctiDv, const __class_type_info* ctiBs) {
+ int offset = 0;
+
+ const __vmi_class_type_info* vcti = dynamic_cast<const __vmi_class_type_info*>(ctiDv);
+ if (vcti) {
+ for (int i = 0; i < vcti->__base_count; i++) {
+ if (vcti->__base_info[i].__base_type == ctiBs) {
+ offset = vcti->__base_info[i].__offset_flags >> __base_class_type_info::__offset_shift;
+ break;
+ }
+ }
+ }
+ return offset;
+ }
+
void __getDerivationPaths(const __class_type_info* dv, const __class_type_info* bs, std::vector<const __class_type_info*>path, std::vector<std::vector<const __class_type_info*>>& paths) {
std::vector<const __class_type_info*> newPath(path);
newPath.emplace_back(dv);
@@ -39,6 +54,14 @@ namespace __cxxabiv1 { }
}
}
+
+ int __pathOffset(std::vector<const __cxxabiv1::__class_type_info*> path) {
+ int offset = 0;
+ for (int i = 0; i < path.size()-1; i++) {
+ offset += __getBaseOffset(path[i], path[i+1]);
+ }
+ return offset;
+ }
}
namespace emscripten {
@@ -112,10 +135,45 @@ namespace emscripten { }
}
}
-
return derivationPath;
}
+ void* EMSCRIPTEN_KEEPALIVE __staticPointerCast(void* p, int dv, int bs) {
+ std::vector<std::vector<const __cxxabiv1::__class_type_info*>> paths;
+ int direction = 1;
+
+ const std::type_info* dv1 = (std::type_info*)dv;
+ const std::type_info* bs1 = (std::type_info*)bs;
+ const __cxxabiv1::__class_type_info* dv2 = dynamic_cast<const __cxxabiv1::__class_type_info*>(dv1);
+ const __cxxabiv1::__class_type_info* bs2 = dynamic_cast<const __cxxabiv1::__class_type_info*>(bs1);
+
+ if (dv2 && bs2) {
+ __cxxabiv1::__getDerivationPaths(dv2, bs2, std::vector<const __cxxabiv1::__class_type_info*>(), paths);
+ if (paths.size() == 0) {
+ __cxxabiv1::__getDerivationPaths(bs2, dv2, std::vector<const __cxxabiv1::__class_type_info*>(), paths);
+ direction = -1;
+ }
+ }
+
+ int offset = -1;
+ for (int i = 0; i < paths.size(); i++) {
+ if (offset < 0) {
+ offset = __cxxabiv1::__pathOffset(paths[i]);
+ } else {
+ if (offset != __cxxabiv1::__pathOffset(paths[i])) {
+ return (void *)-2; // ambiguous cast -- throw instead?
+ }
+ }
+ }
+ if (offset < 0) {
+ return (void *)-1; // types are not related -- throw instead?
+ }
+ if (p == 0) {
+ return (void *)0;
+ }
+ return (void *)((int)p + offset * direction);
+ }
+
// __getDynamicPointerType returns (for polymorphic types only!) the type of the instance actually
// pointed to.
int EMSCRIPTEN_KEEPALIVE __getDynamicPointerType(int p) {
|