| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'package:js_runtime/shared/embedded_names.dart'; | 5 import 'package:js_runtime/shared/embedded_names.dart'; |
| 6 import 'package:kernel/ast.dart' as ir; | 6 import 'package:kernel/ast.dart' as ir; |
| 7 | 7 |
| 8 import '../common.dart'; | 8 import '../common.dart'; |
| 9 import '../common/names.dart'; | 9 import '../common/names.dart'; |
| 10 import '../compiler.dart'; | 10 import '../compiler.dart'; |
| 11 import '../constants/expressions.dart'; | 11 import '../constants/expressions.dart'; |
| 12 import '../constants/values.dart'; | 12 import '../constants/values.dart'; |
| 13 import '../elements/resolution_types.dart'; | 13 import '../elements/resolution_types.dart'; |
| 14 import '../elements/elements.dart'; | 14 import '../elements/elements.dart'; |
| 15 import '../elements/modelx.dart'; | 15 import '../elements/modelx.dart'; |
| 16 import '../js/js.dart' as js; | 16 import '../js/js.dart' as js; |
| 17 import '../js_backend/backend_helpers.dart'; | 17 import '../js_backend/backend_helpers.dart'; |
| 18 import '../js_backend/js_backend.dart'; | 18 import '../js_backend/js_backend.dart'; |
| 19 import '../kernel/kernel.dart'; | 19 import '../kernel/kernel.dart'; |
| 20 import '../kernel/kernel_debug.dart'; | 20 import '../kernel/kernel_debug.dart'; |
| 21 import '../native/native.dart' as native; | 21 import '../native/native.dart' as native; |
| 22 import '../resolution/tree_elements.dart'; | 22 import '../resolution/tree_elements.dart'; |
| 23 import '../tree/tree.dart' as ast; | 23 import '../tree/tree.dart' as ast; |
| 24 import '../types/masks.dart'; | 24 import '../types/masks.dart'; |
| 25 import '../types/types.dart'; | 25 import '../types/types.dart'; |
| 26 import '../universe/call_structure.dart'; | 26 import '../universe/call_structure.dart'; |
| 27 import '../universe/selector.dart'; | 27 import '../universe/selector.dart'; |
| 28 import '../universe/side_effects.dart'; | 28 import '../universe/side_effects.dart'; |
| 29 import '../world.dart'; | 29 import '../world.dart'; |
| 30 import 'jump_handler.dart' show SwitchCaseJumpHandler; |
| 30 import 'locals_handler.dart'; | 31 import 'locals_handler.dart'; |
| 31 import 'types.dart'; | 32 import 'types.dart'; |
| 32 | 33 |
| 33 /// A helper class that abstracts all accesses of the AST from Kernel nodes. | 34 /// A helper class that abstracts all accesses of the AST from Kernel nodes. |
| 34 /// | 35 /// |
| 35 /// The goal is to remove all need for the AST from the Kernel SSA builder. | 36 /// The goal is to remove all need for the AST from the Kernel SSA builder. |
| 36 class KernelAstAdapter { | 37 class KernelAstAdapter { |
| 37 final Kernel kernel; | 38 final Kernel kernel; |
| 38 final JavaScriptBackend _backend; | 39 final JavaScriptBackend _backend; |
| 39 final Map<ir.Node, ast.Node> _nodeToAst; | 40 final Map<ir.Node, ast.Node> _nodeToAst; |
| 40 final Map<ir.Node, Element> _nodeToElement; | 41 final Map<ir.Node, Element> _nodeToElement; |
| 41 final Map<ir.VariableDeclaration, SyntheticLocal> _syntheticLocals = | 42 final Map<ir.VariableDeclaration, SyntheticLocal> _syntheticLocals = |
| 42 <ir.VariableDeclaration, SyntheticLocal>{}; | 43 <ir.VariableDeclaration, SyntheticLocal>{}; |
| 43 final Map<ir.LabeledStatement, KernelJumpTarget> _jumpTargets = | 44 // TODO(efortuna): In an ideal world the TreeNodes should be some common |
| 44 <ir.LabeledStatement, KernelJumpTarget>{}; | 45 // interface we create for both ir.Statements and ir.SwitchCase (the |
| 46 // ContinueSwitchStatement's target is a SwitchCase) rather than general |
| 47 // TreeNode. Talking to Asger about this. |
| 48 final Map<ir.TreeNode, KernelJumpTarget> _jumpTargets = |
| 49 <ir.TreeNode, KernelJumpTarget>{}; |
| 45 DartTypeConverter _typeConverter; | 50 DartTypeConverter _typeConverter; |
| 46 ResolvedAst _resolvedAst; | 51 ResolvedAst _resolvedAst; |
| 47 | 52 |
| 48 /// Sometimes for resolution the resolved AST element needs to change (for | 53 /// Sometimes for resolution the resolved AST element needs to change (for |
| 49 /// example, if we're inlining, or if we're in a constructor, but then also | 54 /// example, if we're inlining, or if we're in a constructor, but then also |
| 50 /// constructing the field values). We keep track of this with a stack. | 55 /// constructing the field values). We keep track of this with a stack. |
| 51 final List<ResolvedAst> _resolvedAstStack = <ResolvedAst>[]; | 56 final List<ResolvedAst> _resolvedAstStack = <ResolvedAst>[]; |
| 52 | 57 |
| 53 KernelAstAdapter(this.kernel, this._backend, this._resolvedAst, | 58 KernelAstAdapter(this.kernel, this._backend, this._resolvedAst, |
| 54 this._nodeToAst, this._nodeToElement) { | 59 this._nodeToAst, this._nodeToElement) { |
| 60 KernelJumpTarget.index = 0; |
| 55 // TODO(het): Maybe just use all of the kernel maps directly? | 61 // TODO(het): Maybe just use all of the kernel maps directly? |
| 56 for (FieldElement fieldElement in kernel.fields.keys) { | 62 for (FieldElement fieldElement in kernel.fields.keys) { |
| 57 _nodeToElement[kernel.fields[fieldElement]] = fieldElement; | 63 _nodeToElement[kernel.fields[fieldElement]] = fieldElement; |
| 58 } | 64 } |
| 59 for (FunctionElement functionElement in kernel.functions.keys) { | 65 for (FunctionElement functionElement in kernel.functions.keys) { |
| 60 _nodeToElement[kernel.functions[functionElement]] = functionElement; | 66 _nodeToElement[kernel.functions[functionElement]] = functionElement; |
| 61 } | 67 } |
| 62 for (ClassElement classElement in kernel.classes.keys) { | 68 for (ClassElement classElement in kernel.classes.keys) { |
| 63 _nodeToElement[kernel.classes[classElement]] = classElement; | 69 _nodeToElement[kernel.classes[classElement]] = classElement; |
| 64 } | 70 } |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 bool isLazyStatic(ir.Member member) { | 365 bool isLazyStatic(ir.Member member) { |
| 360 if (member is ir.Field) { | 366 if (member is ir.Field) { |
| 361 FieldElement field = _nodeToElement[member]; | 367 FieldElement field = _nodeToElement[member]; |
| 362 return field.constant == null; | 368 return field.constant == null; |
| 363 } | 369 } |
| 364 return false; | 370 return false; |
| 365 } | 371 } |
| 366 | 372 |
| 367 LibraryElement get jsHelperLibrary => _backend.helpers.jsHelperLibrary; | 373 LibraryElement get jsHelperLibrary => _backend.helpers.jsHelperLibrary; |
| 368 | 374 |
| 369 JumpTarget getTargetDefinition(ir.Node node) => | 375 KernelJumpTarget getJumpTarget(ir.TreeNode node) => |
| 370 elements.getTargetDefinition(getNode(node)); | 376 _jumpTargets.putIfAbsent(node, () { |
| 371 | 377 if (node is ir.LabeledStatement && |
| 372 JumpTarget getTargetOf(ir.Node node) => elements.getTargetOf(getNode(node)); | 378 _jumpTargets.containsKey((node as ir.LabeledStatement).body)) { |
| 373 | 379 return _jumpTargets[(node as ir.LabeledStatement).body]; |
| 374 KernelJumpTarget getJumpTarget(ir.LabeledStatement labeledStatement) => | 380 } |
| 375 _jumpTargets.putIfAbsent(labeledStatement, () { | 381 return new KernelJumpTarget(node); |
| 376 return new KernelJumpTarget(); | |
| 377 }); | 382 }); |
| 378 | 383 |
| 379 LabelDefinition getTargetLabel(ir.Node node) => | 384 LabelDefinition getTargetLabel(ir.Node node) => |
| 380 elements.getTargetLabel(getNode(node)); | 385 elements.getTargetLabel(getNode(node)); |
| 381 | 386 |
| 382 ir.Class get mapLiteralClass => | 387 ir.Class get mapLiteralClass => |
| 383 kernel.classes[_backend.helpers.mapLiteralClass]; | 388 kernel.classes[_backend.helpers.mapLiteralClass]; |
| 384 | 389 |
| 385 ir.Procedure get mapLiteralConstructor => | 390 ir.Procedure get mapLiteralConstructor => |
| 386 kernel.functions[_backend.helpers.mapLiteralConstructor]; | 391 kernel.functions[_backend.helpers.mapLiteralConstructor]; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 404 TypeMask get traceFromExceptionType => | 409 TypeMask get traceFromExceptionType => |
| 405 TypeMaskFactory.inferredReturnTypeForElement( | 410 TypeMaskFactory.inferredReturnTypeForElement( |
| 406 _backend.helpers.traceFromException, _globalInferenceResults); | 411 _backend.helpers.traceFromException, _globalInferenceResults); |
| 407 | 412 |
| 408 ir.Procedure get streamIteratorConstructor => | 413 ir.Procedure get streamIteratorConstructor => |
| 409 kernel.functions[_backend.helpers.streamIteratorConstructor]; | 414 kernel.functions[_backend.helpers.streamIteratorConstructor]; |
| 410 | 415 |
| 411 TypeMask get streamIteratorConstructorType => | 416 TypeMask get streamIteratorConstructorType => |
| 412 TypeMaskFactory.inferredReturnTypeForElement( | 417 TypeMaskFactory.inferredReturnTypeForElement( |
| 413 _backend.helpers.streamIteratorConstructor, _globalInferenceResults); | 418 _backend.helpers.streamIteratorConstructor, _globalInferenceResults); |
| 419 ir.Procedure get fallThroughError => |
| 420 kernel.functions[_backend.helpers.fallThroughError]; |
| 421 |
| 422 TypeMask get fallThroughErrorType => |
| 423 TypeMaskFactory.inferredReturnTypeForElement( |
| 424 _backend.helpers.fallThroughError, _globalInferenceResults); |
| 414 | 425 |
| 415 ir.Procedure get mapLiteralUntypedMaker => | 426 ir.Procedure get mapLiteralUntypedMaker => |
| 416 kernel.functions[_backend.helpers.mapLiteralUntypedMaker]; | 427 kernel.functions[_backend.helpers.mapLiteralUntypedMaker]; |
| 417 | 428 |
| 418 MemberElement get jsIndexableLength => _backend.helpers.jsIndexableLength; | 429 MemberElement get jsIndexableLength => _backend.helpers.jsIndexableLength; |
| 419 | 430 |
| 420 ir.Procedure get checkConcurrentModificationError => | 431 ir.Procedure get checkConcurrentModificationError => |
| 421 kernel.functions[_backend.helpers.checkConcurrentModificationError]; | 432 kernel.functions[_backend.helpers.checkConcurrentModificationError]; |
| 422 | 433 |
| 423 TypeMask get checkConcurrentModificationErrorReturnType => | 434 TypeMask get checkConcurrentModificationErrorReturnType => |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 954 | 965 |
| 955 @override | 966 @override |
| 956 ConstantExpression visitStringLiteral(ir.StringLiteral node) { | 967 ConstantExpression visitStringLiteral(ir.StringLiteral node) { |
| 957 return new StringConstantExpression(node.value); | 968 return new StringConstantExpression(node.value); |
| 958 } | 969 } |
| 959 } | 970 } |
| 960 | 971 |
| 961 class KernelJumpTarget extends JumpTarget { | 972 class KernelJumpTarget extends JumpTarget { |
| 962 static int index = 0; | 973 static int index = 0; |
| 963 | 974 |
| 964 KernelJumpTarget() { | 975 /// Pointer to the actual executable statements that a jump target refers to. |
| 965 labels = <LabelDefinition>[ | 976 /// If this jump target was not initially constructed with a LabeledStatement, |
| 966 new LabelDefinitionX(null, 'l${index++}', this)..setBreakTarget() | 977 /// this value is identical to originalStatement. |
| 967 ]; | 978 // TODO(efortuna): In an ideal world the Node should be some common |
| 979 // interface we create for both ir.Statements and ir.SwitchCase (the |
| 980 // ContinueSwitchStatement's target is a SwitchCase) rather than general |
| 981 // Node. Talking to Asger about this. |
| 982 ir.Node targetStatement; |
| 983 |
| 984 /// The original statement used to construct this jump target. |
| 985 /// If this jump target was not initially constructed with a LabeledStatement, |
| 986 /// this value is identical to targetStatement. |
| 987 ir.Node originalStatement; |
| 988 |
| 989 @override |
| 990 bool isBreakTarget = false; |
| 991 |
| 992 @override |
| 993 bool isContinueTarget = false; |
| 994 |
| 995 KernelJumpTarget(this.targetStatement) { |
| 996 labels = <LabelDefinition>[]; |
| 997 originalStatement = targetStatement; |
| 998 if (targetStatement is ir.LabeledStatement) { |
| 999 targetStatement = (targetStatement as ir.LabeledStatement).body; |
| 1000 labels.add( |
| 1001 new LabelDefinitionX(null, 'L${index++}', this)..setBreakTarget()); |
| 1002 isBreakTarget = true; |
| 1003 } |
| 968 } | 1004 } |
| 969 | 1005 |
| 970 @override | 1006 @override |
| 971 bool get isBreakTarget => true; | |
| 972 | |
| 973 set isBreakTarget(bool x) { | |
| 974 // do nothing, these are always break targets | |
| 975 } | |
| 976 | |
| 977 @override | |
| 978 bool get isContinueTarget => false; | |
| 979 | |
| 980 set isContinueTarget(bool x) { | |
| 981 // do nothing, these are always break targets | |
| 982 } | |
| 983 | |
| 984 @override | |
| 985 LabelDefinition addLabel(ast.Label label, String labelName) { | 1007 LabelDefinition addLabel(ast.Label label, String labelName) { |
| 986 LabelDefinition result = new LabelDefinitionX(label, labelName, this); | 1008 LabelDefinition result = new LabelDefinitionX(label, labelName, this); |
| 987 labels.add(result); | 1009 labels.add(result); |
| 988 return result; | 1010 return result; |
| 989 } | 1011 } |
| 990 | 1012 |
| 991 @override | 1013 @override |
| 992 ExecutableElement get executableContext => null; | 1014 ExecutableElement get executableContext => null; |
| 993 | 1015 |
| 994 @override | 1016 @override |
| 995 bool get isSwitch => false; | 1017 bool get isSwitch => targetStatement is ir.SwitchStatement; |
| 996 | 1018 |
| 997 @override | 1019 @override |
| 998 bool get isTarget => true; | 1020 bool get isTarget => isBreakTarget || isContinueTarget; |
| 999 | 1021 |
| 1000 @override | 1022 @override |
| 1001 List<LabelDefinition> labels; | 1023 List<LabelDefinition> labels; |
| 1002 | 1024 |
| 1003 @override | 1025 @override |
| 1004 String get name => null; | 1026 String get name => null; |
| 1005 | 1027 |
| 1006 @override | 1028 @override |
| 1007 int get nestingLevel => 1; | 1029 int get nestingLevel => 1; |
| 1008 | 1030 |
| 1009 @override | 1031 @override |
| 1010 ast.Node get statement => null; | 1032 ast.Node get statement => null; |
| 1033 |
| 1034 String toString() => 'Target:$targetStatement'; |
| 1011 } | 1035 } |
| OLD | NEW |