| 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 SsaCodeGeneratorTask extends CompilerTask { | 7 class SsaCodeGeneratorTask extends CompilerTask { |
| 8 | 8 |
| 9 final JavaScriptBackend backend; | 9 final JavaScriptBackend backend; |
| 10 | 10 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 sourceFile, expression.getEndToken()); | 35 sourceFile, expression.getEndToken()); |
| 36 } | 36 } |
| 37 return result; | 37 return result; |
| 38 } | 38 } |
| 39 | 39 |
| 40 CodeBuffer prettyPrint(js.Node node) { | 40 CodeBuffer prettyPrint(js.Node node) { |
| 41 var code = js.prettyPrint(node, compiler, allowVariableMinification: true); | 41 var code = js.prettyPrint(node, compiler, allowVariableMinification: true); |
| 42 return code; | 42 return code; |
| 43 } | 43 } |
| 44 | 44 |
| 45 CodeBuffer generateCode(WorkItem work, HGraph graph) { | 45 js.Expression generateCode(WorkItem work, HGraph graph) { |
| 46 if (work.element.isField()) { | 46 if (work.element.isField()) { |
| 47 return generateLazyInitializer(work, graph); | 47 return generateLazyInitializer(work, graph); |
| 48 } else { | 48 } else { |
| 49 return generateMethod(work, graph); | 49 return generateMethod(work, graph); |
| 50 } | 50 } |
| 51 } | 51 } |
| 52 | 52 |
| 53 CodeBuffer generateLazyInitializer(work, graph) { | 53 js.Expression generateLazyInitializer(work, graph) { |
| 54 return measure(() { | 54 return measure(() { |
| 55 compiler.tracer.traceGraph("codegen", graph); | 55 compiler.tracer.traceGraph("codegen", graph); |
| 56 SsaOptimizedCodeGenerator codegen = | 56 SsaOptimizedCodeGenerator codegen = |
| 57 new SsaOptimizedCodeGenerator(backend, work); | 57 new SsaOptimizedCodeGenerator(backend, work); |
| 58 codegen.visitGraph(graph); | 58 codegen.visitGraph(graph); |
| 59 js.Block body = codegen.body; | 59 return new js.Fun(codegen.parameters, codegen.body); |
| 60 js.Fun fun = new js.Fun(codegen.parameters, body); | |
| 61 return prettyPrint(fun); | |
| 62 }); | 60 }); |
| 63 } | 61 } |
| 64 | 62 |
| 65 CodeBuffer generateMethod(WorkItem work, HGraph graph) { | 63 js.Expression generateMethod(WorkItem work, HGraph graph) { |
| 66 return measure(() { | 64 return measure(() { |
| 67 compiler.tracer.traceGraph("codegen", graph); | 65 compiler.tracer.traceGraph("codegen", graph); |
| 68 SsaOptimizedCodeGenerator codegen = | 66 SsaOptimizedCodeGenerator codegen = |
| 69 new SsaOptimizedCodeGenerator(backend, work); | 67 new SsaOptimizedCodeGenerator(backend, work); |
| 70 codegen.visitGraph(graph); | 68 codegen.visitGraph(graph); |
| 71 | 69 |
| 72 FunctionElement element = work.element; | 70 FunctionElement element = work.element; |
| 73 js.Block body; | 71 js.Block body; |
| 74 ClassElement enclosingClass = element.getEnclosingClass(); | 72 ClassElement enclosingClass = element.getEnclosingClass(); |
| 75 | 73 |
| 76 if (element.isInstanceMember() | 74 if (element.isInstanceMember() |
| 77 && enclosingClass.isNative() | 75 && enclosingClass.isNative() |
| 78 && native.isOverriddenMethod( | 76 && native.isOverriddenMethod( |
| 79 element, enclosingClass, nativeEmitter)) { | 77 element, enclosingClass, nativeEmitter)) { |
| 80 // Record that this method is overridden. In case of optional | 78 // Record that this method is overridden. In case of optional |
| 81 // arguments, the emitter will generate stubs to handle them, | 79 // arguments, the emitter will generate stubs to handle them, |
| 82 // and needs to know if the method is overridden. | 80 // and needs to know if the method is overridden. |
| 83 nativeEmitter.overriddenMethods.add(element); | 81 nativeEmitter.overriddenMethods.add(element); |
| 84 StringBuffer buffer = new StringBuffer(); | 82 StringBuffer buffer = new StringBuffer(); |
| 85 body = | 83 body = |
| 86 nativeEmitter.generateMethodBodyWithPrototypeCheckForElement( | 84 nativeEmitter.generateMethodBodyWithPrototypeCheckForElement( |
| 87 element, codegen.body, codegen.parameters); | 85 element, codegen.body, codegen.parameters); |
| 88 } else { | 86 } else { |
| 89 body = codegen.body; | 87 body = codegen.body; |
| 90 } | 88 } |
| 91 | 89 |
| 92 js.Fun fun = buildJavaScriptFunction(element, codegen.parameters, body); | 90 return buildJavaScriptFunction(element, codegen.parameters, body); |
| 93 return prettyPrint(fun); | |
| 94 }); | 91 }); |
| 95 } | 92 } |
| 96 | 93 |
| 97 CodeBuffer generateBailoutMethod(WorkItem work, HGraph graph) { | 94 js.Expression generateBailoutMethod(WorkItem work, HGraph graph) { |
| 98 return measure(() { | 95 return measure(() { |
| 99 compiler.tracer.traceGraph("codegen-bailout", graph); | 96 compiler.tracer.traceGraph("codegen-bailout", graph); |
| 100 | 97 |
| 101 SsaUnoptimizedCodeGenerator codegen = | 98 SsaUnoptimizedCodeGenerator codegen = |
| 102 new SsaUnoptimizedCodeGenerator(backend, work); | 99 new SsaUnoptimizedCodeGenerator(backend, work); |
| 103 codegen.visitGraph(graph); | 100 codegen.visitGraph(graph); |
| 104 | 101 |
| 105 js.Block body = new js.Block(<js.Statement>[]); | 102 js.Block body = new js.Block(<js.Statement>[]); |
| 106 if (codegen.setup != null) body.statements.add(codegen.setup); | 103 if (codegen.setup != null) body.statements.add(codegen.setup); |
| 107 body.statements.add(codegen.body); | 104 body.statements.add(codegen.body); |
| 108 js.Fun fun = | 105 js.Fun fun = |
| 109 buildJavaScriptFunction(work.element, codegen.newParameters, body); | 106 buildJavaScriptFunction(work.element, codegen.newParameters, body); |
| 110 return prettyPrint(fun); | 107 return fun; |
| 111 }); | 108 }); |
| 112 } | 109 } |
| 113 } | 110 } |
| 114 | 111 |
| 115 // Stop-gap until the core classes have such a class. | 112 // Stop-gap until the core classes have such a class. |
| 116 class OrderedSet<T> { | 113 class OrderedSet<T> { |
| 117 final LinkedHashMap<T, bool> map = new LinkedHashMap<T, bool>(); | 114 final LinkedHashMap<T, bool> map = new LinkedHashMap<T, bool>(); |
| 118 | 115 |
| 119 void add(T x) { | 116 void add(T x) { |
| 120 if (!map.containsKey(x)) { | 117 if (!map.containsKey(x)) { |
| (...skipping 2065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2186 use(input); | 2183 use(input); |
| 2187 js.Expression right = pop(); | 2184 js.Expression right = pop(); |
| 2188 // TODO(4984): Deal with infinity and -0.0. | 2185 // TODO(4984): Deal with infinity and -0.0. |
| 2189 push(new js.LiteralExpression.withData('Math.floor(#) === #', | 2186 push(new js.LiteralExpression.withData('Math.floor(#) === #', |
| 2190 <js.Expression>[left, right])); | 2187 <js.Expression>[left, right])); |
| 2191 } | 2188 } |
| 2192 | 2189 |
| 2193 void checkTypeOf(HInstruction input, String cmp, String typeName) { | 2190 void checkTypeOf(HInstruction input, String cmp, String typeName) { |
| 2194 use(input); | 2191 use(input); |
| 2195 js.Expression typeOf = new js.Prefix("typeof", pop()); | 2192 js.Expression typeOf = new js.Prefix("typeof", pop()); |
| 2196 push(new js.Binary(cmp, typeOf, new js.LiteralString("'$typeName'"))); | 2193 push(new js.Binary(cmp, typeOf, js.string(typeName))); |
| 2197 } | 2194 } |
| 2198 | 2195 |
| 2199 void checkNum(HInstruction input, String cmp) | 2196 void checkNum(HInstruction input, String cmp) |
| 2200 => checkTypeOf(input, cmp, 'number'); | 2197 => checkTypeOf(input, cmp, 'number'); |
| 2201 | 2198 |
| 2202 void checkDouble(HInstruction input, String cmp) => checkNum(input, cmp); | 2199 void checkDouble(HInstruction input, String cmp) => checkNum(input, cmp); |
| 2203 | 2200 |
| 2204 void checkString(HInstruction input, String cmp) | 2201 void checkString(HInstruction input, String cmp) |
| 2205 => checkTypeOf(input, cmp, 'string'); | 2202 => checkTypeOf(input, cmp, 'string'); |
| 2206 | 2203 |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2494 List<js.Expression> arguments = <js.Expression>[]; | 2491 List<js.Expression> arguments = <js.Expression>[]; |
| 2495 use(node.checkedInput); | 2492 use(node.checkedInput); |
| 2496 arguments.add(pop()); | 2493 arguments.add(pop()); |
| 2497 int parameterCount = | 2494 int parameterCount = |
| 2498 helperElement.computeSignature(compiler).parameterCount; | 2495 helperElement.computeSignature(compiler).parameterCount; |
| 2499 if (parameterCount == 2) { | 2496 if (parameterCount == 2) { |
| 2500 // 2 arguments implies that the method is either [propertyTypeCheck] | 2497 // 2 arguments implies that the method is either [propertyTypeCheck] |
| 2501 // or [propertyTypeCast]. | 2498 // or [propertyTypeCast]. |
| 2502 assert(!type.isMalformed); | 2499 assert(!type.isMalformed); |
| 2503 String additionalArgument = backend.namer.operatorIs(element); | 2500 String additionalArgument = backend.namer.operatorIs(element); |
| 2504 arguments.add(new js.LiteralString("'$additionalArgument'")); | 2501 arguments.add(js.string(additionalArgument)); |
| 2505 } else if (parameterCount == 3) { | 2502 } else if (parameterCount == 3) { |
| 2506 // 3 arguments implies that the method is [malformedTypeCheck]. | 2503 // 3 arguments implies that the method is [malformedTypeCheck]. |
| 2507 assert(type.isMalformed); | 2504 assert(type.isMalformed); |
| 2508 String reasons = fetchReasonsFromMalformedType(type); | 2505 String reasons = fetchReasonsFromMalformedType(type); |
| 2509 arguments.add(new js.LiteralString("'$type'")); | 2506 arguments.add(js.string('$type')); |
| 2510 // TODO(johnniwinther): Handle escaping correctly. | 2507 // TODO(johnniwinther): Handle escaping correctly. |
| 2511 arguments.add(new js.LiteralString("'$reasons'")); | 2508 arguments.add(js.string(reasons)); |
| 2512 } else { | 2509 } else { |
| 2513 assert(!type.isMalformed); | 2510 assert(!type.isMalformed); |
| 2514 } | 2511 } |
| 2515 String helperName = backend.namer.isolateAccess(helperElement); | 2512 String helperName = backend.namer.isolateAccess(helperElement); |
| 2516 push(new js.Call(new js.VariableUse(helperName), arguments)); | 2513 push(new js.Call(new js.VariableUse(helperName), arguments)); |
| 2517 } else { | 2514 } else { |
| 2518 use(node.checkedInput); | 2515 use(node.checkedInput); |
| 2519 } | 2516 } |
| 2520 } | 2517 } |
| 2521 } | 2518 } |
| (...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3043 if (leftType.canBeNull() && rightType.canBeNull()) { | 3040 if (leftType.canBeNull() && rightType.canBeNull()) { |
| 3044 if (left.isConstantNull() || right.isConstantNull() || | 3041 if (left.isConstantNull() || right.isConstantNull() || |
| 3045 (leftType.isPrimitive() && leftType == rightType)) { | 3042 (leftType.isPrimitive() && leftType == rightType)) { |
| 3046 return '=='; | 3043 return '=='; |
| 3047 } | 3044 } |
| 3048 return null; | 3045 return null; |
| 3049 } else { | 3046 } else { |
| 3050 return '==='; | 3047 return '==='; |
| 3051 } | 3048 } |
| 3052 } | 3049 } |
| OLD | NEW |