OLD | NEW |
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 visitBitAnd(HBitAnd node); | 9 R visitBitAnd(HBitAnd node); |
10 R visitBitNot(HBitNot node); | 10 R visitBitNot(HBitNot node); |
(...skipping 20 matching lines...) Expand all Loading... |
31 R visitIndexAssign(HIndexAssign node); | 31 R visitIndexAssign(HIndexAssign node); |
32 R visitInterceptor(HInterceptor node); | 32 R visitInterceptor(HInterceptor node); |
33 R visitInvokeClosure(HInvokeClosure node); | 33 R visitInvokeClosure(HInvokeClosure node); |
34 R visitInvokeDynamicGetter(HInvokeDynamicGetter node); | 34 R visitInvokeDynamicGetter(HInvokeDynamicGetter node); |
35 R visitInvokeDynamicMethod(HInvokeDynamicMethod node); | 35 R visitInvokeDynamicMethod(HInvokeDynamicMethod node); |
36 R visitInvokeDynamicSetter(HInvokeDynamicSetter node); | 36 R visitInvokeDynamicSetter(HInvokeDynamicSetter node); |
37 R visitInvokeStatic(HInvokeStatic node); | 37 R visitInvokeStatic(HInvokeStatic node); |
38 R visitInvokeSuper(HInvokeSuper node); | 38 R visitInvokeSuper(HInvokeSuper node); |
39 R visitInvokeConstructorBody(HInvokeConstructorBody node); | 39 R visitInvokeConstructorBody(HInvokeConstructorBody node); |
40 R visitIs(HIs node); | 40 R visitIs(HIs node); |
| 41 R visitIsViaInterceptor(HIsViaInterceptor node); |
41 R visitLazyStatic(HLazyStatic node); | 42 R visitLazyStatic(HLazyStatic node); |
42 R visitLess(HLess node); | 43 R visitLess(HLess node); |
43 R visitLessEqual(HLessEqual node); | 44 R visitLessEqual(HLessEqual node); |
44 R visitLiteralList(HLiteralList node); | 45 R visitLiteralList(HLiteralList node); |
45 R visitLocalGet(HLocalGet node); | 46 R visitLocalGet(HLocalGet node); |
46 R visitLocalSet(HLocalSet node); | 47 R visitLocalSet(HLocalSet node); |
47 R visitLocalValue(HLocalValue node); | 48 R visitLocalValue(HLocalValue node); |
48 R visitLoopBranch(HLoopBranch node); | 49 R visitLoopBranch(HLoopBranch node); |
49 R visitMultiply(HMultiply node); | 50 R visitMultiply(HMultiply node); |
50 R visitNegate(HNegate node); | 51 R visitNegate(HNegate node); |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 visitStatic(HStatic node) => visitInstruction(node); | 329 visitStatic(HStatic node) => visitInstruction(node); |
329 visitStaticStore(HStaticStore node) => visitInstruction(node); | 330 visitStaticStore(HStaticStore node) => visitInstruction(node); |
330 visitStringConcat(HStringConcat node) => visitInstruction(node); | 331 visitStringConcat(HStringConcat node) => visitInstruction(node); |
331 visitStringify(HStringify node) => visitInstruction(node); | 332 visitStringify(HStringify node) => visitInstruction(node); |
332 visitThis(HThis node) => visitParameterValue(node); | 333 visitThis(HThis node) => visitParameterValue(node); |
333 visitThrow(HThrow node) => visitControlFlow(node); | 334 visitThrow(HThrow node) => visitControlFlow(node); |
334 visitThrowExpression(HThrowExpression node) => visitInstruction(node); | 335 visitThrowExpression(HThrowExpression node) => visitInstruction(node); |
335 visitTruncatingDivide(HTruncatingDivide node) => visitBinaryArithmetic(node); | 336 visitTruncatingDivide(HTruncatingDivide node) => visitBinaryArithmetic(node); |
336 visitTry(HTry node) => visitControlFlow(node); | 337 visitTry(HTry node) => visitControlFlow(node); |
337 visitIs(HIs node) => visitInstruction(node); | 338 visitIs(HIs node) => visitInstruction(node); |
| 339 visitIsViaInterceptor(HIsViaInterceptor node) => visitInstruction(node); |
338 visitTypeConversion(HTypeConversion node) => visitCheck(node); | 340 visitTypeConversion(HTypeConversion node) => visitCheck(node); |
339 visitTypeKnown(HTypeKnown node) => visitCheck(node); | 341 visitTypeKnown(HTypeKnown node) => visitCheck(node); |
340 visitReadTypeVariable(HReadTypeVariable node) => visitInstruction(node); | 342 visitReadTypeVariable(HReadTypeVariable node) => visitInstruction(node); |
341 visitFunctionType(HFunctionType node) => visitInstruction(node); | 343 visitFunctionType(HFunctionType node) => visitInstruction(node); |
342 visitVoidType(HVoidType node) => visitInstruction(node); | 344 visitVoidType(HVoidType node) => visitInstruction(node); |
343 visitInterfaceType(HInterfaceType node) => visitInstruction(node); | 345 visitInterfaceType(HInterfaceType node) => visitInstruction(node); |
344 visitDynamicType(HDynamicType node) => visitInstruction(node); | 346 visitDynamicType(HDynamicType node) => visitInstruction(node); |
345 } | 347 } |
346 | 348 |
347 class SubGraph { | 349 class SubGraph { |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 static const int INDEX_TYPECODE = 27; | 796 static const int INDEX_TYPECODE = 27; |
795 static const int IS_TYPECODE = 28; | 797 static const int IS_TYPECODE = 28; |
796 static const int INVOKE_DYNAMIC_TYPECODE = 29; | 798 static const int INVOKE_DYNAMIC_TYPECODE = 29; |
797 static const int SHIFT_RIGHT_TYPECODE = 30; | 799 static const int SHIFT_RIGHT_TYPECODE = 30; |
798 static const int READ_TYPE_VARIABLE_TYPECODE = 31; | 800 static const int READ_TYPE_VARIABLE_TYPECODE = 31; |
799 static const int FUNCTION_TYPE_TYPECODE = 32; | 801 static const int FUNCTION_TYPE_TYPECODE = 32; |
800 static const int VOID_TYPE_TYPECODE = 33; | 802 static const int VOID_TYPE_TYPECODE = 33; |
801 static const int INTERFACE_TYPE_TYPECODE = 34; | 803 static const int INTERFACE_TYPE_TYPECODE = 34; |
802 static const int DYNAMIC_TYPE_TYPECODE = 35; | 804 static const int DYNAMIC_TYPE_TYPECODE = 35; |
803 static const int TRUNCATING_DIVIDE_TYPECODE = 36; | 805 static const int TRUNCATING_DIVIDE_TYPECODE = 36; |
| 806 static const int IS_VIA_INTERCEPTOR_TYPECODE = 37; |
804 | 807 |
805 HInstruction(this.inputs, this.instructionType) | 808 HInstruction(this.inputs, this.instructionType) |
806 : id = idCounter++, usedBy = <HInstruction>[] { | 809 : id = idCounter++, usedBy = <HInstruction>[] { |
807 assert(inputs.every((e) => e != null)); | 810 assert(inputs.every((e) => e != null)); |
808 } | 811 } |
809 | 812 |
810 int get hashCode => id; | 813 int get hashCode => id; |
811 | 814 |
812 bool useGvn() => _useGvn; | 815 bool useGvn() => _useGvn; |
813 void setUseGvn() { _useGvn = true; } | 816 void setUseGvn() { _useGvn = true; } |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1230 | 1233 |
1231 /** | 1234 /** |
1232 * Return whether the instructions do not belong to a loop or | 1235 * Return whether the instructions do not belong to a loop or |
1233 * belong to the same loop. | 1236 * belong to the same loop. |
1234 */ | 1237 */ |
1235 bool hasSameLoopHeaderAs(HInstruction other) { | 1238 bool hasSameLoopHeaderAs(HInstruction other) { |
1236 return block.enclosingLoopHeader == other.block.enclosingLoopHeader; | 1239 return block.enclosingLoopHeader == other.block.enclosingLoopHeader; |
1237 } | 1240 } |
1238 } | 1241 } |
1239 | 1242 |
| 1243 /** |
| 1244 * Late instructions are used after the main optimization phases. They capture |
| 1245 * codegen decisions just prior to generating JavaScript. |
| 1246 */ |
| 1247 abstract class HLateInstruction extends HInstruction { |
| 1248 HLateInstruction(List<HInstruction> inputs, TypeMask type) |
| 1249 : super(inputs, type); |
| 1250 } |
| 1251 |
1240 class HBoolify extends HInstruction { | 1252 class HBoolify extends HInstruction { |
1241 HBoolify(HInstruction value, TypeMask type) | 1253 HBoolify(HInstruction value, TypeMask type) |
1242 : super(<HInstruction>[value], type) { | 1254 : super(<HInstruction>[value], type) { |
1243 setUseGvn(); | 1255 setUseGvn(); |
1244 } | 1256 } |
1245 | 1257 |
1246 accept(HVisitor visitor) => visitor.visitBoolify(this); | 1258 accept(HVisitor visitor) => visitor.visitBoolify(this); |
1247 int typeCode() => HInstruction.BOOLIFY_TYPECODE; | 1259 int typeCode() => HInstruction.BOOLIFY_TYPECODE; |
1248 bool typeEquals(other) => other is HBoolify; | 1260 bool typeEquals(other) => other is HBoolify; |
1249 bool dataEquals(HInstruction other) => true; | 1261 bool dataEquals(HInstruction other) => true; |
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2018 toString() => 'phi'; | 2030 toString() => 'phi'; |
2019 accept(HVisitor visitor) => visitor.visitPhi(this); | 2031 accept(HVisitor visitor) => visitor.visitPhi(this); |
2020 } | 2032 } |
2021 | 2033 |
2022 abstract class HRelational extends HInvokeBinary { | 2034 abstract class HRelational extends HInvokeBinary { |
2023 bool usesBoolifiedInterceptor = false; | 2035 bool usesBoolifiedInterceptor = false; |
2024 HRelational(left, right, selector, type) : super(left, right, selector, type); | 2036 HRelational(left, right, selector, type) : super(left, right, selector, type); |
2025 } | 2037 } |
2026 | 2038 |
2027 class HIdentity extends HRelational { | 2039 class HIdentity extends HRelational { |
| 2040 // Cached codegen decision. |
| 2041 String singleComparisonOp; // null, '===', '==' |
| 2042 |
2028 HIdentity(left, right, selector, type) : super(left, right, selector, type); | 2043 HIdentity(left, right, selector, type) : super(left, right, selector, type); |
2029 accept(HVisitor visitor) => visitor.visitIdentity(this); | 2044 accept(HVisitor visitor) => visitor.visitIdentity(this); |
2030 | 2045 |
2031 BinaryOperation operation(ConstantSystem constantSystem) | 2046 BinaryOperation operation(ConstantSystem constantSystem) |
2032 => constantSystem.identity; | 2047 => constantSystem.identity; |
2033 int typeCode() => HInstruction.IDENTITY_TYPECODE; | 2048 int typeCode() => HInstruction.IDENTITY_TYPECODE; |
2034 bool typeEquals(other) => other is HIdentity; | 2049 bool typeEquals(other) => other is HIdentity; |
2035 bool dataEquals(HInstruction other) => true; | 2050 bool dataEquals(HInstruction other) => true; |
2036 } | 2051 } |
2037 | 2052 |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2335 int typeCode() => HInstruction.IS_TYPECODE; | 2350 int typeCode() => HInstruction.IS_TYPECODE; |
2336 | 2351 |
2337 bool typeEquals(HInstruction other) => other is HIs; | 2352 bool typeEquals(HInstruction other) => other is HIs; |
2338 | 2353 |
2339 bool dataEquals(HIs other) { | 2354 bool dataEquals(HIs other) { |
2340 return typeExpression == other.typeExpression | 2355 return typeExpression == other.typeExpression |
2341 && kind == other.kind; | 2356 && kind == other.kind; |
2342 } | 2357 } |
2343 } | 2358 } |
2344 | 2359 |
| 2360 /** |
| 2361 * HIsViaInterceptor is a late-stage instruction for a type test that can be |
| 2362 * done entirely on an interceptor. It is not a HCheck because the checked |
| 2363 * input is not one of the inputs. |
| 2364 */ |
| 2365 class HIsViaInterceptor extends HLateInstruction { |
| 2366 final DartType typeExpression; |
| 2367 HIsViaInterceptor(this.typeExpression, HInstruction interceptor, |
| 2368 TypeMask type) |
| 2369 : super(<HInstruction>[interceptor], type) { |
| 2370 setUseGvn(); |
| 2371 } |
| 2372 |
| 2373 HInstruction get interceptor => inputs[0]; |
| 2374 |
| 2375 accept(HVisitor visitor) => visitor.visitIsViaInterceptor(this); |
| 2376 toString() => "$interceptor is $typeExpression"; |
| 2377 int typeCode() => HInstruction.IS_VIA_INTERCEPTOR_TYPECODE; |
| 2378 bool typeEquals(HInstruction other) => other is HIsViaInterceptor; |
| 2379 bool dataEquals(HIs other) { |
| 2380 return typeExpression == other.typeExpression; |
| 2381 } |
| 2382 } |
| 2383 |
2345 class HTypeConversion extends HCheck { | 2384 class HTypeConversion extends HCheck { |
2346 final DartType typeExpression; | 2385 final DartType typeExpression; |
2347 final int kind; | 2386 final int kind; |
2348 final Selector receiverTypeCheckSelector; | 2387 final Selector receiverTypeCheckSelector; |
2349 final bool contextIsTypeArguments; | 2388 final bool contextIsTypeArguments; |
2350 TypeMask checkedType; // Not final because we refine it. | 2389 TypeMask checkedType; // Not final because we refine it. |
2351 | 2390 |
2352 static const int CHECKED_MODE_CHECK = 0; | 2391 static const int CHECKED_MODE_CHECK = 0; |
2353 static const int ARGUMENT_TYPE_CHECK = 1; | 2392 static const int ARGUMENT_TYPE_CHECK = 1; |
2354 static const int CAST_TYPE_CHECK = 2; | 2393 static const int CAST_TYPE_CHECK = 2; |
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2910 class HDynamicType extends HRuntimeType { | 2949 class HDynamicType extends HRuntimeType { |
2911 HDynamicType(DynamicType dartType, TypeMask instructionType) | 2950 HDynamicType(DynamicType dartType, TypeMask instructionType) |
2912 : super(const <HInstruction>[], dartType, instructionType); | 2951 : super(const <HInstruction>[], dartType, instructionType); |
2913 | 2952 |
2914 accept(HVisitor visitor) => visitor.visitDynamicType(this); | 2953 accept(HVisitor visitor) => visitor.visitDynamicType(this); |
2915 | 2954 |
2916 int typeCode() => HInstruction.DYNAMIC_TYPE_TYPECODE; | 2955 int typeCode() => HInstruction.DYNAMIC_TYPE_TYPECODE; |
2917 | 2956 |
2918 bool typeEquals(HInstruction other) => other is HDynamicType; | 2957 bool typeEquals(HInstruction other) => other is HDynamicType; |
2919 } | 2958 } |
OLD | NEW |