| 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 'graph_builder.dart'; |
| 30 import 'jump_handler.dart' show SwitchCaseJumpHandler; | 31 import 'jump_handler.dart' show SwitchCaseJumpHandler; |
| 31 import 'locals_handler.dart'; | 32 import 'locals_handler.dart'; |
| 32 import 'types.dart'; | 33 import 'types.dart'; |
| 33 | 34 |
| 34 /// A helper class that abstracts all accesses of the AST from Kernel nodes. | 35 /// A helper class that abstracts all accesses of the AST from Kernel nodes. |
| 35 /// | 36 /// |
| 36 /// The goal is to remove all need for the AST from the Kernel SSA builder. | 37 /// The goal is to remove all need for the AST from the Kernel SSA builder. |
| 37 class KernelAstAdapter { | 38 class KernelAstAdapter { |
| 38 final Kernel kernel; | 39 final Kernel kernel; |
| 39 final JavaScriptBackend _backend; | 40 final JavaScriptBackend _backend; |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 bool isLazyStatic(ir.Member member) { | 366 bool isLazyStatic(ir.Member member) { |
| 366 if (member is ir.Field) { | 367 if (member is ir.Field) { |
| 367 FieldElement field = _nodeToElement[member]; | 368 FieldElement field = _nodeToElement[member]; |
| 368 return field.constant == null; | 369 return field.constant == null; |
| 369 } | 370 } |
| 370 return false; | 371 return false; |
| 371 } | 372 } |
| 372 | 373 |
| 373 LibraryElement get jsHelperLibrary => _backend.helpers.jsHelperLibrary; | 374 LibraryElement get jsHelperLibrary => _backend.helpers.jsHelperLibrary; |
| 374 | 375 |
| 375 KernelJumpTarget getJumpTarget(ir.TreeNode node) => | 376 KernelJumpTarget getJumpTarget(ir.TreeNode node, |
| 377 {bool isContinueTarget: false}) => |
| 376 _jumpTargets.putIfAbsent(node, () { | 378 _jumpTargets.putIfAbsent(node, () { |
| 377 if (node is ir.LabeledStatement && | 379 if (node is ir.LabeledStatement && |
| 378 _jumpTargets.containsKey((node as ir.LabeledStatement).body)) { | 380 _jumpTargets.containsKey((node as ir.LabeledStatement).body)) { |
| 379 return _jumpTargets[(node as ir.LabeledStatement).body]; | 381 return _jumpTargets[(node as ir.LabeledStatement).body]; |
| 380 } | 382 } |
| 381 return new KernelJumpTarget(node); | 383 return new KernelJumpTarget(node, makeContinueLabel: isContinueTarget); |
| 382 }); | 384 }); |
| 383 | 385 |
| 384 LabelDefinition getTargetLabel(ir.Node node) => | 386 LabelDefinition getTargetLabel(ir.Node node) => |
| 385 elements.getTargetLabel(getNode(node)); | 387 elements.getTargetLabel(getNode(node)); |
| 386 | 388 |
| 387 ir.Class get mapLiteralClass => | 389 ir.Class get mapLiteralClass => |
| 388 kernel.classes[_backend.helpers.mapLiteralClass]; | 390 kernel.classes[_backend.helpers.mapLiteralClass]; |
| 389 | 391 |
| 390 ir.Procedure get mapLiteralConstructor => | 392 ir.Procedure get mapLiteralConstructor => |
| 391 kernel.functions[_backend.helpers.mapLiteralConstructor]; | 393 kernel.functions[_backend.helpers.mapLiteralConstructor]; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 409 TypeMask get traceFromExceptionType => | 411 TypeMask get traceFromExceptionType => |
| 410 TypeMaskFactory.inferredReturnTypeForElement( | 412 TypeMaskFactory.inferredReturnTypeForElement( |
| 411 _backend.helpers.traceFromException, _globalInferenceResults); | 413 _backend.helpers.traceFromException, _globalInferenceResults); |
| 412 | 414 |
| 413 ir.Procedure get streamIteratorConstructor => | 415 ir.Procedure get streamIteratorConstructor => |
| 414 kernel.functions[_backend.helpers.streamIteratorConstructor]; | 416 kernel.functions[_backend.helpers.streamIteratorConstructor]; |
| 415 | 417 |
| 416 TypeMask get streamIteratorConstructorType => | 418 TypeMask get streamIteratorConstructorType => |
| 417 TypeMaskFactory.inferredReturnTypeForElement( | 419 TypeMaskFactory.inferredReturnTypeForElement( |
| 418 _backend.helpers.streamIteratorConstructor, _globalInferenceResults); | 420 _backend.helpers.streamIteratorConstructor, _globalInferenceResults); |
| 421 |
| 419 ir.Procedure get fallThroughError => | 422 ir.Procedure get fallThroughError => |
| 420 kernel.functions[_backend.helpers.fallThroughError]; | 423 kernel.functions[_backend.helpers.fallThroughError]; |
| 421 | 424 |
| 422 TypeMask get fallThroughErrorType => | 425 TypeMask get fallThroughErrorType => |
| 423 TypeMaskFactory.inferredReturnTypeForElement( | 426 TypeMaskFactory.inferredReturnTypeForElement( |
| 424 _backend.helpers.fallThroughError, _globalInferenceResults); | 427 _backend.helpers.fallThroughError, _globalInferenceResults); |
| 425 | 428 |
| 426 ir.Procedure get mapLiteralUntypedMaker => | 429 ir.Procedure get mapLiteralUntypedMaker => |
| 427 kernel.functions[_backend.helpers.mapLiteralUntypedMaker]; | 430 kernel.functions[_backend.helpers.mapLiteralUntypedMaker]; |
| 428 | 431 |
| (...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 /// If this jump target was not initially constructed with a LabeledStatement, | 988 /// If this jump target was not initially constructed with a LabeledStatement, |
| 986 /// this value is identical to targetStatement. | 989 /// this value is identical to targetStatement. |
| 987 ir.Node originalStatement; | 990 ir.Node originalStatement; |
| 988 | 991 |
| 989 @override | 992 @override |
| 990 bool isBreakTarget = false; | 993 bool isBreakTarget = false; |
| 991 | 994 |
| 992 @override | 995 @override |
| 993 bool isContinueTarget = false; | 996 bool isContinueTarget = false; |
| 994 | 997 |
| 995 KernelJumpTarget(this.targetStatement) { | 998 KernelJumpTarget(this.targetStatement, {bool makeContinueLabel = false}) { |
| 996 labels = <LabelDefinition>[]; | 999 labels = <LabelDefinition>[]; |
| 997 originalStatement = targetStatement; | 1000 originalStatement = targetStatement; |
| 998 if (targetStatement is ir.LabeledStatement) { | 1001 if (targetStatement is ir.LabeledStatement) { |
| 999 targetStatement = (targetStatement as ir.LabeledStatement).body; | 1002 targetStatement = (targetStatement as ir.LabeledStatement).body; |
| 1000 labels.add( | 1003 labels.add( |
| 1001 new LabelDefinitionX(null, 'L${index++}', this)..setBreakTarget()); | 1004 new LabelDefinitionX(null, 'L${index++}', this)..setBreakTarget()); |
| 1002 isBreakTarget = true; | 1005 isBreakTarget = true; |
| 1006 } else if (makeContinueLabel) { |
| 1007 labels.add( |
| 1008 new LabelDefinitionX(null, 'L${index++}', this)..setContinueTarget()); |
| 1009 isContinueTarget = true; |
| 1003 } | 1010 } |
| 1004 } | 1011 } |
| 1005 | 1012 |
| 1006 @override | 1013 @override |
| 1007 LabelDefinition addLabel(ast.Label label, String labelName) { | 1014 LabelDefinition addLabel(ast.Label label, String labelName) { |
| 1008 LabelDefinition result = new LabelDefinitionX(label, labelName, this); | 1015 LabelDefinition result = new LabelDefinitionX(label, labelName, this); |
| 1009 labels.add(result); | 1016 labels.add(result); |
| 1010 return result; | 1017 return result; |
| 1011 } | 1018 } |
| 1012 | 1019 |
| 1013 @override | 1020 @override |
| 1014 ExecutableElement get executableContext => null; | 1021 ExecutableElement get executableContext => null; |
| 1015 | 1022 |
| 1016 @override | 1023 @override |
| 1017 bool get isSwitch => targetStatement is ir.SwitchStatement; | 1024 bool get isSwitch => targetStatement is ir.SwitchStatement; |
| 1018 | 1025 |
| 1019 @override | 1026 @override |
| 1020 bool get isTarget => isBreakTarget || isContinueTarget; | 1027 bool get isTarget => isBreakTarget || isContinueTarget; |
| 1021 | 1028 |
| 1022 @override | 1029 @override |
| 1023 List<LabelDefinition> labels; | 1030 List<LabelDefinition> labels; |
| 1024 | 1031 |
| 1025 @override | 1032 @override |
| 1026 String get name => null; | 1033 String get name => 'target'; |
| 1027 | 1034 |
| 1035 // TODO(efortuna): In the original version, this nesting level is specified at |
| 1036 // jump target construction time, by the resolver. Because these are |
| 1037 // instantiated later, we don't have that information. When we move fully over |
| 1038 // to the kernel model, we can pass the nesting level in KernelJumpTarget's |
| 1039 // constructor. |
| 1028 @override | 1040 @override |
| 1029 int get nestingLevel => 1; | 1041 int get nestingLevel => 0; |
| 1030 | 1042 |
| 1031 @override | 1043 @override |
| 1032 ast.Node get statement => null; | 1044 ast.Node get statement => null; |
| 1033 | 1045 |
| 1034 String toString() => 'Target:$targetStatement'; | 1046 String toString() => 'Target:$targetStatement'; |
| 1035 } | 1047 } |
| 1048 |
| 1049 /// Special [JumpHandler] implementation used to handle continue statements |
| 1050 /// targeting switch cases. |
| 1051 class KernelSwitchCaseJumpHandler extends SwitchCaseJumpHandler { |
| 1052 KernelSwitchCaseJumpHandler(GraphBuilder builder, JumpTarget target, |
| 1053 ir.SwitchStatement switchStatement, KernelAstAdapter astAdapter) |
| 1054 : super(builder, target) { |
| 1055 // The switch case indices must match those computed in |
| 1056 // [KernelSsaBuilder.buildSwitchCaseConstants]. |
| 1057 // Switch indices are 1-based so we can bypass the synthetic loop when no |
| 1058 // cases match simply by branching on the index (which defaults to null). |
| 1059 // TODO |
| 1060 int switchIndex = 1; |
| 1061 for (ir.SwitchCase switchCase in switchStatement.cases) { |
| 1062 JumpTarget continueTarget = |
| 1063 astAdapter.getJumpTarget(switchCase, isContinueTarget: true); |
| 1064 assert(continueTarget is KernelJumpTarget); |
| 1065 targetIndexMap[continueTarget] = switchIndex; |
| 1066 assert(builder.jumpTargets[continueTarget] == null); |
| 1067 builder.jumpTargets[continueTarget] = this; |
| 1068 switchIndex++; |
| 1069 } |
| 1070 } |
| 1071 } |
| OLD | NEW |