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 |