 Issue 29431555:
  Issue 5216 - [emscripten] Use a more reliable way of retrieving mangled function name  (Closed) 
  Base URL: https://hg.adblockplus.org/adblockpluscore
    
  
    Issue 29431555:
  Issue 5216 - [emscripten] Use a more reliable way of retrieving mangled function name  (Closed) 
  Base URL: https://hg.adblockplus.org/adblockpluscore| Index: compiled/bindings/generator.cpp | 
| =================================================================== | 
| --- a/compiled/bindings/generator.cpp | 
| +++ b/compiled/bindings/generator.cpp | 
| @@ -12,19 +12,18 @@ | 
| * GNU General Public License for more details. | 
| * | 
| * You should have received a copy of the GNU General Public License | 
| * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 
| */ | 
| #include <cstdio> | 
| -#include <emscripten.h> | 
| - | 
| #include "generator.h" | 
| +#include "library.h" | 
| namespace | 
| { | 
| std::vector<bindings_internal::ClassInfo> classes; | 
| std::vector<bindings_internal::NamespaceInfo> namespaces; | 
| void printProperties(const bindings_internal::PropertyList& properties) | 
| { | 
| @@ -53,27 +52,24 @@ namespace | 
| printf("%s: %s,\n", method.name.c_str(), wrapCall(method.call).c_str()); | 
| } | 
| } | 
| namespace bindings_internal | 
| { | 
| FunctionInfo::FunctionInfo() | 
| { | 
| - name[0] = '\0'; | 
| } | 
| FunctionInfo::FunctionInfo(TypeCategory returnType, TYPEID pointerType, | 
| std::initializer_list<TypeCategory> argTypes, bool instance_function, | 
| void* function) | 
| : returnType(returnType), pointerType(pointerType), | 
| instance_function(instance_function) | 
| { | 
| - name[0] = '\0'; | 
| - | 
| // The function parameter is a pointer to the function pointer. | 
| // Emscripten's "function pointers" are actually integers indicating the | 
| // position in the call table. 0 represents nullptr. | 
| if (!*reinterpret_cast<int*>(function)) | 
| return; | 
| std::string signature; | 
| @@ -136,85 +132,24 @@ namespace bindings_internal | 
| signature += 'd'; | 
| break; | 
| default: | 
| throw std::runtime_error("Unexpected function argument type"); | 
| } | 
| args.push_back(type); | 
| } | 
| - get_function_name(function, signature.c_str()); | 
| + int nameLength = GetFunctionName(nullptr, function, signature.c_str()); | 
| + name.resize(nameLength); | 
| + GetFunctionName(name.data(), function, signature.c_str()); | 
| } | 
| bool FunctionInfo::empty() const | 
| { | 
| - return name[0] == '\0'; | 
| - } | 
| - | 
| - void FunctionInfo::get_function_name(void* ptr, const char* signature) | 
| - { | 
| - // This is a hack, C++ won't let us get the mangled function name. | 
| - // JavaScript is more dynamic so we pass the pointer to our function | 
| - // there. With that and the function signature we can call the function - | 
| - // with a full stack so that we will cause it to abort. Sometimes the | 
| - // function we are calling will also be missing from the build. The result | 
| - // is the same: abort() is called which in turn calls stackTrace(). By | 
| - // replacing stackTrace() we get access to the call stack and search it | 
| - // for the name of our function. | 
| - | 
| - EM_ASM_ARGS({ | 
| - var signature = AsciiToString($2); | 
| - var args = []; | 
| - for (var i = 1; i < signature.length; i++) | 
| - args.push(0); | 
| - | 
| - var oldPrint = Module.print; | 
| - var oldPrintErr = Module.printErr; | 
| - var oldStackTrace = stackTrace; | 
| - var sp = Runtime.stackSave(); | 
| - Module.print = function(){}; | 
| - Module.printErr = function(){}; | 
| - stackTrace = function() | 
| - { | 
| - var stack = []; | 
| - for (var f = arguments.callee.caller; f; f = f.caller) | 
| - { | 
| - if (f.name) | 
| - { | 
| - if (f.name.indexOf("dynCall") == 0) | 
| - break; | 
| - else | 
| - stack.push(f.name); | 
| - } | 
| - } | 
| - | 
| - result = stack[stack.length - 1]; | 
| - if (result && result.indexOf("__wrapper") >= 0) | 
| - result = stack[stack.length - 2]; | 
| - throw result; | 
| - }; | 
| - | 
| - Runtime.stackRestore(STACK_MAX); | 
| - | 
| - try | 
| - { | 
| - Runtime.dynCall(signature, HEAP32[$1 >> 2], args); | 
| - } | 
| - catch(e) | 
| - { | 
| - Module.stringToAscii(e, $0); | 
| - } | 
| - finally | 
| - { | 
| - Runtime.stackRestore(sp); | 
| - Module.print = oldPrint; | 
| - Module.printErr = oldPrintErr; | 
| - stackTrace = oldStackTrace; | 
| - } | 
| - }, name, ptr, signature); | 
| + return name.size() == 0; | 
| 
sergei
2017/05/08 10:58:19
name.empty() would be better.
 
Wladimir Palant
2017/05/08 11:41:34
Done.
 | 
| } | 
| ClassInfo* find_class(TYPEID classID) | 
| { | 
| for (auto& classInfo : classes) | 
| if (classInfo.id == classID) | 
| return &classInfo; | 
| return nullptr; | 
| @@ -376,31 +311,31 @@ namespace bindings_internal | 
| { | 
| std::string result; | 
| result += " var result = " + call_str + ";\n"; | 
| result += " if (result)\n"; | 
| result += " {\n"; | 
| const ClassInfo* cls = find_class(call.pointerType); | 
| if (!cls) | 
| - throw std::runtime_error("Function " + std::string(call.name) + " returns pointer to unknown class"); | 
| + throw std::runtime_error("Function " + call.name + " returns pointer to unknown class"); | 
| auto offset = cls->subclass_differentiator.offset; | 
| if (offset == SIZE_MAX) | 
| result += " result = exports." + cls->name + "(result);\n"; | 
| else | 
| result += " result = exports." + cls->name + ".fromPointer(result);\n"; | 
| result += " }\n"; | 
| result += " else\n"; | 
| result += " result = null;\n"; | 
| return result; | 
| } | 
| default: | 
| - throw std::runtime_error("Unexpected return type for " + std::string(call.name)); | 
| + throw std::runtime_error("Unexpected return type for " + call.name); | 
| } | 
| } | 
| std::string wrapCall(const FunctionInfo& call, bool isFunction) | 
| { | 
| bool hasStringArgs = false; | 
| std::vector<std::string> params; | 
| std::string prefix; |