| 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 class SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
| 8 SsaCodeGeneratorTask generator; | 8 SsaCodeGeneratorTask generator; |
| 9 SsaBuilderTask builder; | 9 SsaBuilderTask builder; |
| 10 SsaOptimizerTask optimizer; | 10 SsaOptimizerTask optimizer; |
| (...skipping 959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 970 for (JumpTarget target in targetIndexMap.keys) { | 970 for (JumpTarget target in targetIndexMap.keys) { |
| 971 builder.jumpTargets.remove(target); | 971 builder.jumpTargets.remove(target); |
| 972 } | 972 } |
| 973 super.close(); | 973 super.close(); |
| 974 } | 974 } |
| 975 } | 975 } |
| 976 | 976 |
| 977 /** | 977 /** |
| 978 * This class builds SSA nodes for functions represented in AST. | 978 * This class builds SSA nodes for functions represented in AST. |
| 979 */ | 979 */ |
| 980 class SsaBuilder extends ResolvedVisitor { | 980 class SsaBuilder extends NewResolvedVisitor { |
| 981 final Compiler compiler; | 981 final Compiler compiler; |
| 982 final JavaScriptBackend backend; | 982 final JavaScriptBackend backend; |
| 983 final ConstantSystem constantSystem; | 983 final ConstantSystem constantSystem; |
| 984 final CodegenWorkItem work; | 984 final CodegenWorkItem work; |
| 985 final RuntimeTypes rti; | 985 final RuntimeTypes rti; |
| 986 final bool generateSourceMap; | 986 final bool generateSourceMap; |
| 987 bool inLazyInitializerExpression = false; | 987 bool inLazyInitializerExpression = false; |
| 988 | 988 |
| 989 /* This field is used by the native handler. */ | 989 /* This field is used by the native handler. */ |
| 990 final NativeEmitter nativeEmitter; | 990 final NativeEmitter nativeEmitter; |
| (...skipping 2132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3123 isAnd: ("&&" == op.source)); | 3123 isAnd: ("&&" == op.source)); |
| 3124 } | 3124 } |
| 3125 | 3125 |
| 3126 void visitLogicalNot(ast.Send node) { | 3126 void visitLogicalNot(ast.Send node) { |
| 3127 assert(node.argumentsNode is ast.Prefix); | 3127 assert(node.argumentsNode is ast.Prefix); |
| 3128 visit(node.receiver); | 3128 visit(node.receiver); |
| 3129 HNot not = new HNot(popBoolified(), backend.boolType); | 3129 HNot not = new HNot(popBoolified(), backend.boolType); |
| 3130 pushWithPosition(not, node); | 3130 pushWithPosition(not, node); |
| 3131 } | 3131 } |
| 3132 | 3132 |
| 3133 void visitUnary(ast.Send node, ast.Operator op) { | 3133 void visitUnarySend(ast.Send node, ast.Operator op) { |
| 3134 assert(node.argumentsNode is ast.Prefix); | 3134 assert(node.argumentsNode is ast.Prefix); |
| 3135 visit(node.receiver); | 3135 visit(node.receiver); |
| 3136 assert(!identical(op.token.kind, PLUS_TOKEN)); | 3136 assert(!identical(op.token.kind, PLUS_TOKEN)); |
| 3137 HInstruction operand = pop(); | 3137 HInstruction operand = pop(); |
| 3138 | 3138 |
| 3139 // See if we can constant-fold right away. This avoids rewrites later on. | 3139 // See if we can constant-fold right away. This avoids rewrites later on. |
| 3140 if (operand is HConstant) { | 3140 if (operand is HConstant) { |
| 3141 UnaryOperation operation = constantSystem.lookupUnary(op.source); | 3141 UnaryOperation operation = constantSystem.lookupUnary(op.source); |
| 3142 HConstant constant = operand; | 3142 HConstant constant = operand; |
| 3143 ConstantValue folded = operation.fold(constant.constant); | 3143 ConstantValue folded = operation.fold(constant.constant); |
| 3144 if (folded != null) { | 3144 if (folded != null) { |
| 3145 stack.add(graph.addConstant(folded, compiler)); | 3145 stack.add(graph.addConstant(folded, compiler)); |
| 3146 return; | 3146 return; |
| 3147 } | 3147 } |
| 3148 } | 3148 } |
| 3149 | 3149 |
| 3150 pushInvokeDynamic(node, elements.getSelector(node), [operand]); | 3150 pushInvokeDynamic(node, elements.getSelector(node), [operand]); |
| 3151 } | 3151 } |
| 3152 | 3152 |
| 3153 void visitBinary(HInstruction left, | 3153 void visitBinarySend(HInstruction left, |
| 3154 ast.Operator op, | 3154 ast.Operator op, |
| 3155 HInstruction right, | 3155 HInstruction right, |
| 3156 Selector selector, | 3156 Selector selector, |
| 3157 ast.Send send) { | 3157 ast.Send send) { |
| 3158 switch (op.source) { | 3158 switch (op.source) { |
| 3159 case "===": | 3159 case "===": |
| 3160 pushWithPosition( | 3160 pushWithPosition( |
| 3161 new HIdentity(left, right, null, backend.boolType), op); | 3161 new HIdentity(left, right, null, backend.boolType), op); |
| 3162 return; | 3162 return; |
| 3163 case "!==": | 3163 case "!==": |
| 3164 HIdentity eq = new HIdentity(left, right, null, backend.boolType); | 3164 HIdentity eq = new HIdentity(left, right, null, backend.boolType); |
| 3165 add(eq); | 3165 add(eq); |
| 3166 pushWithPosition(new HNot(eq, backend.boolType), op); | 3166 pushWithPosition(new HNot(eq, backend.boolType), op); |
| 3167 return; | 3167 return; |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3415 visitOperatorSend(ast.Send node) { | 3415 visitOperatorSend(ast.Send node) { |
| 3416 ast.Operator op = node.selector; | 3416 ast.Operator op = node.selector; |
| 3417 if ("[]" == op.source) { | 3417 if ("[]" == op.source) { |
| 3418 visitDynamicSend(node); | 3418 visitDynamicSend(node); |
| 3419 } else if ("&&" == op.source || | 3419 } else if ("&&" == op.source || |
| 3420 "||" == op.source) { | 3420 "||" == op.source) { |
| 3421 visitLogicalAndOr(node, op); | 3421 visitLogicalAndOr(node, op); |
| 3422 } else if ("!" == op.source) { | 3422 } else if ("!" == op.source) { |
| 3423 visitLogicalNot(node); | 3423 visitLogicalNot(node); |
| 3424 } else if (node.argumentsNode is ast.Prefix) { | 3424 } else if (node.argumentsNode is ast.Prefix) { |
| 3425 visitUnary(node, op); | 3425 visitUnarySend(node, op); |
| 3426 } else if ("is" == op.source) { | 3426 } else if ("is" == op.source) { |
| 3427 visitIsSend(node); | 3427 visitIsSend(node); |
| 3428 } else if ("as" == op.source) { | 3428 } else if ("as" == op.source) { |
| 3429 visit(node.receiver); | 3429 visit(node.receiver); |
| 3430 HInstruction expression = pop(); | 3430 HInstruction expression = pop(); |
| 3431 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); | 3431 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); |
| 3432 if (type.isMalformed) { | 3432 if (type.isMalformed) { |
| 3433 ErroneousElement element = type.element; | 3433 ErroneousElement element = type.element; |
| 3434 generateTypeError(node, element.message); | 3434 generateTypeError(node, element.message); |
| 3435 } else { | 3435 } else { |
| 3436 HInstruction converted = buildTypeConversion( | 3436 HInstruction converted = buildTypeConversion( |
| 3437 expression, | 3437 expression, |
| 3438 localsHandler.substInContext(type), | 3438 localsHandler.substInContext(type), |
| 3439 HTypeConversion.CAST_TYPE_CHECK); | 3439 HTypeConversion.CAST_TYPE_CHECK); |
| 3440 if (converted != expression) add(converted); | 3440 if (converted != expression) add(converted); |
| 3441 stack.add(converted); | 3441 stack.add(converted); |
| 3442 } | 3442 } |
| 3443 } else { | 3443 } else { |
| 3444 visit(node.receiver); | 3444 visit(node.receiver); |
| 3445 visit(node.argumentsNode); | 3445 visit(node.argumentsNode); |
| 3446 var right = pop(); | 3446 var right = pop(); |
| 3447 var left = pop(); | 3447 var left = pop(); |
| 3448 visitBinary(left, op, right, elements.getSelector(node), node); | 3448 visitBinarySend(left, op, right, elements.getSelector(node), node); |
| 3449 } | 3449 } |
| 3450 } | 3450 } |
| 3451 | 3451 |
| 3452 void visitIsSend(ast.Send node) { | 3452 void visitIsSend(ast.Send node) { |
| 3453 visit(node.receiver); | 3453 visit(node.receiver); |
| 3454 HInstruction expression = pop(); | 3454 HInstruction expression = pop(); |
| 3455 bool isNot = node.isIsNotCheck; | 3455 bool isNot = node.isIsNotCheck; |
| 3456 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); | 3456 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); |
| 3457 HInstruction instruction = buildIsNode(node, type, expression); | 3457 HInstruction instruction = buildIsNode(node, type, expression); |
| 3458 if (isNot) { | 3458 if (isNot) { |
| (...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4527 DartType instance = type.asInstanceOf(supertype.element); | 4527 DartType instance = type.asInstanceOf(supertype.element); |
| 4528 compiler.types.checkTypeVariableBounds(instance, | 4528 compiler.types.checkTypeVariableBounds(instance, |
| 4529 addTypeVariableBoundCheck); | 4529 addTypeVariableBoundCheck); |
| 4530 if (definitelyFails) { | 4530 if (definitelyFails) { |
| 4531 return true; | 4531 return true; |
| 4532 } | 4532 } |
| 4533 } | 4533 } |
| 4534 return false; | 4534 return false; |
| 4535 } | 4535 } |
| 4536 | 4536 |
| 4537 visitAssert(node) { | 4537 visitAssertSend(node) { |
| 4538 if (!compiler.enableUserAssertions) { | 4538 if (!compiler.enableUserAssertions) { |
| 4539 stack.add(graph.addConstantNull(compiler)); | 4539 stack.add(graph.addConstantNull(compiler)); |
| 4540 return; | 4540 return; |
| 4541 } | 4541 } |
| 4542 // TODO(johnniwinther): Don't handle assert like a regular static call. | 4542 // TODO(johnniwinther): Don't handle assert like a regular static call. |
| 4543 // It breaks the selector name check since the assert helper method cannot | 4543 // It breaks the selector name check since the assert helper method cannot |
| 4544 // be called `assert` and therefore does not match the selector like a | 4544 // be called `assert` and therefore does not match the selector like a |
| 4545 // regular method. | 4545 // regular method. |
| 4546 visitStaticSend(node); | 4546 visitStaticSend(node); |
| 4547 } | 4547 } |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4627 type = localsHandler.substInContext(type); | 4627 type = localsHandler.substInContext(type); |
| 4628 HInstruction value = analyzeTypeArgument(type); | 4628 HInstruction value = analyzeTypeArgument(type); |
| 4629 pushInvokeStatic(node, | 4629 pushInvokeStatic(node, |
| 4630 backend.getRuntimeTypeToString(), | 4630 backend.getRuntimeTypeToString(), |
| 4631 [value], | 4631 [value], |
| 4632 backend.stringType); | 4632 backend.stringType); |
| 4633 pushInvokeStatic(node, | 4633 pushInvokeStatic(node, |
| 4634 backend.getCreateRuntimeType(), | 4634 backend.getCreateRuntimeType(), |
| 4635 [pop()]); | 4635 [pop()]); |
| 4636 } else { | 4636 } else { |
| 4637 internalError('unexpected type kind ${type.kind}', node: node); | 4637 internalError(node, 'unexpected type kind ${type.kind}'); |
| 4638 } | 4638 } |
| 4639 if (node.isCall) { | 4639 if (node.isCall) { |
| 4640 // This send is of the form 'e(...)', where e is resolved to a type | 4640 // This send is of the form 'e(...)', where e is resolved to a type |
| 4641 // reference. We create a regular closure call on the result of the type | 4641 // reference. We create a regular closure call on the result of the type |
| 4642 // reference instead of creating a NoSuchMethodError to avoid pulling it | 4642 // reference instead of creating a NoSuchMethodError to avoid pulling it |
| 4643 // in if it is not used (e.g., in a try/catch). | 4643 // in if it is not used (e.g., in a try/catch). |
| 4644 HInstruction target = pop(); | 4644 HInstruction target = pop(); |
| 4645 Selector selector = elements.getSelector(node); | 4645 Selector selector = elements.getSelector(node); |
| 4646 List<HInstruction> inputs = <HInstruction>[target]; | 4646 List<HInstruction> inputs = <HInstruction>[target]; |
| 4647 addDynamicSendArgumentsToList(node, inputs); | 4647 addDynamicSendArgumentsToList(node, inputs); |
| 4648 Selector closureSelector = new Selector.callClosureFrom(selector); | 4648 Selector closureSelector = new Selector.callClosureFrom(selector); |
| 4649 push(new HInvokeClosure(closureSelector, inputs, backend.dynamicType)); | 4649 push(new HInvokeClosure(closureSelector, inputs, backend.dynamicType)); |
| 4650 } | 4650 } |
| 4651 } | 4651 } |
| 4652 | 4652 |
| 4653 visitGetterSend(ast.Send node) { | 4653 visitGetterSend(ast.Send node) { |
| 4654 generateIsDeferredLoadedCheckIfNeeded(node); | 4654 generateIsDeferredLoadedCheckIfNeeded(node); |
| 4655 generateGetter(node, elements[node]); | 4655 generateGetter(node, elements[node]); |
| 4656 } | 4656 } |
| 4657 | 4657 |
| 4658 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. | 4658 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. |
| 4659 internalError(String reason, {ast.Node node}) { | 4659 internalError(Spannable node, String reason) { |
| 4660 compiler.internalError(node, reason); | 4660 compiler.internalError(node, reason); |
| 4661 } | 4661 } |
| 4662 | 4662 |
| 4663 void generateError(ast.Node node, String message, Element helper) { | 4663 void generateError(ast.Node node, String message, Element helper) { |
| 4664 HInstruction errorMessage = addConstantString(message); | 4664 HInstruction errorMessage = addConstantString(message); |
| 4665 pushInvokeStatic(node, helper, [errorMessage]); | 4665 pushInvokeStatic(node, helper, [errorMessage]); |
| 4666 } | 4666 } |
| 4667 | 4667 |
| 4668 void generateRuntimeError(ast.Node node, String message) { | 4668 void generateRuntimeError(ast.Node node, String message) { |
| 4669 generateError(node, message, backend.getThrowRuntimeError()); | 4669 generateError(node, message, backend.getThrowRuntimeError()); |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4914 HInstruction receiver, | 4914 HInstruction receiver, |
| 4915 Link<ast.Node> arguments) { | 4915 Link<ast.Node> arguments) { |
| 4916 HInstruction rhs; | 4916 HInstruction rhs; |
| 4917 if (node.isPrefix || node.isPostfix) { | 4917 if (node.isPrefix || node.isPostfix) { |
| 4918 rhs = graph.addConstantInt(1, compiler); | 4918 rhs = graph.addConstantInt(1, compiler); |
| 4919 } else { | 4919 } else { |
| 4920 visit(arguments.head); | 4920 visit(arguments.head); |
| 4921 assert(arguments.tail.isEmpty); | 4921 assert(arguments.tail.isEmpty); |
| 4922 rhs = pop(); | 4922 rhs = pop(); |
| 4923 } | 4923 } |
| 4924 visitBinary(receiver, node.assignmentOperator, rhs, | 4924 visitBinarySend(receiver, node.assignmentOperator, rhs, |
| 4925 elements.getOperatorSelectorInComplexSendSet(node), node); | 4925 elements.getOperatorSelectorInComplexSendSet(node), node); |
| 4926 } | 4926 } |
| 4927 | 4927 |
| 4928 visitSendSet(ast.SendSet node) { | 4928 visitSendSet(ast.SendSet node) { |
| 4929 generateIsDeferredLoadedCheckIfNeeded(node); | 4929 generateIsDeferredLoadedCheckIfNeeded(node); |
| 4930 Element element = elements[node]; | 4930 Element element = elements[node]; |
| 4931 if (!Elements.isUnresolved(element) && element.impliesType) { | 4931 if (!Elements.isUnresolved(element) && element.impliesType) { |
| 4932 ast.Identifier selector = node.selector; | 4932 ast.Identifier selector = node.selector; |
| 4933 generateThrowNoSuchMethod(node, selector.source, | 4933 generateThrowNoSuchMethod(node, selector.source, |
| 4934 argumentNodes: node.arguments); | 4934 argumentNodes: node.arguments); |
| 4935 return; | 4935 return; |
| (...skipping 2008 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6944 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 6944 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 6945 unaliased.accept(this, builder); | 6945 unaliased.accept(this, builder); |
| 6946 } | 6946 } |
| 6947 | 6947 |
| 6948 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 6948 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 6949 JavaScriptBackend backend = builder.compiler.backend; | 6949 JavaScriptBackend backend = builder.compiler.backend; |
| 6950 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 6950 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 6951 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 6951 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 6952 } | 6952 } |
| 6953 } | 6953 } |
| OLD | NEW |