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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/nodes.dart

Issue 12033056: Implement "one-shot" interceptors. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 11 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 ssa; 5 part of ssa;
6 6
7 abstract class HVisitor<R> { 7 abstract class HVisitor<R> {
8 R visitAdd(HAdd node); 8 R visitAdd(HAdd node);
9 R visitBailoutTarget(HBailoutTarget node); 9 R visitBailoutTarget(HBailoutTarget node);
10 R visitBitAnd(HBitAnd node); 10 R visitBitAnd(HBitAnd node);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 R visitLess(HLess node); 43 R visitLess(HLess node);
44 R visitLessEqual(HLessEqual node); 44 R visitLessEqual(HLessEqual node);
45 R visitLiteralList(HLiteralList node); 45 R visitLiteralList(HLiteralList node);
46 R visitLocalGet(HLocalGet node); 46 R visitLocalGet(HLocalGet node);
47 R visitLocalSet(HLocalSet node); 47 R visitLocalSet(HLocalSet node);
48 R visitLocalValue(HLocalValue node); 48 R visitLocalValue(HLocalValue node);
49 R visitLoopBranch(HLoopBranch node); 49 R visitLoopBranch(HLoopBranch node);
50 R visitMultiply(HMultiply node); 50 R visitMultiply(HMultiply node);
51 R visitNegate(HNegate node); 51 R visitNegate(HNegate node);
52 R visitNot(HNot node); 52 R visitNot(HNot node);
53 R visitOneShotInterceptor(HOneShotInterceptor);
53 R visitParameterValue(HParameterValue node); 54 R visitParameterValue(HParameterValue node);
54 R visitPhi(HPhi node); 55 R visitPhi(HPhi node);
55 R visitRangeConversion(HRangeConversion node); 56 R visitRangeConversion(HRangeConversion node);
56 R visitReturn(HReturn node); 57 R visitReturn(HReturn node);
57 R visitShiftLeft(HShiftLeft node); 58 R visitShiftLeft(HShiftLeft node);
58 R visitStatic(HStatic node); 59 R visitStatic(HStatic node);
59 R visitStaticStore(HStaticStore node); 60 R visitStaticStore(HStaticStore node);
60 R visitStringConcat(HStringConcat node); 61 R visitStringConcat(HStringConcat node);
61 R visitSubtract(HSubtract node); 62 R visitSubtract(HSubtract node);
62 R visitSwitch(HSwitch node); 63 R visitSwitch(HSwitch node);
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 visitLazyStatic(HLazyStatic node) => visitInstruction(node); 307 visitLazyStatic(HLazyStatic node) => visitInstruction(node);
307 visitLess(HLess node) => visitRelational(node); 308 visitLess(HLess node) => visitRelational(node);
308 visitLessEqual(HLessEqual node) => visitRelational(node); 309 visitLessEqual(HLessEqual node) => visitRelational(node);
309 visitLiteralList(HLiteralList node) => visitInstruction(node); 310 visitLiteralList(HLiteralList node) => visitInstruction(node);
310 visitLocalGet(HLocalGet node) => visitFieldAccess(node); 311 visitLocalGet(HLocalGet node) => visitFieldAccess(node);
311 visitLocalSet(HLocalSet node) => visitFieldAccess(node); 312 visitLocalSet(HLocalSet node) => visitFieldAccess(node);
312 visitLocalValue(HLocalValue node) => visitInstruction(node); 313 visitLocalValue(HLocalValue node) => visitInstruction(node);
313 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node); 314 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node);
314 visitNegate(HNegate node) => visitInvokeUnary(node); 315 visitNegate(HNegate node) => visitInvokeUnary(node);
315 visitNot(HNot node) => visitInstruction(node); 316 visitNot(HNot node) => visitInstruction(node);
317 visitOneShotInterceptor(HOneShotInterceptor node)
318 => visitInvokeDynamic(node);
316 visitPhi(HPhi node) => visitInstruction(node); 319 visitPhi(HPhi node) => visitInstruction(node);
317 visitMultiply(HMultiply node) => visitBinaryArithmetic(node); 320 visitMultiply(HMultiply node) => visitBinaryArithmetic(node);
318 visitParameterValue(HParameterValue node) => visitLocalValue(node); 321 visitParameterValue(HParameterValue node) => visitLocalValue(node);
319 visitRangeConversion(HRangeConversion node) => visitCheck(node); 322 visitRangeConversion(HRangeConversion node) => visitCheck(node);
320 visitReturn(HReturn node) => visitControlFlow(node); 323 visitReturn(HReturn node) => visitControlFlow(node);
321 visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node); 324 visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node);
322 visitSubtract(HSubtract node) => visitBinaryArithmetic(node); 325 visitSubtract(HSubtract node) => visitBinaryArithmetic(node);
323 visitSwitch(HSwitch node) => visitControlFlow(node); 326 visitSwitch(HSwitch node) => visitControlFlow(node);
324 visitStatic(HStatic node) => visitInstruction(node); 327 visitStatic(HStatic node) => visitInstruction(node);
325 visitStaticStore(HStaticStore node) => visitInstruction(node); 328 visitStaticStore(HStaticStore node) => visitInstruction(node);
(...skipping 823 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 new HType.fromBoundedType(type, compiler, canBeNull); 1152 new HType.fromBoundedType(type, compiler, canBeNull);
1150 1153
1151 // No need to convert if we know the instruction has 1154 // No need to convert if we know the instruction has
1152 // [convertedType] as a bound. 1155 // [convertedType] as a bound.
1153 if (this.guaranteedType == convertedType) { 1156 if (this.guaranteedType == convertedType) {
1154 return this; 1157 return this;
1155 } 1158 }
1156 1159
1157 return new HTypeConversion(convertedType, this, kind); 1160 return new HTypeConversion(convertedType, this, kind);
1158 } 1161 }
1162
1163 /**
1164 * Return whether the instructions do not belong to a loop or
1165 * belong to the same loop.
1166 */
1167 bool bothNotInLoopOrInSameLoop(HInstruction other) {
kasperl 2013/01/24 09:03:51 hasSameLoopHeaderAs
ngeoffray 2013/01/24 10:41:30 Done.
1168 return block.enclosingLoopHeader == other.block.enclosingLoopHeader;
1169 }
1159 } 1170 }
1160 1171
1161 class HBoolify extends HInstruction { 1172 class HBoolify extends HInstruction {
1162 HBoolify(HInstruction value) : super(<HInstruction>[value]) { 1173 HBoolify(HInstruction value) : super(<HInstruction>[value]) {
1163 assert(!hasSideEffects()); 1174 assert(!hasSideEffects());
1164 setUseGvn(); 1175 setUseGvn();
1165 } 1176 }
1166 1177
1167 HType get guaranteedType => HType.BOOLEAN; 1178 HType get guaranteedType => HType.BOOLEAN;
1168 1179
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1307 */ 1318 */
1308 HInvoke(List<HInstruction> inputs) : super(inputs) { 1319 HInvoke(List<HInstruction> inputs) : super(inputs) {
1309 setAllSideEffects(); 1320 setAllSideEffects();
1310 setDependsOnSomething(); 1321 setDependsOnSomething();
1311 } 1322 }
1312 static const int ARGUMENTS_OFFSET = 1; 1323 static const int ARGUMENTS_OFFSET = 1;
1313 bool canThrow() => true; 1324 bool canThrow() => true;
1314 } 1325 }
1315 1326
1316 abstract class HInvokeDynamic extends HInvoke { 1327 abstract class HInvokeDynamic extends HInvoke {
1328 final InvokeDynamicSpecializer specializer;
1317 final Selector selector; 1329 final Selector selector;
1318 Element element; 1330 Element element;
1319 1331
1320 HInvokeDynamic(this.selector, this.element, List<HInstruction> inputs) 1332 HInvokeDynamic(Selector selector,
1321 : super(inputs); 1333 this.element,
1334 List<HInstruction> inputs,
1335 [bool isIntercepted = false])
1336 : super(inputs),
1337 this.selector = selector,
1338 specializer = isIntercepted
1339 ? InvokeDynamicSpecializer.lookupSpecializer(selector)
1340 : const InvokeDynamicSpecializer();
1322 toString() => 'invoke dynamic: $selector'; 1341 toString() => 'invoke dynamic: $selector';
1323 HInstruction get receiver => inputs[0]; 1342 HInstruction get receiver => inputs[0];
1324 1343
1325 bool get isInterceptorCall { 1344 bool get isInterceptorCall {
1326 // We know it's a selector call if it follows the interceptor 1345 // We know it's a selector call if it follows the interceptor
1327 // calling convention, which adds the actual receiver as a 1346 // calling convention, which adds the actual receiver as a
1328 // parameter to the call. 1347 // parameter to the call.
1329 return inputs.length - 2 == selector.argumentCount; 1348 return inputs.length - 2 == selector.argumentCount;
1330 } 1349 }
1331 1350
1332 int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE; 1351 int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE;
1333 bool typeEquals(other) => other is HInvokeDynamic; 1352 bool typeEquals(other) => other is HInvokeDynamic;
1334 bool dataEquals(HInvokeDynamic other) { 1353 bool dataEquals(HInvokeDynamic other) {
1335 return selector == other.selector 1354 return selector == other.selector
1336 && element == other.element; 1355 && element == other.element;
1337 } 1356 }
1357
1358 HType computeDesiredTypeForInput(HInstruction input,
1359 HTypeMap types,
1360 Compiler compiler) {
1361 return specializer.computeDesiredTypeForInput(this, input, types, compiler);
1362 }
1363
1364 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) {
1365 return specializer.computeTypeFromInputTypes(this, types, compiler);
1366 }
1338 } 1367 }
1339 1368
1340 class HInvokeClosure extends HInvokeDynamic { 1369 class HInvokeClosure extends HInvokeDynamic {
1341 HInvokeClosure(Selector selector, List<HInstruction> inputs) 1370 HInvokeClosure(Selector selector, List<HInstruction> inputs)
1342 : super(selector, null, inputs) { 1371 : super(selector, null, inputs) {
1343 assert(selector.isClosureCall()); 1372 assert(selector.isClosureCall());
1344 } 1373 }
1345 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); 1374 accept(HVisitor visitor) => visitor.visitInvokeClosure(this);
1346 } 1375 }
1347 1376
1348 class HInvokeDynamicMethod extends HInvokeDynamic { 1377 class HInvokeDynamicMethod extends HInvokeDynamic {
1349 final InvokeDynamicSpecializer specializer;
1350 HInvokeDynamicMethod(Selector selector, 1378 HInvokeDynamicMethod(Selector selector,
1351 List<HInstruction> inputs, 1379 List<HInstruction> inputs,
1352 [bool isIntercepted = false]) 1380 [bool isIntercepted = false])
1353 : super(selector, null, inputs), 1381 : super(selector, null, inputs, isIntercepted);
1354 specializer = isIntercepted 1382
1355 ? InvokeDynamicSpecializer.lookupSpecializer(selector)
1356 : const InvokeDynamicSpecializer();
1357 String toString() => 'invoke dynamic method: $selector'; 1383 String toString() => 'invoke dynamic method: $selector';
1358 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); 1384 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
1359 1385
1360 bool isIndexOperatorOnIndexablePrimitive(HTypeMap types) { 1386 bool isIndexOperatorOnIndexablePrimitive(HTypeMap types) {
1361 return isInterceptorCall 1387 return isInterceptorCall
1362 && selector.kind == SelectorKind.INDEX 1388 && selector.kind == SelectorKind.INDEX
1363 && selector.name == const SourceString('[]') 1389 && selector.name == const SourceString('[]')
1364 && inputs[1].isIndexablePrimitive(types); 1390 && inputs[1].isIndexablePrimitive(types);
1365 } 1391 }
1366
1367 HType computeDesiredTypeForInput(HInstruction input,
1368 HTypeMap types,
1369 Compiler compiler) {
1370 return specializer.computeDesiredTypeForInput(this, input, types, compiler);
1371 }
1372
1373 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) {
1374 return specializer.computeTypeFromInputTypes(this, types, compiler);
1375 }
1376 } 1392 }
1377 1393
1378 abstract class HInvokeDynamicField extends HInvokeDynamic { 1394 abstract class HInvokeDynamicField extends HInvokeDynamic {
1379 final bool isSideEffectFree; 1395 final bool isSideEffectFree;
1380 HInvokeDynamicField( 1396 HInvokeDynamicField(
1381 Selector selector, Element element, List<HInstruction> inputs, 1397 Selector selector, Element element, List<HInstruction> inputs,
1382 this.isSideEffectFree) 1398 this.isSideEffectFree)
1383 : super(selector, element, inputs); 1399 : super(selector, element, inputs);
1384 toString() => 'invoke dynamic field: $selector'; 1400 toString() => 'invoke dynamic field: $selector';
1385 } 1401 }
(...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after
2128 2144
2129 int typeCode() => HInstruction.INTERCEPTOR_TYPECODE; 2145 int typeCode() => HInstruction.INTERCEPTOR_TYPECODE;
2130 bool typeEquals(other) => other is HInterceptor; 2146 bool typeEquals(other) => other is HInterceptor;
2131 bool dataEquals(HInterceptor other) { 2147 bool dataEquals(HInterceptor other) {
2132 return interceptedClasses == other.interceptedClasses 2148 return interceptedClasses == other.interceptedClasses
2133 || (interceptedClasses.length == other.interceptedClasses.length 2149 || (interceptedClasses.length == other.interceptedClasses.length
2134 && interceptedClasses.containsAll(other.interceptedClasses)); 2150 && interceptedClasses.containsAll(other.interceptedClasses));
2135 } 2151 }
2136 } 2152 }
2137 2153
2154 /**
2155 * A "one-shot" interceptor is a call to a synthetized method that
2156 * will fetch the interceptor of its first parameter, and make a call
2157 * on a given selector with the remaining parameters.
2158 *
2159 * In order to share the same optimizations with regular interceptor
2160 * calls, this class extends [HInvokeDynamic] and also has the null
2161 * constant as the first input.
2162 */
2163 class HOneShotInterceptor extends HInvokeDynamic {
2164 Set<ClassElement> interceptedClasses;
2165 HOneShotInterceptor(Selector selector,
2166 List<HInstruction> inputs,
2167 this.interceptedClasses)
2168 : super(selector, null, inputs, true) {
2169 assert(inputs[0] is HConstant);
2170 assert(inputs[0].guaranteedType == HType.NULL);
2171 }
2172
2173 String toString() => 'one shot interceptor on $selector';
2174 accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this);
2175 }
2176
2138 /** An [HLazyStatic] is a static that is initialized lazily at first read. */ 2177 /** An [HLazyStatic] is a static that is initialized lazily at first read. */
2139 class HLazyStatic extends HInstruction { 2178 class HLazyStatic extends HInstruction {
2140 final Element element; 2179 final Element element;
2141 HLazyStatic(this.element) : super(<HInstruction>[]) { 2180 HLazyStatic(this.element) : super(<HInstruction>[]) {
2142 // TODO(4931): The first access has side-effects, but we afterwards we 2181 // TODO(4931): The first access has side-effects, but we afterwards we
2143 // should be able to GVN. 2182 // should be able to GVN.
2144 setAllSideEffects(); 2183 setAllSideEffects();
2145 setDependsOnSomething(); 2184 setDependsOnSomething();
2146 } 2185 }
2147 2186
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
2646 HBasicBlock get start => expression.start; 2685 HBasicBlock get start => expression.start;
2647 HBasicBlock get end { 2686 HBasicBlock get end {
2648 // We don't create a switch block if there are no cases. 2687 // We don't create a switch block if there are no cases.
2649 assert(!statements.isEmpty); 2688 assert(!statements.isEmpty);
2650 return statements.last.end; 2689 return statements.last.end;
2651 } 2690 }
2652 2691
2653 bool accept(HStatementInformationVisitor visitor) => 2692 bool accept(HStatementInformationVisitor visitor) =>
2654 visitor.visitSwitchInfo(this); 2693 visitor.visitSwitchInfo(this);
2655 } 2694 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698