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

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: Removed unused parameter. 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 // Cache the object class and type.
34 ClassElement objectClass = compiler.objectClass; 30 ClassElement objectClass = compiler.objectClass;
herhut 2015/02/03 09:39:53 How about caching the TypeMask here. Then it can b
zarah 2015/02/03 10:07:19 Done.
35 DartType objectType = objectClass.rawType; 31 DartType objectType = objectClass.rawType;
herhut 2015/02/03 09:39:53 Is [objectType] used?
zarah 2015/02/03 10:07:19 Nope :-)
36 32
37 for (Selector selector in selectors) { 33 for (Selector selector in selectors) {
38 TypeMask mask = selector.mask; 34 TypeMask mask = selector.mask;
39 if (mask == null) { 35 if (mask == null) {
40 mask = new TypeMask.subclass(compiler.objectClass, compiler.world); 36 mask = new TypeMask.subclass(compiler.objectClass,
41 } 37 compiler.world);
38 }
42 39
43 if (!mask.needsNoSuchMethodHandling(selector, compiler.world)) continue; 40 if (!mask.needsNoSuchMethodHandling(selector, compiler.world)) {
44 String jsName = namer.invocationMirrorInternalName(selector); 41 continue;
45 addedJsNames[jsName] = selector; 42 }
46 String reflectionName = emitter.getReflectionName(selector, jsName); 43 String jsName = namer.invocationMirrorInternalName(selector);
47 if (reflectionName != null) { 44 jsNames[jsName] = selector;
48 emitter.mangledFieldNames[jsName] = reflectionName;
49 } 45 }
50 } 46 }
47
48 compiler.codegenWorld.invokedNames.forEach(addNoSuchMethodHandlers);
49 compiler.codegenWorld.invokedGetters.forEach(addNoSuchMethodHandlers);
50 compiler.codegenWorld.invokedSetters.forEach(addNoSuchMethodHandlers);
51 } 51 }
52 52
53 compiler.codegenWorld.invokedNames.forEach(addNoSuchMethodHandlers); 53 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. 54 // Values match JSInvocationMirror in js-helper library.
65 int type = selector.invocationMirrorKind; 55 int type = selector.invocationMirrorKind;
66 List<String> parameterNames = 56 List<String> parameterNames =
67 new List.generate(selector.argumentCount, (i) => '\$$i'); 57 new List.generate(selector.argumentCount, (i) => '\$$i');
68 58
69 List<jsAst.Expression> argNames = 59 List<jsAst.Expression> argNames =
70 selector.getOrderedNamedArguments().map((String name) => 60 selector.getOrderedNamedArguments().map((String name) =>
71 js.string(name)).toList(); 61 js.string(name)).toList();
72 62
73 String methodName = selector.invocationMirrorMemberName; 63 String methodName = selector.invocationMirrorMemberName;
74 String internalName = namer.invocationMirrorInternalName(selector); 64 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 65
83 assert(backend.isInterceptedName(Compiler.NO_SUCH_METHOD)); 66 assert(backend.isInterceptedName(Compiler.NO_SUCH_METHOD));
84 jsAst.Expression expression = 67 jsAst.Expression expression =
85 js('''this.#noSuchMethodName(this, 68 js('''this.#noSuchMethodName(this,
86 #createInvocationMirror(#methodName, 69 #createInvocationMirror(#methodName,
87 #internalName, 70 #internalName,
88 #type, 71 #type,
89 #arguments, 72 #arguments,
90 #namedArguments))''', 73 #namedArguments))''',
91 {'noSuchMethodName': noSuchMethodName, 74 {'noSuchMethodName': namer.noSuchMethodName,
92 'createInvocationMirror': 75 'createInvocationMirror':
93 backend.emitter.staticFunctionAccess( 76 backend.emitter.staticFunctionAccess(
94 backend.getCreateInvocationMirror()), 77 backend.getCreateInvocationMirror()),
95 'methodName': 78 'methodName':
96 js.string(compiler.enableMinification 79 js.string(compiler.enableMinification
97 ? internalName : methodName), 80 ? internalName : methodName),
98 'internalName': js.string(internalName), 81 'internalName': js.string(internalName),
99 'type': js.number(type), 82 'type': js.number(type),
100 'arguments': 83 'arguments':
101 new jsAst.ArrayInitializer(parameterNames.map(js).toList()), 84 new jsAst.ArrayInitializer(parameterNames.map(js).toList()),
102 'namedArguments': new jsAst.ArrayInitializer(argNames)}); 85 'namedArguments': new jsAst.ArrayInitializer(argNames)});
103 86
104 if (backend.isInterceptedName(selector.name)) { 87 if (backend.isInterceptedName(selector.name)) {
105 return js(r'function($receiver, #) { return # }', 88 return js(r'function($receiver, #) { return # }',
106 [parameterNames, expression]); 89 [parameterNames, expression]);
107 } else { 90 } else {
108 return js(r'function(#) { return # }', [parameterNames, expression]); 91 return js(r'function(#) { return # }', [parameterNames, expression]);
109 } 92 }
110 } 93 }
111 94
95 // Keep track of the JavaScript names we've already added so we
96 // do not introduce duplicates (bad for code size).
97 Map<String, Selector> addedJsNames = new Map<String, Selector>();
98 computeSelectorsForNsmHandlers(addedJsNames);
99
100 // Set flag used by generateMethod helper below. If we have very few
101 // handlers we use addProperty for them all, rather than try to generate
102 // them at runtime.
103 bool haveVeryFewNoSuchMemberHandlers =
104 (addedJsNames.length < VERY_FEW_NO_SUCH_METHOD_HANDLERS);
112 for (String jsName in addedJsNames.keys.toList()..sort()) { 105 for (String jsName in addedJsNames.keys.toList()..sort()) {
113 Selector selector = addedJsNames[jsName]; 106 Selector selector = addedJsNames[jsName];
107 String reflectionName = emitter.getReflectionName(selector, jsName);
108
109 if (reflectionName != null) {
110 emitter.mangledFieldNames[jsName] = reflectionName;
111 }
112
113 List<jsAst.Expression> argNames =
114 selector.getOrderedNamedArguments().map((String name) =>
115 js.string(name)).toList();
116 int type = selector.invocationMirrorKind;
117 if (!haveVeryFewNoSuchMemberHandlers &&
118 isTrivialNsmHandler(type, argNames, selector, jsName) &&
119 reflectionName == null) {
120 trivialNsmHandlers.add(selector);
121 }
122
114 jsAst.Expression method = generateMethod(jsName, selector); 123 jsAst.Expression method = generateMethod(jsName, selector);
115 if (method != null) { 124 if (method != null) {
116 addProperty(jsName, method); 125 addProperty(jsName, method);
117 String reflectionName = emitter.getReflectionName(selector, jsName);
118 if (reflectionName != null) { 126 if (reflectionName != null) {
119 bool accessible = compiler.world.allFunctions.filter(selector).any( 127 bool accessible = compiler.world.allFunctions.filter(selector).any(
120 (Element e) => backend.isAccessibleByReflection(e)); 128 (Element e) => backend.isAccessibleByReflection(e));
121 addProperty('+$reflectionName', js(accessible ? '2' : '0')); 129 addProperty('+$reflectionName', js(accessible ? '2' : '0'));
122 } 130 }
123 } 131 }
124 } 132 }
125 } 133 }
126 134
127 // Identify the noSuchMethod handlers that are so simple that we can 135 // 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); 282 diffEncoding.write(short);
275 } 283 }
276 nameCounter++; 284 nameCounter++;
277 } 285 }
278 286
279 // Startup code that loops over the method names and puts handlers on the 287 // Startup code that loops over the method names and puts handlers on the
280 // Object class to catch noSuchMethod invocations. 288 // Object class to catch noSuchMethod invocations.
281 ClassElement objectClass = compiler.objectClass; 289 ClassElement objectClass = compiler.objectClass;
282 jsAst.Expression createInvocationMirror = backend.emitter 290 jsAst.Expression createInvocationMirror = backend.emitter
283 .staticFunctionAccess(backend.getCreateInvocationMirror()); 291 .staticFunctionAccess(backend.getCreateInvocationMirror());
284 String noSuchMethodName = namer.publicInstanceMethodNameByArity( 292 String noSuchMethodName = namer.noSuchMethodName;
285 Compiler.NO_SUCH_METHOD, Compiler.NO_SUCH_METHOD_ARG_COUNT);
286 var type = 0; 293 var type = 0;
287 if (useDiffEncoding) { 294 if (useDiffEncoding) {
288 statements.add(js.statement('''{ 295 statements.add(js.statement('''{
289 var objectClassObject = processedClasses.collected[#objectClass], 296 var objectClassObject = processedClasses.collected[#objectClass],
290 shortNames = #diffEncoding.split(","), 297 shortNames = #diffEncoding.split(","),
291 nameNumber = 0, 298 nameNumber = 0,
292 diffEncodedString = shortNames[0], 299 diffEncodedString = shortNames[0],
293 calculatedShortNames = [0, 1]; // 0, 1 are args for splice. 300 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 301 // 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 302 // the collectedClasses so objectClassObject is undefined, and we skip
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 }''', { 394 }''', {
388 'sliceOffsetParams': sliceOffsetParams, 395 'sliceOffsetParams': sliceOffsetParams,
389 'noSuchMethodName': noSuchMethodName, 396 'noSuchMethodName': noSuchMethodName,
390 'createInvocationMirror': createInvocationMirror, 397 'createInvocationMirror': createInvocationMirror,
391 'names': minify ? 'shortNames' : 'longNames', 398 'names': minify ? 'shortNames' : 'longNames',
392 'sliceOffsetArguments': sliceOffsetArguments})); 399 'sliceOffsetArguments': sliceOffsetArguments}));
393 400
394 return statements; 401 return statements;
395 } 402 }
396 } 403 }
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