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: Rebased Created May 10, 2017, 12:36 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 19 matching lines...) Expand all
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 { 227 {
299 std::string result; 228 std::string result;
300 result += " var string = createString();\n"; 229 result += " var string = createString();\n";
301 result += " " + call_str + ";\n"; 230 result += " " + call_str + ";\n";
302 result += " var result = readString(string);\n"; 231 result += " var result = readString(string);\n";
232 // We don't call a destructor here because we know that dependent
233 // strings don't need to clean up.
303 return result; 234 return result;
304 } 235 }
305 case TypeCategory::OWNED_STRING: 236 case TypeCategory::OWNED_STRING:
306 { 237 {
307 std::string result; 238 std::string result;
308 result += " var string = createOwnedString();\n"; 239 result += " var string = createOwnedString();\n";
309 result += " " + call_str + ";\n"; 240 result += " " + call_str + ";\n";
310 result += " var result = readString(string);\n"; 241 result += " var result = readString(string);\n";
311 result += " Module._DestroyString(string);\n"; 242 result += " Module._DestroyString(string);\n";
312 return result; 243 return result;
313 } 244 }
314 case TypeCategory::STRING_REF: 245 case TypeCategory::STRING_REF:
315 return " var result = readString(" + call_str + ");\n"; 246 return " var result = readString(" + call_str + ");\n";
316 case TypeCategory::CLASS_PTR: 247 case TypeCategory::CLASS_PTR:
317 { 248 {
318 std::string result; 249 std::string result;
319 result += " var result = " + call_str + ";\n"; 250 result += " var result = " + call_str + ";\n";
320 result += " if (result)\n"; 251 result += " if (result)\n";
321 result += " {\n";
322 252
323 const ClassInfo* cls = find_class(call.pointerType); 253 const ClassInfo* cls = find_class(call.pointerType);
324 if (!cls) 254 if (!cls)
325 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");
326 256
327 auto offset = cls->subclass_differentiator.offset; 257 auto offset = cls->subclass_differentiator.offset;
328 if (offset == SIZE_MAX) 258 if (offset == SIZE_MAX)
329 result += " result = exports." + cls->name + "(result);\n"; 259 result += " result = exports." + cls->name + "(result);\n";
330 else 260 else
331 result += " result = exports." + cls->name + ".fromPointer(result); \n"; 261 result += " result = exports." + cls->name + ".fromPointer(result); \n";
332 262
333 result += " }\n";
334 result += " else\n"; 263 result += " else\n";
335 result += " result = null;\n"; 264 result += " result = null;\n";
336 return result; 265 return result;
337 } 266 }
338 default: 267 default:
339 throw std::runtime_error("Unexpected return type for " + call.name); 268 throw std::runtime_error("Unexpected return type for " + call.name);
340 } 269 }
341 } 270 }
342 271
343 std::string wrapCall(const FunctionInfo& call, bool isFunction) 272 std::string wrapCall(const FunctionInfo& call, bool isFunction,
273 const FunctionInfo& instanceGetter)
344 { 274 {
345 bool hasStringArgs = false; 275 bool hasStringArgs = false;
346 std::vector<std::string> params; 276 std::vector<std::string> params;
347 std::string prefix; 277 std::string prefix;
348 278
349 if (isFunction) 279 if (isFunction)
350 prefix += "function"; 280 prefix += "function";
351 prefix += "("; 281 prefix += "(";
352 for (int i = 0; i < call.args.size(); i++) 282 for (int i = 0; i < call.args.size(); i++)
353 { 283 {
(...skipping 25 matching lines...) Expand all
379 suffix = " return result;\n" + suffix; 309 suffix = " return result;\n" + suffix;
380 310
381 if (call.returnType == TypeCategory::DEPENDENT_STRING || 311 if (call.returnType == TypeCategory::DEPENDENT_STRING ||
382 call.returnType == TypeCategory::OWNED_STRING || hasStringArgs) 312 call.returnType == TypeCategory::OWNED_STRING || hasStringArgs)
383 { 313 {
384 prefix += " var sp = Runtime.stackSave();\n"; 314 prefix += " var sp = Runtime.stackSave();\n";
385 suffix = " Runtime.stackRestore(sp);\n" + suffix; 315 suffix = " Runtime.stackRestore(sp);\n" + suffix;
386 } 316 }
387 317
388 if (call.instance_function) 318 if (call.instance_function)
389 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 }
390 325
391 return prefix + generateCall(call, params) + suffix; 326 return prefix + generateCall(call, params) + suffix;
392 } 327 }
393 328
394 void printHelpers() 329 void printHelpers()
395 { 330 {
396 printf("var sizeofString = %i;\n", sizeof(String)); 331 printf("var sizeofString = %i;\n", sizeof(String));
397 332
398 puts(R"( 333 puts(R"(
399 function copyString(str, buffer) 334 function copyString(str, buffer)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 Module._ReleaseRef(this._pointer + ref_counted_offset); 381 Module._ReleaseRef(this._pointer + ref_counted_offset);
447 }; 382 };
448 return result; 383 return result;
449 } 384 }
450 )"); 385 )");
451 } 386 }
452 387
453 void printClass(const ClassInfo& cls) 388 void printClass(const ClassInfo& cls)
454 { 389 {
455 // Begin class definition 390 // Begin class definition
456 ClassInfo* baseClass = find_class(cls.baseClass); 391 bool singleton = !cls.instanceGetter.empty();
457 printf("exports.%s = createClass(%s, %i, {\n", cls.name.c_str(), 392 if (singleton)
458 (baseClass ? ("exports." + baseClass->name).c_str() : "null"), 393 printf("exports.%s = {\n", cls.name.c_str());
459 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 }
460 401
461 // Print prototype members 402 // Print prototype members
462 printProperties(cls.properties); 403 for (const auto& property : cls.properties)
463 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 }
464 428
465 // End class definition 429 // End class definition
466 printf("});\n"); 430 if (singleton)
431 printf("};\n");
432 else
433 printf("});\n");
467 434
468 // Print static members 435 // Print static members
469 DifferentiatorInfo differentiator = cls.subclass_differentiator; 436 DifferentiatorInfo differentiator = cls.subclass_differentiator;
470 if (differentiator.offset != SIZE_MAX) 437 if (differentiator.offset != SIZE_MAX)
471 { 438 {
472 printf("exports.%s.fromPointer = function(ptr)\n", cls.name.c_str()); 439 printf("exports.%s.fromPointer = function(ptr)\n", cls.name.c_str());
473 puts("{"); 440 puts("{");
474 printf(" var type = HEAP32[ptr + %i >> 2];\n", differentiator.offset); 441 printf(" var type = HEAP32[ptr + %i >> 2];\n", differentiator.offset);
475 printf(" if (type in %s_mapping)\n", cls.name.c_str()); 442 printf(" if (type in %s_mapping)\n", cls.name.c_str());
476 printf(" return new %s_mapping[type](ptr);\n", cls.name.c_str()); 443 printf(" return new %s_mapping[type](ptr);\n", cls.name.c_str());
(...skipping 23 matching lines...) Expand all
500 DifferentiatorInfo differentiator = cls.subclass_differentiator; 467 DifferentiatorInfo differentiator = cls.subclass_differentiator;
501 if (differentiator.offset == SIZE_MAX) 468 if (differentiator.offset == SIZE_MAX)
502 return; 469 return;
503 470
504 printf("var %s_mapping = \n", cls.name.c_str()); 471 printf("var %s_mapping = \n", cls.name.c_str());
505 puts("{"); 472 puts("{");
506 for (const auto& item : differentiator.mapping) 473 for (const auto& item : differentiator.mapping)
507 printf(" %i: exports.%s,\n", item.first, item.second.c_str()); 474 printf(" %i: exports.%s,\n", item.first, item.second.c_str());
508 puts("};"); 475 puts("};");
509 } 476 }
510
511 void printNamespace(const NamespaceInfo& namespaceInfo)
512 {
513 printf("exports.%s = {\n", namespaceInfo.name.c_str());
514 printProperties(namespaceInfo.properties);
515 printMethods(namespaceInfo.methods, false);
516 puts("};");
517 }
518 } 477 }
519 478
520 void printBindings() 479 void printBindings()
521 { 480 {
522 bindings_internal::printHelpers(); 481 bindings_internal::printHelpers();
523 482
524 for (const auto& cls : classes) 483 for (const auto& cls : classes)
525 bindings_internal::printClass(cls); 484 bindings_internal::printClass(cls);
526 for (const auto& cls : classes) 485 for (const auto& cls : classes)
527 bindings_internal::printClassMapping(cls); 486 bindings_internal::printClassMapping(cls);
528 for (const auto& namespace_ : namespaces)
529 bindings_internal::printNamespace(namespace_);
530 } 487 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld