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

Delta Between Two Patch Sets: compiled/bindings/generator.cpp

Issue 29426559: Issue 5137 - [emscripten] Added basic filter storage implementation (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore
Left Patch Set: Improved type names and added finally block Created May 8, 2017, 12:53 p.m.
Right Patch Set: Fixed bogus assert Created Aug. 31, 2017, 12:44 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « compiled/bindings/generator.h ('k') | compiled/bindings/main.cpp » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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-present 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
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 #include <cstdio> 18 #include <cstdio>
19 19
20 #include "generator.h" 20 #include "generator.h"
21 #include "library.h" 21 #include "library.h"
22 22
23 namespace 23 namespace
24 { 24 {
25 std::vector<bindings_internal::ClassInfo> classes; 25 std::vector<bindings_internal::ClassInfo> classes;
26 std::vector<bindings_internal::NamespaceInfo> namespaces;
27
28 void printProperties(const bindings_internal::Properties& properties)
29 {
30 for (const auto& property : properties)
31 {
32 if (property.jsValue.empty())
33 {
34 printf("get %s%s,\n", property.name.c_str(),
35 wrapCall(property.getter, false).c_str());
36 if (!property.setter.empty())
37 {
38 printf("set %s%s,\n", property.name.c_str(),
39 wrapCall(property.setter, false).c_str());
40 }
41 }
42 else
43 printf("%s: %s,\n", property.name.c_str(), property.jsValue.c_str());
44 }
45 }
46
47 void printMethods(const bindings_internal::Methods& methods,
48 bool instanceOnly = true)
49 {
50 for (const auto& method : methods)
51 if (!instanceOnly || method.call.instance_function)
52 printf("%s: %s,\n", method.name.c_str(), wrapCall(method.call).c_str());
53 }
54 } 26 }
55 27
56 namespace bindings_internal 28 namespace bindings_internal
57 { 29 {
58 FunctionInfo::FunctionInfo() 30 FunctionInfo::FunctionInfo()
59 { 31 {
60 } 32 }
61 33
62 FunctionInfo::FunctionInfo(TypeCategory returnType, TYPEID pointerType, 34 FunctionInfo::FunctionInfo(TypeCategory returnType, TYPEID pointerType,
63 std::initializer_list<TypeCategory> argTypes, bool instance_function, 35 std::initializer_list<TypeCategory> argTypes, bool instance_function,
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 121
150 ClassInfo* find_class(TYPEID classID) 122 ClassInfo* find_class(TYPEID classID)
151 { 123 {
152 for (auto& classInfo : classes) 124 for (auto& classInfo : classes)
153 if (classInfo.id == classID) 125 if (classInfo.id == classID)
154 return &classInfo; 126 return &classInfo;
155 return nullptr; 127 return nullptr;
156 } 128 }
157 129
158 void register_class(const char* name, TYPEID classID, TYPEID baseClassID, 130 void register_class(const char* name, TYPEID classID, TYPEID baseClassID,
159 ptrdiff_t ref_counted_offset) 131 ptrdiff_t ref_counted_offset,
132 const FunctionInfo& instanceGetter)
160 { 133 {
161 if (find_class(classID)) 134 if (find_class(classID))
162 throw std::runtime_error(std::string("Duplicate definition for class ") + name); 135 throw std::runtime_error(std::string("Duplicate definition for class ") + name);
163 136
164 if (baseClassID != TypeInfo<NoBaseClass>() && !find_class(baseClassID)) 137 if (baseClassID != TypeInfo<NoBaseClass>() && !find_class(baseClassID))
165 throw std::runtime_error(std::string("Unknown base class defined for class ") + name); 138 throw std::runtime_error(std::string("Unknown base class defined for class ") + name);
166 139
167 ClassInfo classInfo; 140 ClassInfo classInfo;
168 classInfo.id = classID; 141 classInfo.id = classID;
169 classInfo.baseClass = baseClassID; 142 classInfo.baseClass = baseClassID;
170 classInfo.name = name; 143 classInfo.name = name;
171 classInfo.subclass_differentiator.offset = SIZE_MAX; 144 classInfo.subclass_differentiator.offset = SIZE_MAX;
172 classInfo.ref_counted_offset = ref_counted_offset; 145 classInfo.ref_counted_offset = ref_counted_offset;
146 classInfo.instanceGetter = instanceGetter;
173 classes.push_back(classInfo); 147 classes.push_back(classInfo);
174 } 148 }
175 149
176 void register_property(TYPEID classID, const char* name, 150 void register_property(TYPEID classID, const char* name,
177 const FunctionInfo& getter, const FunctionInfo& setter, 151 const FunctionInfo& getter, const FunctionInfo& setter,
178 const char* jsValue) 152 const char* jsValue)
179 { 153 {
180 ClassInfo* classInfo = find_class(classID); 154 ClassInfo* classInfo = find_class(classID);
181 if (!classInfo) 155 if (!classInfo)
182 throw std::runtime_error(std::string("Property defined on unknown class: " ) + name); 156 throw std::runtime_error(std::string("Property defined on unknown class: " ) + name);
(...skipping 26 matching lines...) Expand all
209 if (!classInfo) 183 if (!classInfo)
210 throw std::runtime_error("Subclass differentiator defined on unknown class "); 184 throw std::runtime_error("Subclass differentiator defined on unknown class ");
211 185
212 if (classInfo->subclass_differentiator.offset != SIZE_MAX) 186 if (classInfo->subclass_differentiator.offset != SIZE_MAX)
213 throw std::runtime_error("More than one subclass differentiator defined fo r class " + classInfo->name); 187 throw std::runtime_error("More than one subclass differentiator defined fo r class " + classInfo->name);
214 188
215 DifferentiatorInfo differentiatorInfo; 189 DifferentiatorInfo differentiatorInfo;
216 differentiatorInfo.offset = offset; 190 differentiatorInfo.offset = offset;
217 differentiatorInfo.mapping = mapping; 191 differentiatorInfo.mapping = mapping;
218 classInfo->subclass_differentiator = differentiatorInfo; 192 classInfo->subclass_differentiator = differentiatorInfo;
219 }
220
221 NamespaceInfo* find_namespace(const char* namespaceName)
222 {
223 for (auto& namespaceInfo : namespaces)
224 if (namespaceInfo.name == namespaceName)
225 return &namespaceInfo;
226 return nullptr;
227 }
228
229 void register_namespace(const char* name)
230 {
231 if (find_namespace(name))
232 throw std::runtime_error(std::string("Duplicate definition for namespace " ) + name);
233
234 NamespaceInfo namespaceInfo;
235 namespaceInfo.name = name;
236 namespaces.push_back(namespaceInfo);
237 }
238
239 void register_namespace_property(const char* namespaceName, const char* name,
240 const FunctionInfo& getter, const FunctionInfo& setter)
241 {
242 NamespaceInfo* namespaceInfo = find_namespace(namespaceName);
243 if (!namespaceInfo)
244 throw std::runtime_error(std::string("Property defined on unknown namespac e: ") + name);
245
246 PropertyInfo propertyInfo;
247 propertyInfo.name = name;
248 propertyInfo.getter = getter;
249 propertyInfo.setter = setter;
250 namespaceInfo->properties.push_back(propertyInfo);
251 }
252
253 void register_namespace_method(const char* namespaceName, const char* name,
254 const FunctionInfo& call)
255 {
256 NamespaceInfo* namespaceInfo = find_namespace(namespaceName);
257 if (!namespaceInfo)
258 throw std::runtime_error(std::string("Method defined on unknown namespace: ") + name);
259
260 MethodInfo methodInfo;
261 methodInfo.name = name;
262 methodInfo.call = call;
263 namespaceInfo->methods.push_back(methodInfo);
264 } 193 }
265 194
266 std::string generateCall(const FunctionInfo& call, 195 std::string generateCall(const FunctionInfo& call,
267 std::vector<std::string>& params) 196 std::vector<std::string>& params)
268 { 197 {
269 if (call.returnType == TypeCategory::DEPENDENT_STRING || 198 if (call.returnType == TypeCategory::DEPENDENT_STRING ||
270 call.returnType == TypeCategory::OWNED_STRING) 199 call.returnType == TypeCategory::OWNED_STRING)
271 { 200 {
272 params.insert(params.begin(), "string"); 201 params.insert(params.begin(), "string");
273 } 202 }
(...skipping 14 matching lines...) Expand all
288 return " " + call_str + ";\n"; 217 return " " + call_str + ";\n";
289 case TypeCategory::INT: 218 case TypeCategory::INT:
290 case TypeCategory::FLOAT: 219 case TypeCategory::FLOAT:
291 case TypeCategory::DOUBLE: 220 case TypeCategory::DOUBLE:
292 return " var result = " + call_str + ";\n"; 221 return " var result = " + call_str + ";\n";
293 case TypeCategory::INT64: 222 case TypeCategory::INT64:
294 return " var result = Runtime.makeBigInt(" + call_str + ", " + 223 return " var result = Runtime.makeBigInt(" + call_str + ", " +
295 "Runtime.getTempRet0(), " + 224 "Runtime.getTempRet0(), " +
296 "true);\n"; 225 "true);\n";
297 case TypeCategory::DEPENDENT_STRING: 226 case TypeCategory::DEPENDENT_STRING:
298 case TypeCategory::OWNED_STRING:
299 { 227 {
300 std::string result; 228 std::string result;
301 result += " var string = createString();\n"; 229 result += " var string = createString();\n";
302 result += " " + call_str + ";\n"; 230 result += " " + call_str + ";\n";
303 result += " var result = readString(string);\n"; 231 result += " var result = readString(string);\n";
304 if (call.returnType == TypeCategory::OWNED_STRING) 232 // We don't call a destructor here because we know that dependent
305 result += " Module._DestroyString(string);\n"; 233 // strings don't need to clean up.
234 return result;
235 }
236 case TypeCategory::OWNED_STRING:
237 {
238 std::string result;
239 result += " var string = createOwnedString();\n";
240 result += " " + call_str + ";\n";
241 result += " var result = readString(string);\n";
242 result += " Module._DestroyString(string);\n";
306 return result; 243 return result;
307 } 244 }
308 case TypeCategory::STRING_REF: 245 case TypeCategory::STRING_REF:
309 return " var result = readString(" + call_str + ");\n"; 246 return " var result = readString(" + call_str + ");\n";
310 case TypeCategory::CLASS_PTR: 247 case TypeCategory::CLASS_PTR:
311 { 248 {
312 std::string result; 249 std::string result;
313 result += " var result = " + call_str + ";\n"; 250 result += " var result = " + call_str + ";\n";
314 result += " if (result)\n"; 251 result += " if (result)\n";
315 result += " {\n";
316 252
317 const ClassInfo* cls = find_class(call.pointerType); 253 const ClassInfo* cls = find_class(call.pointerType);
318 if (!cls) 254 if (!cls)
319 throw std::runtime_error("Function " + call.name + " returns pointer t o unknown class"); 255 throw std::runtime_error("Function " + call.name + " returns pointer t o unknown class");
320 256
321 auto offset = cls->subclass_differentiator.offset; 257 auto offset = cls->subclass_differentiator.offset;
322 if (offset == SIZE_MAX) 258 if (offset == SIZE_MAX)
323 result += " result = exports." + cls->name + "(result);\n"; 259 result += " result = exports." + cls->name + "(result);\n";
324 else 260 else
325 result += " result = exports." + cls->name + ".fromPointer(result); \n"; 261 result += " result = exports." + cls->name + ".fromPointer(result); \n";
326 262
327 result += " }\n";
328 result += " else\n"; 263 result += " else\n";
329 result += " result = null;\n"; 264 result += " result = null;\n";
330 return result; 265 return result;
331 } 266 }
332 default: 267 default:
333 throw std::runtime_error("Unexpected return type for " + call.name); 268 throw std::runtime_error("Unexpected return type for " + call.name);
334 } 269 }
335 } 270 }
336 271
337 std::string wrapCall(const FunctionInfo& call, bool isFunction) 272 std::string wrapCall(const FunctionInfo& call, bool isFunction,
273 const FunctionInfo& instanceGetter)
338 { 274 {
339 bool hasStringArgs = false; 275 bool hasStringArgs = false;
340 std::vector<std::string> params; 276 std::vector<std::string> params;
341 std::string prefix; 277 std::string prefix;
342 278
343 if (isFunction) 279 if (isFunction)
344 prefix += "function"; 280 prefix += "function";
345 prefix += "("; 281 prefix += "(";
346 for (int i = 0; i < call.args.size(); i++) 282 for (int i = 0; i < call.args.size(); i++)
347 { 283 {
(...skipping 25 matching lines...) Expand all
373 suffix = " return result;\n" + suffix; 309 suffix = " return result;\n" + suffix;
374 310
375 if (call.returnType == TypeCategory::DEPENDENT_STRING || 311 if (call.returnType == TypeCategory::DEPENDENT_STRING ||
376 call.returnType == TypeCategory::OWNED_STRING || hasStringArgs) 312 call.returnType == TypeCategory::OWNED_STRING || hasStringArgs)
377 { 313 {
378 prefix += " var sp = Runtime.stackSave();\n"; 314 prefix += " var sp = Runtime.stackSave();\n";
379 suffix = " Runtime.stackRestore(sp);\n" + suffix; 315 suffix = " Runtime.stackRestore(sp);\n" + suffix;
380 } 316 }
381 317
382 if (call.instance_function) 318 if (call.instance_function)
383 params.insert(params.begin(), "this._pointer"); 319 {
320 if (instanceGetter.empty())
321 params.insert(params.begin(), "this._pointer");
322 else
323 params.insert(params.begin(), instanceGetter.name + "()");
324 }
384 325
385 return prefix + generateCall(call, params) + suffix; 326 return prefix + generateCall(call, params) + suffix;
386 } 327 }
387 328
388 void printHelpers() 329 void printHelpers()
389 { 330 {
390 printf("var sizeofString = %i;\n", sizeof(String)); 331 printf("var sizeofString = %i;\n", sizeof(String));
391 332
392 puts(R"( 333 puts(R"(
393 function copyString(str, buffer) 334 function copyString(str, buffer)
394 { 335 {
395 var length = str.length; 336 var length = str.length;
396 for (var i = 0, pointer = (buffer >> 1); i < length; i++, pointer++) 337 for (var i = 0, pointer = (buffer >> 1); i < length; i++, pointer++)
397 HEAP16[pointer] = str.charCodeAt(i); 338 HEAP16[pointer] = str.charCodeAt(i);
398 return length; 339 return length;
399 } 340 }
400 341
401 function createString(str) 342 function createString(str)
402 { 343 {
403 var length = 0; 344 var length = 0;
404 var buffer = 0; 345 var buffer = 0;
405 if (str) 346 if (str)
406 { 347 {
407 buffer = Runtime.stackAlloc(str.length * 2); 348 buffer = Runtime.stackAlloc(str.length * 2);
408 length = copyString(str, buffer); 349 length = copyString(str, buffer);
409 } 350 }
410 351
411 var result = Runtime.stackAlloc(sizeofString); 352 var result = Runtime.stackAlloc(sizeofString);
412 Module._InitString(result, buffer, length); 353 Module._InitString(result, buffer, length);
354 return result;
355 }
356
357 function createOwnedString()
358 {
359 var result = Runtime.stackAlloc(sizeofString);
360 Module._InitOwnedString(result);
413 return result; 361 return result;
414 } 362 }
415 363
416 function readString(str) 364 function readString(str)
417 { 365 {
418 var length = Module._GetStringLength(str); 366 var length = Module._GetStringLength(str);
419 var pointer = Module._GetStringData(str) >> 1; 367 var pointer = Module._GetStringData(str) >> 1;
420 return String.fromCharCode.apply(String, HEAP16.slice(pointer, pointer + length)); 368 return String.fromCharCode.apply(String, HEAP16.slice(pointer, pointer + length));
421 } 369 }
422 370
(...skipping 10 matching lines...) Expand all
433 Module._ReleaseRef(this._pointer + ref_counted_offset); 381 Module._ReleaseRef(this._pointer + ref_counted_offset);
434 }; 382 };
435 return result; 383 return result;
436 } 384 }
437 )"); 385 )");
438 } 386 }
439 387
440 void printClass(const ClassInfo& cls) 388 void printClass(const ClassInfo& cls)
441 { 389 {
442 // Begin class definition 390 // Begin class definition
443 ClassInfo* baseClass = find_class(cls.baseClass); 391 bool singleton = !cls.instanceGetter.empty();
444 printf("exports.%s = createClass(%s, %i, {\n", cls.name.c_str(), 392 if (singleton)
445 (baseClass ? ("exports." + baseClass->name).c_str() : "null"), 393 printf("exports.%s = {\n", cls.name.c_str());
446 cls.ref_counted_offset); 394 else
395 {
396 ClassInfo* baseClass = find_class(cls.baseClass);
397 printf("exports.%s = createClass(%s, %i, {\n", cls.name.c_str(),
398 (baseClass ? ("exports." + baseClass->name).c_str() : "null"),
399 cls.ref_counted_offset);
400 }
447 401
448 // Print prototype members 402 // Print prototype members
449 printProperties(cls.properties); 403 for (const auto& property : cls.properties)
450 printMethods(cls.methods); 404 {
405 if (property.jsValue.empty())
406 {
407 printf("get %s%s,\n", property.name.c_str(),
408 wrapCall(property.getter, false, cls.instanceGetter).c_str());
409 if (!property.setter.empty())
410 {
411 printf("set %s%s,\n", property.name.c_str(),
412 wrapCall(property.setter, false, cls.instanceGetter).c_str());
413 }
414 }
415 else
416 printf("%s: %s,\n", property.name.c_str(), property.jsValue.c_str());
417 }
418
419 for (const auto& method : cls.methods)
420 {
421 if (method.call.instance_function)
422 {
423 printf("%s: %s,\n",
424 method.name.c_str(),
425 wrapCall(method.call, true, cls.instanceGetter).c_str());
426 }
427 }
451 428
452 // End class definition 429 // End class definition
453 printf("});\n"); 430 if (singleton)
431 printf("};\n");
432 else
433 printf("});\n");
454 434
455 // Print static members 435 // Print static members
456 DifferentiatorInfo differentiator = cls.subclass_differentiator; 436 DifferentiatorInfo differentiator = cls.subclass_differentiator;
457 if (differentiator.offset != SIZE_MAX) 437 if (differentiator.offset != SIZE_MAX)
458 { 438 {
459 printf("var %s_mapping = \n", cls.name.c_str());
460 puts("{");
461 for (const auto& item : differentiator.mapping)
462 printf(" %i: '%s',\n", item.first, item.second.c_str());
463 puts("};");
464
465 printf("exports.%s.fromPointer = function(ptr)\n", cls.name.c_str()); 439 printf("exports.%s.fromPointer = function(ptr)\n", cls.name.c_str());
466 puts("{"); 440 puts("{");
467 printf(" var type = HEAP32[ptr + %i >> 2];\n", differentiator.offset); 441 printf(" var type = HEAP32[ptr + %i >> 2];\n", differentiator.offset);
468 printf(" if (type in %s_mapping)\n", cls.name.c_str()); 442 printf(" if (type in %s_mapping)\n", cls.name.c_str());
469 printf(" return new (exports[%s_mapping[type]])(ptr);\n", cls.name.c_st r()); 443 printf(" return new %s_mapping[type](ptr);\n", cls.name.c_str());
470 printf(" throw new Error('Unexpected %s type: ' + type);\n", cls.name.c_s tr()); 444 printf(" throw new Error('Unexpected %s type: ' + type);\n", cls.name.c_s tr());
471 puts("};"); 445 puts("};");
472 } 446 }
473 else 447 else
474 { 448 {
475 printf("exports.%s.fromPointer = function(ptr)\n", cls.name.c_str()); 449 printf("exports.%s.fromPointer = function(ptr)\n", cls.name.c_str());
476 puts("{"); 450 puts("{");
477 printf(" return new exports.%s(ptr);\n", cls.name.c_str()); 451 printf(" return new exports.%s(ptr);\n", cls.name.c_str());
478 puts("};"); 452 puts("};");
479 } 453 }
480 454
481 for (const auto& method : cls.methods) 455 for (const auto& method : cls.methods)
482 { 456 {
483 if (!method.call.instance_function) 457 if (!method.call.instance_function)
484 { 458 {
485 printf("exports.%s.%s = %s;\n", cls.name.c_str(), method.name.c_str(), 459 printf("exports.%s.%s = %s;\n", cls.name.c_str(), method.name.c_str(),
486 wrapCall(method.call).c_str()); 460 wrapCall(method.call).c_str());
487 } 461 }
488 } 462 }
489 } 463 }
490 464
491 void printNamespace(const NamespaceInfo& namespaceInfo) 465 void printClassMapping(const ClassInfo& cls)
492 { 466 {
493 printf("exports.%s = {\n", namespaceInfo.name.c_str()); 467 DifferentiatorInfo differentiator = cls.subclass_differentiator;
494 printProperties(namespaceInfo.properties); 468 if (differentiator.offset == SIZE_MAX)
495 printMethods(namespaceInfo.methods, false); 469 return;
496 puts("};"); 470
471 printf("var %s_mapping = \n", cls.name.c_str());
472 puts("{");
473 for (const auto& item : differentiator.mapping)
474 printf(" %i: exports.%s,\n", item.first, item.second.c_str());
475 puts("};");
497 } 476 }
498 } 477 }
499 478
500 void printBindings() 479 void printBindings()
501 { 480 {
502 bindings_internal::printHelpers(); 481 bindings_internal::printHelpers();
503 482
504 for (const auto& item : classes) 483 for (const auto& cls : classes)
505 bindings_internal::printClass(item); 484 bindings_internal::printClass(cls);
506 for (const auto& item : namespaces) 485 for (const auto& cls : classes)
507 bindings_internal::printNamespace(item); 486 bindings_internal::printClassMapping(cls);
508 } 487 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld