| 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 class SsaCodeGeneratorTask extends CompilerTask { | 5 class SsaCodeGeneratorTask extends CompilerTask { |
| 6 final JavaScriptBackend backend; | 6 final JavaScriptBackend backend; |
| 7 SsaCodeGeneratorTask(JavaScriptBackend backend) | 7 SsaCodeGeneratorTask(JavaScriptBackend backend) |
| 8 : this.backend = backend, | 8 : this.backend = backend, |
| 9 super(backend.compiler); | 9 super(backend.compiler); |
| 10 String get name() => 'SSA code generator'; | 10 String get name() => 'SSA code generator'; |
| 11 NativeEmitter get nativeEmitter() => backend.emitter.nativeEmitter; | 11 NativeEmitter get nativeEmitter() => backend.emitter.nativeEmitter; |
| 12 | 12 |
| 13 | 13 |
| 14 CodeBuffer buildJavaScriptFunction(FunctionElement element, | 14 CodeBuffer buildJavaScriptFunction(FunctionElement element, |
| 15 String parameters, | 15 String parameters, |
| 16 String body) { | 16 CodeBuffer body) { |
| 17 String extraSpace = ""; | 17 String extraSpace = ""; |
| 18 // Members are emitted inside a JavaScript object literal. To line up the | 18 // Members are emitted inside a JavaScript object literal. To line up the |
| 19 // indentation we want the closing curly brace to be indented by one space. | 19 // indentation we want the closing curly brace to be indented by one space. |
| 20 // Example: | 20 // Example: |
| 21 // defineClass("A", "B", ... , { | 21 // defineClass("A", "B", ... , { |
| 22 // foo$1: function(..) { | 22 // foo$1: function(..) { |
| 23 // }, /* <========== indent by 1. */ | 23 // }, /* <========== indent by 1. */ |
| 24 // bar$2: function(..) { | 24 // bar$2: function(..) { |
| 25 // }, /* <========== indent by 1. */ | 25 // }, /* <========== indent by 1. */ |
| 26 // | 26 // |
| (...skipping 23 matching lines...) Expand all Loading... |
| 50 Map<Element, String> parameterNames = getParameterNames(work); | 50 Map<Element, String> parameterNames = getParameterNames(work); |
| 51 parameterNames.forEach((element, name) { | 51 parameterNames.forEach((element, name) { |
| 52 compiler.enqueuer.codegen.addToWorkList(element); | 52 compiler.enqueuer.codegen.addToWorkList(element); |
| 53 }); | 53 }); |
| 54 String parameters = Strings.join(parameterNames.getValues(), ', '); | 54 String parameters = Strings.join(parameterNames.getValues(), ', '); |
| 55 SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator( | 55 SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator( |
| 56 backend, work, parameters, parameterNames); | 56 backend, work, parameters, parameterNames); |
| 57 codegen.visitGraph(graph); | 57 codegen.visitGraph(graph); |
| 58 | 58 |
| 59 FunctionElement element = work.element; | 59 FunctionElement element = work.element; |
| 60 String code; | 60 CodeBuffer code; |
| 61 if (element.isInstanceMember() | 61 if (element.isInstanceMember() |
| 62 && element.enclosingElement.isClass() | 62 && element.enclosingElement.isClass() |
| 63 && element.enclosingElement.isNative() | 63 && element.enclosingElement.isNative() |
| 64 && native.isOverriddenMethod( | 64 && native.isOverriddenMethod( |
| 65 element, element.enclosingElement, nativeEmitter)) { | 65 element, element.enclosingElement, nativeEmitter)) { |
| 66 // Record that this method is overridden. In case of optional | 66 // Record that this method is overridden. In case of optional |
| 67 // arguments, the emitter will generate stubs to handle them, | 67 // arguments, the emitter will generate stubs to handle them, |
| 68 // and needs to know if the method is overridden. | 68 // and needs to know if the method is overridden. |
| 69 nativeEmitter.overriddenMethods.add(element); | 69 nativeEmitter.overriddenMethods.add(element); |
| 70 StringBuffer buffer = new StringBuffer(); | 70 StringBuffer buffer = new StringBuffer(); |
| 71 native.generateMethodWithPrototypeCheckForElement( | 71 native.generateMethodWithPrototypeCheckForElement( |
| 72 compiler, buffer, element, '${codegen.buffer}', parameters); | 72 compiler, buffer, element, '${codegen.buffer}', parameters); |
| 73 code = buffer.toString(); | 73 code = new CodeBuffer(); |
| 74 code.add(buffer); |
| 74 } else { | 75 } else { |
| 75 code = codegen.buffer.toString(); | 76 code = codegen.buffer; |
| 76 } | 77 } |
| 77 return buildJavaScriptFunction(element, parameters, code); | 78 return buildJavaScriptFunction(element, parameters, code); |
| 78 }); | 79 }); |
| 79 } | 80 } |
| 80 | 81 |
| 81 CodeBuffer generateBailoutMethod(WorkItem work, HGraph graph) { | 82 CodeBuffer generateBailoutMethod(WorkItem work, HGraph graph) { |
| 82 return measure(() { | 83 return measure(() { |
| 83 compiler.tracer.traceGraph("codegen-bailout", graph); | 84 compiler.tracer.traceGraph("codegen-bailout", graph); |
| 84 | 85 |
| 85 Map<Element, String> parameterNames = getParameterNames(work); | 86 Map<Element, String> parameterNames = getParameterNames(work); |
| 86 String parameters = Strings.join(parameterNames.getValues(), ', '); | 87 String parameters = Strings.join(parameterNames.getValues(), ', '); |
| 87 SsaUnoptimizedCodeGenerator codegen = new SsaUnoptimizedCodeGenerator( | 88 SsaUnoptimizedCodeGenerator codegen = new SsaUnoptimizedCodeGenerator( |
| 88 backend, work, parameters, parameterNames); | 89 backend, work, parameters, parameterNames); |
| 89 codegen.visitGraph(graph); | 90 codegen.visitGraph(graph); |
| 90 | 91 |
| 91 String body = '${codegen.setup}${codegen.buffer}'; | 92 CodeBuffer code = new CodeBuffer(); |
| 93 code.add(codegen.setup); |
| 94 code.add(codegen.buffer); |
| 92 return buildJavaScriptFunction( | 95 return buildJavaScriptFunction( |
| 93 work.element, codegen.newParameters.toString(), body); | 96 work.element, codegen.newParameters.toString(), code); |
| 94 }); | 97 }); |
| 95 } | 98 } |
| 96 | 99 |
| 97 Map<Element, String> getParameterNames(WorkItem work) { | 100 Map<Element, String> getParameterNames(WorkItem work) { |
| 98 Map<Element, String> parameterNames = new LinkedHashMap<Element, String>(); | 101 Map<Element, String> parameterNames = new LinkedHashMap<Element, String>(); |
| 99 FunctionElement function = work.element; | 102 FunctionElement function = work.element; |
| 100 | 103 |
| 101 // The dom/html libraries have inline JS code that reference | 104 // The dom/html libraries have inline JS code that reference |
| 102 // parameter names directly. Long-term such code will be rejected. | 105 // parameter names directly. Long-term such code will be rejected. |
| 103 // Now, just don't mangle the parameter name. | 106 // Now, just don't mangle the parameter name. |
| (...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 HCheck check = argument; | 651 HCheck check = argument; |
| 649 use(check.checkedInput, expectedPrecedenceForArgument); | 652 use(check.checkedInput, expectedPrecedenceForArgument); |
| 650 } else { | 653 } else { |
| 651 buffer.add(variableNames.getName(argument)); | 654 buffer.add(variableNames.getName(argument)); |
| 652 } | 655 } |
| 653 } | 656 } |
| 654 | 657 |
| 655 visit(HInstruction node, int expectedPrecedenceForNode) { | 658 visit(HInstruction node, int expectedPrecedenceForNode) { |
| 656 int oldPrecedence = this.expectedPrecedence; | 659 int oldPrecedence = this.expectedPrecedence; |
| 657 this.expectedPrecedence = expectedPrecedenceForNode; | 660 this.expectedPrecedence = expectedPrecedenceForNode; |
| 661 if (node.sourcePosition !== null) { |
| 662 buffer.setSourceLocation(work.element, node.sourcePosition); |
| 663 } |
| 658 node.accept(this); | 664 node.accept(this); |
| 659 this.expectedPrecedence = oldPrecedence; | 665 this.expectedPrecedence = oldPrecedence; |
| 660 } | 666 } |
| 661 | 667 |
| 662 void continueAsBreak(LabelElement target) { | 668 void continueAsBreak(LabelElement target) { |
| 663 addIndented("break "); | 669 addIndented("break "); |
| 664 writeContinueLabel(target); | 670 writeContinueLabel(target); |
| 665 buffer.add(";\n"); | 671 buffer.add(";\n"); |
| 666 } | 672 } |
| 667 | 673 |
| (...skipping 2468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3136 if (leftType.canBeNull() && rightType.canBeNull()) { | 3142 if (leftType.canBeNull() && rightType.canBeNull()) { |
| 3137 if (left.isConstantNull() || right.isConstantNull() || | 3143 if (left.isConstantNull() || right.isConstantNull() || |
| 3138 (leftType.isPrimitive() && leftType == rightType)) { | 3144 (leftType.isPrimitive() && leftType == rightType)) { |
| 3139 return '=='; | 3145 return '=='; |
| 3140 } | 3146 } |
| 3141 return null; | 3147 return null; |
| 3142 } else { | 3148 } else { |
| 3143 return '==='; | 3149 return '==='; |
| 3144 } | 3150 } |
| 3145 } | 3151 } |
| OLD | NEW |