Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: compiled/bindings.ipp

Issue 29384812: Issue 4127 - [emscripten] Convert subscription classes to C++ - Part 1 (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore
Patch Set: Use uint64_t for properties Created April 7, 2017, 7:12 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2017 eyeo GmbH 3 * Copyright (C) 2006-2017 eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 24 matching lines...) Expand all
35 35
36 namespace bindings_internal 36 namespace bindings_internal
37 { 37 {
38 typedef void* TYPEID; 38 typedef void* TYPEID;
39 39
40 enum class TypeCategory 40 enum class TypeCategory
41 { 41 {
42 UNKNOWN, 42 UNKNOWN,
43 VOID, 43 VOID,
44 INT, 44 INT,
45 INT64,
46 FLOAT,
45 DEPENDENT_STRING, 47 DEPENDENT_STRING,
46 OWNED_STRING, 48 OWNED_STRING,
47 STRING_REF, 49 STRING_REF,
48 CLASS_PTR 50 CLASS_PTR
49 }; 51 };
50 52
51 template<typename T> 53 template<typename T>
52 struct TypeInfo 54 struct TypeInfo
53 { 55 {
54 /* 56 /*
55 * Since TypeInfo is a templated type, in practice the compiler will define 57 * Since TypeInfo is a templated type, in practice the compiler will define
56 * a new type for each possible template parameter value. We use that fact 58 * a new type for each possible template parameter value. We use that fact
57 * to generate type identifiers: each of these TypeInfo types has a 59 * to generate type identifiers: each of these TypeInfo types has a
58 * different s_typeIDHelper member, so we use a pointer to that static 60 * different s_typeIDHelper member, so we use a pointer to that static
59 * variable as a type identifier - it will be different for each template 61 * variable as a type identifier - it will be different for each template
60 * parameter. 62 * parameter.
61 */ 63 */
62 static char s_typeIDHelper; 64 static char s_typeIDHelper;
63 constexpr operator TYPEID() const 65 constexpr operator TYPEID() const
64 { 66 {
65 return &s_typeIDHelper; 67 return &s_typeIDHelper;
66 } 68 }
67 69
68 constexpr operator TypeCategory() const 70 constexpr operator TypeCategory() const
69 { 71 {
70 if (std::is_void<T>()) 72 if (std::is_void<T>())
71 return TypeCategory::VOID; 73 return TypeCategory::VOID;
72 74
75 if (std::is_same<T, uint64_t>())
76 return TypeCategory::INT64;
77
73 if (std::is_integral<T>() || std::is_enum<T>()) 78 if (std::is_integral<T>() || std::is_enum<T>())
74 return TypeCategory::INT; 79 return TypeCategory::INT;
75 80
81 if (std::is_floating_point<T>())
82 return TypeCategory::FLOAT;
83
76 if (std::is_same<DependentString, T>() || std::is_same<const DependentStri ng, T>()) 84 if (std::is_same<DependentString, T>() || std::is_same<const DependentStri ng, T>())
77 return TypeCategory::DEPENDENT_STRING; 85 return TypeCategory::DEPENDENT_STRING;
78 86
79 if (std::is_same<OwnedString, T>() || std::is_same<const OwnedString, T>() ) 87 if (std::is_same<OwnedString, T>() || std::is_same<const OwnedString, T>() )
80 return TypeCategory::OWNED_STRING; 88 return TypeCategory::OWNED_STRING;
81 89
82 if (std::is_same<String&, T>() || std::is_same<const String&, T>() || 90 if (std::is_same<String&, T>() || std::is_same<const String&, T>() ||
83 std::is_same<DependentString&, T>()) 91 std::is_same<DependentString&, T>())
84 { 92 {
85 return TypeCategory::STRING_REF; 93 return TypeCategory::STRING_REF;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 instance_function(instance_function) 133 instance_function(instance_function)
126 { 134 {
127 name[0] = '\0'; 135 name[0] = '\0';
128 136
129 // The function parameter is a pointer to the function pointer. 137 // The function parameter is a pointer to the function pointer.
130 // Emscripten's "function pointers" are actually integers indicating the 138 // Emscripten's "function pointers" are actually integers indicating the
131 // position in the call table. 0 represents nullptr. 139 // position in the call table. 0 represents nullptr.
132 if (!*reinterpret_cast<int*>(function)) 140 if (!*reinterpret_cast<int*>(function))
133 return; 141 return;
134 142
143 char signature[256];
144 int pos = 0;
145 if (returnType == TypeCategory::DEPENDENT_STRING ||
146 returnType == TypeCategory::OWNED_STRING)
147 {
148 // Objects aren't really returned but passed as parameter. Note that
149 // this pointer might come before it but we don't care because both
150 // are integers (pointers) as far as Emscripten is concerned.
151 signature[pos++] = 'v';
152 signature[pos++] = 'i';
153 }
154 else if (returnType == TypeCategory::VOID)
155 signature[pos++] = 'v';
156 else if (returnType == TypeCategory::FLOAT)
157 signature[pos++] = 'd';
158 else if (returnType == TypeCategory::INT ||
159 returnType == TypeCategory::INT64 ||
160 returnType == TypeCategory::STRING_REF ||
161 returnType == TypeCategory::CLASS_PTR)
162 {
163 signature[pos++] = 'i';
164 }
165 else
166 throw std::runtime_error("Unexpected function return type");
167
168 if (instance_function)
169 {
170 // this pointer is an implicit parameter
171 signature[pos++] = 'i';
172 }
173
135 for (const auto& item : argTypes) 174 for (const auto& item : argTypes)
136 { 175 {
137 if (item != TypeCategory::INT && item != TypeCategory::STRING_REF && 176 if (item == TypeCategory::INT || item == TypeCategory::STRING_REF ||
138 item != TypeCategory::CLASS_PTR) 177 item == TypeCategory::CLASS_PTR)
139 { 178 {
179 signature[pos++] = 'i';
180 }
181 else if (item == TypeCategory::INT64)
182 {
183 signature[pos++] = 'i';
184 signature[pos++] = 'i';
185 }
186 else if (item == TypeCategory::FLOAT)
187 signature[pos++] = 'd';
188 else
140 throw std::runtime_error("Unexpected function argument type"); 189 throw std::runtime_error("Unexpected function argument type");
141 }
142 args.push_back(item); 190 args.push_back(item);
143 } 191 }
144 192
145 if (returnType != TypeCategory::VOID && returnType != TypeCategory::INT && 193 signature[pos] = 0;
hub 2017/04/10 15:30:09 Nowhere we check that pos doesn't overflow. Not ev
Wladimir Palant 2017/04/10 18:27:49 Indeed, this is unnecessary. This is bindings gene
146 returnType != TypeCategory::DEPENDENT_STRING &&
147 returnType != TypeCategory::OWNED_STRING &&
148 returnType != TypeCategory::STRING_REF &&
149 returnType != TypeCategory::CLASS_PTR)
150 {
151 throw std::runtime_error("Unexpected function return type");
152 }
153 194
154 effectiveArgs = args.size(); 195 get_function_name(function, signature);
155 effectiveReturnType = returnType;
156 if (instance_function)
157 effectiveArgs++;
158
159 if (returnType == TypeCategory::DEPENDENT_STRING ||
160 returnType == TypeCategory::OWNED_STRING)
161 {
162 effectiveArgs++;
163 effectiveReturnType = TypeCategory::VOID;
164 }
165
166 get_function_name(function, effectiveArgs,
167 effectiveReturnType == TypeCategory::VOID);
168 } 196 }
169 197
170 template<typename ReturnType, typename... Args> 198 template<typename ReturnType, typename... Args>
171 FunctionInfo(ReturnType (*function)(Args...)) 199 FunctionInfo(ReturnType (*function)(Args...))
172 : FunctionInfo(TypeInfo<ReturnType>(), 200 : FunctionInfo(TypeInfo<ReturnType>(),
173 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, false, 201 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, false,
174 &function) 202 &function)
175 { 203 {
176 } 204 }
177 205
(...skipping 11 matching lines...) Expand all
189 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, true, 217 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, true,
190 &function) 218 &function)
191 { 219 {
192 } 220 }
193 221
194 bool empty() const 222 bool empty() const
195 { 223 {
196 return name[0] == '\0'; 224 return name[0] == '\0';
197 } 225 }
198 226
199 void get_function_name(void* ptr, int numArgs, bool voidResult) 227 void get_function_name(void* ptr, char* signature)
200 { 228 {
201 // This is a hack, C++ won't let us get the mangled function name. 229 // This is a hack, C++ won't let us get the mangled function name.
202 // JavaScript is more dynamic so we pass the pointer to our function 230 // JavaScript is more dynamic so we pass the pointer to our function
203 // there. With that and the function signature we can call the function - 231 // there. With that and the function signature we can call the function -
204 // with a full stack so that we will cause it to abort. Sometimes the 232 // with a full stack so that we will cause it to abort. Sometimes the
205 // function we are calling will also be missing from the build. The result 233 // function we are calling will also be missing from the build. The result
206 // is the same: abort() is called which in turn calls stackTrace(). By 234 // is the same: abort() is called which in turn calls stackTrace(). By
207 // replacing stackTrace() we get access to the call stack and search it 235 // replacing stackTrace() we get access to the call stack and search it
208 // for the name of our function. 236 // for the name of our function.
209 237
210 EM_ASM_ARGS({ 238 EM_ASM_ARGS({
211 var signature = $3 ? "v" : "i"; 239 var signature = AsciiToString($2);
212 var args = []; 240 var args = [];
213 for (var i = 0; i < $2; i++) 241 for (var i = 1; i < signature.length; i++)
214 {
215 signature += "i";
216 args.push(0); 242 args.push(0);
217 }
218 243
219 var oldPrint = Module.print; 244 var oldPrint = Module.print;
220 var oldPrintErr = Module.printErr; 245 var oldPrintErr = Module.printErr;
221 var oldStackTrace = stackTrace; 246 var oldStackTrace = stackTrace;
222 var sp = Runtime.stackSave(); 247 var sp = Runtime.stackSave();
223 Module.print = function(){}; 248 Module.print = function(){};
224 Module.printErr = function(){}; 249 Module.printErr = function(){};
225 stackTrace = function() 250 stackTrace = function()
226 { 251 {
227 var stack = []; 252 var stack = [];
(...skipping 24 matching lines...) Expand all
252 { 277 {
253 Module.stringToAscii(e, $0); 278 Module.stringToAscii(e, $0);
254 } 279 }
255 finally 280 finally
256 { 281 {
257 Runtime.stackRestore(sp); 282 Runtime.stackRestore(sp);
258 Module.print = oldPrint; 283 Module.print = oldPrint;
259 Module.printErr = oldPrintErr; 284 Module.printErr = oldPrintErr;
260 stackTrace = oldStackTrace; 285 stackTrace = oldStackTrace;
261 } 286 }
262 }, name, ptr, numArgs, voidResult); 287 }, name, ptr, signature);
263 } 288 }
264 }; 289 };
265 290
266 class NoBaseClass 291 class NoBaseClass
267 { 292 {
268 }; 293 };
269 294
270 struct PropertyInfo 295 struct PropertyInfo
271 { 296 {
272 std::string name; 297 std::string name;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 for (int i = 0; i < params.size(); i++) 417 for (int i = 0; i < params.size(); i++)
393 { 418 {
394 if (i > 0) 419 if (i > 0)
395 call_str += ", "; 420 call_str += ", ";
396 call_str += params[i]; 421 call_str += params[i];
397 } 422 }
398 call_str += ")"; 423 call_str += ")";
399 424
400 if (call.returnType == TypeCategory::VOID) 425 if (call.returnType == TypeCategory::VOID)
401 return " " + call_str + ";\n"; 426 return " " + call_str + ";\n";
402 else if (call.returnType == TypeCategory::INT) 427 else if (call.returnType == TypeCategory::INT ||
428 call.returnType == TypeCategory::FLOAT)
429 {
403 return " var result = " + call_str + ";\n"; 430 return " var result = " + call_str + ";\n";
431 }
432 else if (call.returnType == TypeCategory::INT64)
433 {
434 // Emscripten saves the high bits of a 64-bit return value in a special
435 // variable called tempRet0. We cannot use bit operators to combine the
436 // values because JavaScript operates on 32-bit integers.
437 return " var result = (" + call_str + " >>> 0)" +
438 " + (Runtime.getTempRet0() >>> 0) * 0x100000000;\n";
439 }
404 else if (call.returnType == TypeCategory::DEPENDENT_STRING || 440 else if (call.returnType == TypeCategory::DEPENDENT_STRING ||
405 call.returnType == TypeCategory::OWNED_STRING) 441 call.returnType == TypeCategory::OWNED_STRING)
406 { 442 {
407 std::string result; 443 std::string result;
408 result += " var string = createString();\n"; 444 result += " var string = createString();\n";
409 result += " " + call_str + ";\n"; 445 result += " " + call_str + ";\n";
410 result += " var result = readString(string);\n"; 446 result += " var result = readString(string);\n";
411 if (call.returnType == TypeCategory::OWNED_STRING) 447 if (call.returnType == TypeCategory::OWNED_STRING)
412 result += " Module._DestroyString(string);\n"; 448 result += " Module._DestroyString(string);\n";
413 return result; 449 return result;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 std::string argName("arg" + std::to_string(i)); 493 std::string argName("arg" + std::to_string(i));
458 if (i > 0) 494 if (i > 0)
459 prefix += ", "; 495 prefix += ", ";
460 prefix += argName; 496 prefix += argName;
461 497
462 if (call.args[i] == TypeCategory::STRING_REF) 498 if (call.args[i] == TypeCategory::STRING_REF)
463 { 499 {
464 hasStringArgs = true; 500 hasStringArgs = true;
465 params.push_back(std::string("createString(") + argName + ")"); 501 params.push_back(std::string("createString(") + argName + ")");
466 } 502 }
503 else if (call.args[i] == TypeCategory::CLASS_PTR)
504 params.push_back(argName + "._pointer");
505 else if (call.args[i] == TypeCategory::INT64)
506 {
507 // 64-bit integers are passed as two integer parameters
508 params.push_back(argName + " >>> 0");
509 params.push_back(argName + " / 0x100000000 >>> 0");
510 }
467 else 511 else
468 params.push_back(argName); 512 params.push_back(argName);
469 } 513 }
470 prefix += ")\n{\n"; 514 prefix += ")\n{\n";
471 515
472 std::string suffix = "}"; 516 std::string suffix = "}";
473 if (call.returnType != TypeCategory::VOID) 517 if (call.returnType != TypeCategory::VOID)
474 suffix = " return result;\n" + suffix; 518 suffix = " return result;\n" + suffix;
475 519
476 if (call.returnType == TypeCategory::DEPENDENT_STRING || 520 if (call.returnType == TypeCategory::DEPENDENT_STRING ||
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 779
736 std::vector<std::pair<int, std::string>> mapping; 780 std::vector<std::pair<int, std::string>> mapping;
737 for (const auto& item : list) 781 for (const auto& item : list)
738 mapping.emplace_back(item.first, item.second); 782 mapping.emplace_back(item.first, item.second);
739 783
740 bindings_internal::register_differentiator( 784 bindings_internal::register_differentiator(
741 bindings_internal::TypeInfo<ClassType>(), offset, mapping); 785 bindings_internal::TypeInfo<ClassType>(), offset, mapping);
742 return *this; 786 return *this;
743 } 787 }
744 }; 788 };
OLDNEW
« compiled/String.h ('K') | « compiled/bindings.cpp ('k') | compiled/filter/Filter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld