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

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 827 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 new HType.fromBoundedType(type, compiler, canBeNull); 1156 new HType.fromBoundedType(type, compiler, canBeNull);
1154 1157
1155 // No need to convert if we know the instruction has 1158 // No need to convert if we know the instruction has
1156 // [convertedType] as a bound. 1159 // [convertedType] as a bound.
1157 if (this.guaranteedType == convertedType) { 1160 if (this.guaranteedType == convertedType) {
1158 return this; 1161 return this;
1159 } 1162 }
1160 1163
1161 return new HTypeConversion(convertedType, this, kind); 1164 return new HTypeConversion(convertedType, this, kind);
1162 } 1165 }
1166
1167 /**
1168 * Return whether the instructions do not belong to a loop or
1169 * belong to the same loop.
1170 */
1171 bool hasSameLoopHeaderAs(HInstruction other) {
1172 return block.enclosingLoopHeader == other.block.enclosingLoopHeader;
1173 }
1163 } 1174 }
1164 1175
1165 class HBoolify extends HInstruction { 1176 class HBoolify extends HInstruction {
1166 HBoolify(HInstruction value) : super(<HInstruction>[value]) { 1177 HBoolify(HInstruction value) : super(<HInstruction>[value]) {
1167 assert(!hasSideEffects()); 1178 assert(!hasSideEffects());
1168 setUseGvn(); 1179 setUseGvn();
1169 } 1180 }
1170 1181
1171 HType get guaranteedType => HType.BOOLEAN; 1182 HType get guaranteedType => HType.BOOLEAN;
1172 1183
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1315 */ 1326 */
1316 HInvoke(List<HInstruction> inputs) : super(inputs) { 1327 HInvoke(List<HInstruction> inputs) : super(inputs) {
1317 setAllSideEffects(); 1328 setAllSideEffects();
1318 setDependsOnSomething(); 1329 setDependsOnSomething();
1319 } 1330 }
1320 static const int ARGUMENTS_OFFSET = 1; 1331 static const int ARGUMENTS_OFFSET = 1;
1321 bool canThrow() => true; 1332 bool canThrow() => true;
1322 } 1333 }
1323 1334
1324 abstract class HInvokeDynamic extends HInvoke { 1335 abstract class HInvokeDynamic extends HInvoke {
1336 final InvokeDynamicSpecializer specializer;
1325 final Selector selector; 1337 final Selector selector;
1326 Element element; 1338 Element element;
1327 1339
1328 HInvokeDynamic(this.selector, this.element, List<HInstruction> inputs) 1340 HInvokeDynamic(Selector selector,
1329 : super(inputs); 1341 this.element,
1342 List<HInstruction> inputs,
1343 [bool isIntercepted = false])
1344 : super(inputs),
1345 this.selector = selector,
1346 specializer = isIntercepted
1347 ? InvokeDynamicSpecializer.lookupSpecializer(selector)
1348 : const InvokeDynamicSpecializer();
1330 toString() => 'invoke dynamic: $selector'; 1349 toString() => 'invoke dynamic: $selector';
1331 HInstruction get receiver => inputs[0]; 1350 HInstruction get receiver => inputs[0];
1332 1351
1333 bool get isInterceptorCall { 1352 bool get isInterceptorCall {
1334 // We know it's a selector call if it follows the interceptor 1353 // We know it's a selector call if it follows the interceptor
1335 // calling convention, which adds the actual receiver as a 1354 // calling convention, which adds the actual receiver as a
1336 // parameter to the call. 1355 // parameter to the call.
1337 return inputs.length - 2 == selector.argumentCount; 1356 return inputs.length - 2 == selector.argumentCount;
1338 } 1357 }
1339 1358
1340 int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE; 1359 int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE;
1341 bool typeEquals(other) => other is HInvokeDynamic; 1360 bool typeEquals(other) => other is HInvokeDynamic;
1342 bool dataEquals(HInvokeDynamic other) { 1361 bool dataEquals(HInvokeDynamic other) {
1343 return selector == other.selector 1362 return selector == other.selector
1344 && element == other.element; 1363 && element == other.element;
1345 } 1364 }
1365
1366 HType computeDesiredTypeForInput(HInstruction input,
1367 HTypeMap types,
1368 Compiler compiler) {
1369 return specializer.computeDesiredTypeForInput(this, input, types, compiler);
1370 }
1371
1372 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) {
1373 return specializer.computeTypeFromInputTypes(this, types, compiler);
1374 }
1346 } 1375 }
1347 1376
1348 class HInvokeClosure extends HInvokeDynamic { 1377 class HInvokeClosure extends HInvokeDynamic {
1349 HInvokeClosure(Selector selector, List<HInstruction> inputs) 1378 HInvokeClosure(Selector selector, List<HInstruction> inputs)
1350 : super(selector, null, inputs) { 1379 : super(selector, null, inputs) {
1351 assert(selector.isClosureCall()); 1380 assert(selector.isClosureCall());
1352 } 1381 }
1353 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); 1382 accept(HVisitor visitor) => visitor.visitInvokeClosure(this);
1354 } 1383 }
1355 1384
1356 class HInvokeDynamicMethod extends HInvokeDynamic { 1385 class HInvokeDynamicMethod extends HInvokeDynamic {
1357 final InvokeDynamicSpecializer specializer;
1358 HInvokeDynamicMethod(Selector selector, 1386 HInvokeDynamicMethod(Selector selector,
1359 List<HInstruction> inputs, 1387 List<HInstruction> inputs,
1360 [bool isIntercepted = false]) 1388 [bool isIntercepted = false])
1361 : super(selector, null, inputs), 1389 : super(selector, null, inputs, isIntercepted);
1362 specializer = isIntercepted 1390
1363 ? InvokeDynamicSpecializer.lookupSpecializer(selector)
1364 : const InvokeDynamicSpecializer();
1365 String toString() => 'invoke dynamic method: $selector'; 1391 String toString() => 'invoke dynamic method: $selector';
1366 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); 1392 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
1367 1393
1368 bool isIndexOperatorOnIndexablePrimitive(HTypeMap types) { 1394 bool isIndexOperatorOnIndexablePrimitive(HTypeMap types) {
1369 return isInterceptorCall 1395 return isInterceptorCall
1370 && selector.kind == SelectorKind.INDEX 1396 && selector.kind == SelectorKind.INDEX
1371 && selector.name == const SourceString('[]') 1397 && selector.name == const SourceString('[]')
1372 && inputs[1].isIndexablePrimitive(types); 1398 && inputs[1].isIndexablePrimitive(types);
1373 } 1399 }
1374
1375 HType computeDesiredTypeForInput(HInstruction input,
1376 HTypeMap types,
1377 Compiler compiler) {
1378 return specializer.computeDesiredTypeForInput(this, input, types, compiler);
1379 }
1380
1381 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) {
1382 return specializer.computeTypeFromInputTypes(this, types, compiler);
1383 }
1384 } 1400 }
1385 1401
1386 abstract class HInvokeDynamicField extends HInvokeDynamic { 1402 abstract class HInvokeDynamicField extends HInvokeDynamic {
1387 final bool isSideEffectFree; 1403 final bool isSideEffectFree;
1388 HInvokeDynamicField( 1404 HInvokeDynamicField(
1389 Selector selector, Element element, List<HInstruction> inputs, 1405 Selector selector, Element element, List<HInstruction> inputs,
1390 this.isSideEffectFree) 1406 this.isSideEffectFree)
1391 : super(selector, element, inputs); 1407 : super(selector, element, inputs);
1392 toString() => 'invoke dynamic field: $selector'; 1408 toString() => 'invoke dynamic field: $selector';
1393 } 1409 }
(...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after
2136 2152
2137 int typeCode() => HInstruction.INTERCEPTOR_TYPECODE; 2153 int typeCode() => HInstruction.INTERCEPTOR_TYPECODE;
2138 bool typeEquals(other) => other is HInterceptor; 2154 bool typeEquals(other) => other is HInterceptor;
2139 bool dataEquals(HInterceptor other) { 2155 bool dataEquals(HInterceptor other) {
2140 return interceptedClasses == other.interceptedClasses 2156 return interceptedClasses == other.interceptedClasses
2141 || (interceptedClasses.length == other.interceptedClasses.length 2157 || (interceptedClasses.length == other.interceptedClasses.length
2142 && interceptedClasses.containsAll(other.interceptedClasses)); 2158 && interceptedClasses.containsAll(other.interceptedClasses));
2143 } 2159 }
2144 } 2160 }
2145 2161
2162 /**
2163 * A "one-shot" interceptor is a call to a synthetized method that
2164 * will fetch the interceptor of its first parameter, and make a call
2165 * on a given selector with the remaining parameters.
2166 *
2167 * In order to share the same optimizations with regular interceptor
2168 * calls, this class extends [HInvokeDynamic] and also has the null
2169 * constant as the first input.
2170 */
2171 class HOneShotInterceptor extends HInvokeDynamic {
2172 Set<ClassElement> interceptedClasses;
2173 HOneShotInterceptor(Selector selector,
2174 List<HInstruction> inputs,
2175 this.interceptedClasses)
2176 : super(selector, null, inputs, true) {
2177 assert(inputs[0] is HConstant);
2178 assert(inputs[0].guaranteedType == HType.NULL);
2179 }
2180
2181 String toString() => 'one shot interceptor on $selector';
2182 accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this);
2183 }
2184
2146 /** An [HLazyStatic] is a static that is initialized lazily at first read. */ 2185 /** An [HLazyStatic] is a static that is initialized lazily at first read. */
2147 class HLazyStatic extends HInstruction { 2186 class HLazyStatic extends HInstruction {
2148 final Element element; 2187 final Element element;
2149 HLazyStatic(this.element) : super(<HInstruction>[]) { 2188 HLazyStatic(this.element) : super(<HInstruction>[]) {
2150 // TODO(4931): The first access has side-effects, but we afterwards we 2189 // TODO(4931): The first access has side-effects, but we afterwards we
2151 // should be able to GVN. 2190 // should be able to GVN.
2152 setAllSideEffects(); 2191 setAllSideEffects();
2153 setDependsOnSomething(); 2192 setDependsOnSomething();
2154 } 2193 }
2155 2194
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
2654 HBasicBlock get start => expression.start; 2693 HBasicBlock get start => expression.start;
2655 HBasicBlock get end { 2694 HBasicBlock get end {
2656 // We don't create a switch block if there are no cases. 2695 // We don't create a switch block if there are no cases.
2657 assert(!statements.isEmpty); 2696 assert(!statements.isEmpty);
2658 return statements.last.end; 2697 return statements.last.end;
2659 } 2698 }
2660 2699
2661 bool accept(HStatementInformationVisitor visitor) => 2700 bool accept(HStatementInformationVisitor visitor) =>
2662 visitor.visitSwitchInfo(this); 2701 visitor.visitSwitchInfo(this);
2663 } 2702 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698