Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Side by Side Diff: pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart

Issue 895893002: dart2js: refactor nsm_emitter. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed comments. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/compiler/lib/src/js_backend/namer.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart2js.js_emitter; 5 part of dart2js.js_emitter;
6 6
7 class NsmEmitter extends CodeEmitterHelper { 7 class NsmEmitter extends CodeEmitterHelper {
8 final List<Selector> trivialNsmHandlers = <Selector>[]; 8 final List<Selector> trivialNsmHandlers = <Selector>[];
9 9
10 /// If this is true then we can generate the noSuchMethod handlers at startup 10 /// If this is true then we can generate the noSuchMethod handlers at startup
11 /// time, instead of them being emitted as part of the Object class. 11 /// time, instead of them being emitted as part of the Object class.
12 bool get generateTrivialNsmHandlers => true; 12 bool get generateTrivialNsmHandlers => true;
13 13
14 // If we need fewer than this many noSuchMethod handlers we can save space by 14 // If we need fewer than this many noSuchMethod handlers we can save space by
15 // just emitting them in JS, rather than emitting the JS needed to generate 15 // just emitting them in JS, rather than emitting the JS needed to generate
16 // them at run time. 16 // them at run time.
17 static const VERY_FEW_NO_SUCH_METHOD_HANDLERS = 10; 17 static const VERY_FEW_NO_SUCH_METHOD_HANDLERS = 10;
18 18
19 static const MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING = 4; 19 static const MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING = 4;
20 20
21 void emitNoSuchMethodHandlers(AddPropertyFunction addProperty) { 21 void emitNoSuchMethodHandlers(AddPropertyFunction addProperty) {
22 // Do not generate no such method handlers if there is no class.
23 if (compiler.codegenWorld.directlyInstantiatedClasses.isEmpty) return;
24 22
25 String noSuchMethodName = namer.publicInstanceMethodNameByArity( 23 void computeSelectorsForNsmHandlers(Map<String, Selector> jsNames) {
26 Compiler.NO_SUCH_METHOD, Compiler.NO_SUCH_METHOD_ARG_COUNT);
27 24
28 // Keep track of the JavaScript names we've already added so we 25 // Do not generate no such method handlers if there is no class.
29 // do not introduce duplicates (bad for code size). 26 if (compiler.codegenWorld.directlyInstantiatedClasses.isEmpty) return;
30 Map<String, Selector> addedJsNames = new Map<String, Selector>();
31 27
32 void addNoSuchMethodHandlers(String ignore, Set<Selector> selectors) { 28 void addNoSuchMethodHandlers(String ignore, Set<Selector> selectors) {
33 // Cache the object class and type. 29 TypeMask objectSubclassTypeMask =
34 ClassElement objectClass = compiler.objectClass; 30 new TypeMask.subclass(compiler.objectClass, compiler.world);
35 DartType objectType = objectClass.rawType;
36 31
37 for (Selector selector in selectors) { 32 for (Selector selector in selectors) {
38 TypeMask mask = selector.mask; 33 TypeMask mask = selector.mask;
39 if (mask == null) { 34 if (mask == null) mask = objectSubclassTypeMask;
40 mask = new TypeMask.subclass(compiler.objectClass, compiler.world);
41 }
42 35
43 if (!mask.needsNoSuchMethodHandling(selector, compiler.world)) continue; 36 if (!mask.needsNoSuchMethodHandling(selector, compiler.world)) {
44 String jsName = namer.invocationMirrorInternalName(selector); 37 continue;
45 addedJsNames[jsName] = selector; 38 }
46 String reflectionName = emitter.getReflectionName(selector, jsName); 39 String jsName = namer.invocationMirrorInternalName(selector);
47 if (reflectionName != null) { 40 jsNames[jsName] = selector;
48 emitter.mangledFieldNames[jsName] = reflectionName;
49 } 41 }
50 } 42 }
43
44 compiler.codegenWorld.invokedNames.forEach(addNoSuchMethodHandlers);
45 compiler.codegenWorld.invokedGetters.forEach(addNoSuchMethodHandlers);
46 compiler.codegenWorld.invokedSetters.forEach(addNoSuchMethodHandlers);
51 } 47 }
52 48
53 compiler.codegenWorld.invokedNames.forEach(addNoSuchMethodHandlers); 49 jsAst.Expression generateMethod(Selector selector) {
54 compiler.codegenWorld.invokedGetters.forEach(addNoSuchMethodHandlers);
55 compiler.codegenWorld.invokedSetters.forEach(addNoSuchMethodHandlers);
56
57 // Set flag used by generateMethod helper below. If we have very few
58 // handlers we use addProperty for them all, rather than try to generate
59 // them at runtime.
60 bool haveVeryFewNoSuchMemberHandlers =
61 (addedJsNames.length < VERY_FEW_NO_SUCH_METHOD_HANDLERS);
62
63 jsAst.Expression generateMethod(String jsName, Selector selector) {
64 // Values match JSInvocationMirror in js-helper library. 50 // Values match JSInvocationMirror in js-helper library.
65 int type = selector.invocationMirrorKind; 51 int type = selector.invocationMirrorKind;
66 List<String> parameterNames = 52 List<String> parameterNames =
67 new List.generate(selector.argumentCount, (i) => '\$$i'); 53 new List.generate(selector.argumentCount, (i) => '\$$i');
68 54
69 List<jsAst.Expression> argNames = 55 List<jsAst.Expression> argNames =
70 selector.getOrderedNamedArguments().map((String name) => 56 selector.getOrderedNamedArguments().map((String name) =>
71 js.string(name)).toList(); 57 js.string(name)).toList();
72 58
73 String methodName = selector.invocationMirrorMemberName; 59 String methodName = selector.invocationMirrorMemberName;
74 String internalName = namer.invocationMirrorInternalName(selector); 60 String internalName = namer.invocationMirrorInternalName(selector);
75 String reflectionName = emitter.getReflectionName(selector, internalName);
76 if (!haveVeryFewNoSuchMemberHandlers &&
77 isTrivialNsmHandler(type, argNames, selector, internalName) &&
78 reflectionName == null) {
79 trivialNsmHandlers.add(selector);
80 return null;
81 }
82 61
83 assert(backend.isInterceptedName(Compiler.NO_SUCH_METHOD)); 62 assert(backend.isInterceptedName(Compiler.NO_SUCH_METHOD));
84 jsAst.Expression expression = 63 jsAst.Expression expression =
85 js('''this.#noSuchMethodName(this, 64 js('''this.#noSuchMethodName(this,
86 #createInvocationMirror(#methodName, 65 #createInvocationMirror(#methodName,
87 #internalName, 66 #internalName,
88 #type, 67 #type,
89 #arguments, 68 #arguments,
90 #namedArguments))''', 69 #namedArguments))''',
91 {'noSuchMethodName': noSuchMethodName, 70 {'noSuchMethodName': namer.noSuchMethodName,
92 'createInvocationMirror': 71 'createInvocationMirror':
93 backend.emitter.staticFunctionAccess( 72 backend.emitter.staticFunctionAccess(
94 backend.getCreateInvocationMirror()), 73 backend.getCreateInvocationMirror()),
95 'methodName': 74 'methodName':
96 js.string(compiler.enableMinification 75 js.string(compiler.enableMinification
97 ? internalName : methodName), 76 ? internalName : methodName),
98 'internalName': js.string(internalName), 77 'internalName': js.string(internalName),
99 'type': js.number(type), 78 'type': js.number(type),
100 'arguments': 79 'arguments':
101 new jsAst.ArrayInitializer(parameterNames.map(js).toList()), 80 new jsAst.ArrayInitializer(parameterNames.map(js).toList()),
102 'namedArguments': new jsAst.ArrayInitializer(argNames)}); 81 'namedArguments': new jsAst.ArrayInitializer(argNames)});
103 82
104 if (backend.isInterceptedName(selector.name)) { 83 if (backend.isInterceptedName(selector.name)) {
105 return js(r'function($receiver, #) { return # }', 84 return js(r'function($receiver, #) { return # }',
106 [parameterNames, expression]); 85 [parameterNames, expression]);
107 } else { 86 } else {
108 return js(r'function(#) { return # }', [parameterNames, expression]); 87 return js(r'function(#) { return # }', [parameterNames, expression]);
109 } 88 }
110 } 89 }
111 90
91 // Keep track of the JavaScript names we've already added so we
92 // do not introduce duplicates (bad for code size).
93 Map<String, Selector> addedJsNames = new Map<String, Selector>();
94 computeSelectorsForNsmHandlers(addedJsNames);
floitsch 2015/02/03 10:56:02 Let the computeSelectors return the map.
zarah 2015/02/03 11:06:50 Done.
95
96 // Set flag used by generateMethod helper below. If we have very few
97 // handlers we use addProperty for them all, rather than try to generate
98 // them at runtime.
99 bool haveVeryFewNoSuchMemberHandlers =
100 (addedJsNames.length < VERY_FEW_NO_SUCH_METHOD_HANDLERS);
112 for (String jsName in addedJsNames.keys.toList()..sort()) { 101 for (String jsName in addedJsNames.keys.toList()..sort()) {
113 Selector selector = addedJsNames[jsName]; 102 Selector selector = addedJsNames[jsName];
114 jsAst.Expression method = generateMethod(jsName, selector); 103 String reflectionName = emitter.getReflectionName(selector, jsName);
104
105 if (reflectionName != null) {
106 emitter.mangledFieldNames[jsName] = reflectionName;
107 }
108
109 List<jsAst.Expression> argNames =
110 selector.getOrderedNamedArguments().map((String name) =>
111 js.string(name)).toList();
112 int type = selector.invocationMirrorKind;
113 if (!haveVeryFewNoSuchMemberHandlers &&
114 isTrivialNsmHandler(type, argNames, selector, jsName) &&
115 reflectionName == null) {
116 trivialNsmHandlers.add(selector);
117 }
118
119 jsAst.Expression method = generateMethod(selector);
115 if (method != null) { 120 if (method != null) {
116 addProperty(jsName, method); 121 addProperty(jsName, method);
117 String reflectionName = emitter.getReflectionName(selector, jsName);
118 if (reflectionName != null) { 122 if (reflectionName != null) {
119 bool accessible = compiler.world.allFunctions.filter(selector).any( 123 bool accessible = compiler.world.allFunctions.filter(selector).any(
120 (Element e) => backend.isAccessibleByReflection(e)); 124 (Element e) => backend.isAccessibleByReflection(e));
121 addProperty('+$reflectionName', js(accessible ? '2' : '0')); 125 addProperty('+$reflectionName', js(accessible ? '2' : '0'));
122 } 126 }
123 } 127 }
124 } 128 }
125 } 129 }
126 130
127 // Identify the noSuchMethod handlers that are so simple that we can 131 // Identify the noSuchMethod handlers that are so simple that we can
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 diffEncoding.write(short); 278 diffEncoding.write(short);
275 } 279 }
276 nameCounter++; 280 nameCounter++;
277 } 281 }
278 282
279 // Startup code that loops over the method names and puts handlers on the 283 // Startup code that loops over the method names and puts handlers on the
280 // Object class to catch noSuchMethod invocations. 284 // Object class to catch noSuchMethod invocations.
281 ClassElement objectClass = compiler.objectClass; 285 ClassElement objectClass = compiler.objectClass;
282 jsAst.Expression createInvocationMirror = backend.emitter 286 jsAst.Expression createInvocationMirror = backend.emitter
283 .staticFunctionAccess(backend.getCreateInvocationMirror()); 287 .staticFunctionAccess(backend.getCreateInvocationMirror());
284 String noSuchMethodName = namer.publicInstanceMethodNameByArity( 288 String noSuchMethodName = namer.noSuchMethodName;
floitsch 2015/02/03 10:56:02 might as well inline it to its use site.
zarah 2015/02/03 11:06:50 Done.
285 Compiler.NO_SUCH_METHOD, Compiler.NO_SUCH_METHOD_ARG_COUNT);
286 var type = 0; 289 var type = 0;
287 if (useDiffEncoding) { 290 if (useDiffEncoding) {
288 statements.add(js.statement('''{ 291 statements.add(js.statement('''{
289 var objectClassObject = processedClasses.collected[#objectClass], 292 var objectClassObject = processedClasses.collected[#objectClass],
290 shortNames = #diffEncoding.split(","), 293 shortNames = #diffEncoding.split(","),
291 nameNumber = 0, 294 nameNumber = 0,
292 diffEncodedString = shortNames[0], 295 diffEncodedString = shortNames[0],
293 calculatedShortNames = [0, 1]; // 0, 1 are args for splice. 296 calculatedShortNames = [0, 1]; // 0, 1 are args for splice.
294 // If we are loading a deferred library the object class will not be i n 297 // If we are loading a deferred library the object class will not be i n
295 // the collectedClasses so objectClassObject is undefined, and we skip 298 // the collectedClasses so objectClassObject is undefined, and we skip
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 }''', { 390 }''', {
388 'sliceOffsetParams': sliceOffsetParams, 391 'sliceOffsetParams': sliceOffsetParams,
389 'noSuchMethodName': noSuchMethodName, 392 'noSuchMethodName': noSuchMethodName,
390 'createInvocationMirror': createInvocationMirror, 393 'createInvocationMirror': createInvocationMirror,
391 'names': minify ? 'shortNames' : 'longNames', 394 'names': minify ? 'shortNames' : 'longNames',
392 'sliceOffsetArguments': sliceOffsetArguments})); 395 'sliceOffsetArguments': sliceOffsetArguments}));
393 396
394 return statements; 397 return statements;
395 } 398 }
396 } 399 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/namer.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698