| 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 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); | 6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); |
| 7 String get name() => 'SSA code generator'; | 7 String get name() => 'SSA code generator'; |
| 8 | 8 |
| 9 | 9 |
| 10 String buildJavaScriptFunction(FunctionElement element, | 10 String buildJavaScriptFunction(FunctionElement element, |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 final Set<HInstruction> generateAtUseSite; | 149 final Set<HInstruction> generateAtUseSite; |
| 150 final Map<HPhi, String> logicalOperations; | 150 final Map<HPhi, String> logicalOperations; |
| 151 final Map<Element, ElementAction> breakAction; | 151 final Map<Element, ElementAction> breakAction; |
| 152 final Map<Element, ElementAction> continueAction; | 152 final Map<Element, ElementAction> continueAction; |
| 153 final Equivalence<HPhi> phiEquivalence; | 153 final Equivalence<HPhi> phiEquivalence; |
| 154 | 154 |
| 155 Element equalsNullElement; | 155 Element equalsNullElement; |
| 156 Element boolifiedEqualsNullElement; | 156 Element boolifiedEqualsNullElement; |
| 157 int indent = 0; | 157 int indent = 0; |
| 158 int expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE; | 158 int expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE; |
| 159 JSBinaryOperatorPrecedence unsignedShiftPrecedences; |
| 159 HGraph currentGraph; | 160 HGraph currentGraph; |
| 160 /** | 161 /** |
| 161 * Whether the code-generation should try to generate an expression | 162 * Whether the code-generation should try to generate an expression |
| 162 * instead of a sequence of statements. | 163 * instead of a sequence of statements. |
| 163 */ | 164 */ |
| 164 int generationState = STATE_STATEMENT; | 165 int generationState = STATE_STATEMENT; |
| 165 /** | 166 /** |
| 166 * While generating expressions, we can't insert variable declarations. | 167 * While generating expressions, we can't insert variable declarations. |
| 167 * Instead we declare them at the end of the function | 168 * Instead we declare them at the end of the function |
| 168 */ | 169 */ |
| (...skipping 18 matching lines...) Expand all Loading... |
| 187 this.parameters, | 188 this.parameters, |
| 188 this.parameterNames) | 189 this.parameterNames) |
| 189 : names = new Map<int, String>(), | 190 : names = new Map<int, String>(), |
| 190 prefixes = new Map<String, int>(), | 191 prefixes = new Map<String, int>(), |
| 191 usedNames = new Set<String>(), | 192 usedNames = new Set<String>(), |
| 192 buffer = new StringBuffer(), | 193 buffer = new StringBuffer(), |
| 193 generateAtUseSite = new Set<HInstruction>(), | 194 generateAtUseSite = new Set<HInstruction>(), |
| 194 logicalOperations = new Map<HPhi, String>(), | 195 logicalOperations = new Map<HPhi, String>(), |
| 195 breakAction = new Map<Element, ElementAction>(), | 196 breakAction = new Map<Element, ElementAction>(), |
| 196 continueAction = new Map<Element, ElementAction>(), | 197 continueAction = new Map<Element, ElementAction>(), |
| 197 phiEquivalence = new Equivalence<HPhi>() { | 198 phiEquivalence = new Equivalence<HPhi>(), |
| 199 unsignedShiftPrecedences = JSPrecedence.binary['>>>'] { |
| 198 | 200 |
| 199 for (final name in parameterNames.getValues()) { | 201 for (final name in parameterNames.getValues()) { |
| 200 prefixes[name] = 0; | 202 prefixes[name] = 0; |
| 201 } | 203 } |
| 202 | 204 |
| 203 // Create a namespace for temporaries. | 205 // Create a namespace for temporaries. |
| 204 prefixes[TEMPORARY_PREFIX] = 0; | 206 prefixes[TEMPORARY_PREFIX] = 0; |
| 205 | 207 |
| 206 Interceptors interceptors = compiler.builder.interceptors; | 208 Interceptors interceptors = compiler.builder.interceptors; |
| 207 equalsNullElement = interceptors.getEqualsNullInterceptor(); | 209 equalsNullElement = interceptors.getEqualsNullInterceptor(); |
| (...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1104 beginExpression(operatorPrecedences.precedence); | 1106 beginExpression(operatorPrecedences.precedence); |
| 1105 use(node.left, operatorPrecedences.left); | 1107 use(node.left, operatorPrecedences.left); |
| 1106 buffer.add(' $op '); | 1108 buffer.add(' $op '); |
| 1107 use(node.right, operatorPrecedences.right); | 1109 use(node.right, operatorPrecedences.right); |
| 1108 endExpression(operatorPrecedences.precedence); | 1110 endExpression(operatorPrecedences.precedence); |
| 1109 } else { | 1111 } else { |
| 1110 visitInvokeStatic(node); | 1112 visitInvokeStatic(node); |
| 1111 } | 1113 } |
| 1112 } | 1114 } |
| 1113 | 1115 |
| 1116 // We want the outcome of bit-operations to be positive. We use the unsigned |
| 1117 // shift operator to achieve this. |
| 1118 visitBitInvokeBinary(HBinaryBitOp node, String op) { |
| 1119 if (node.builtin){ |
| 1120 beginExpression(unsignedShiftPrecedences.precedence); |
| 1121 visitInvokeBinary(node, op); |
| 1122 buffer.add(' >>> 0'); |
| 1123 endExpression(unsignedShiftPrecedences.precedence); |
| 1124 } else { |
| 1125 visitInvokeBinary(node, op); |
| 1126 } |
| 1127 } |
| 1128 |
| 1114 visitInvokeUnary(HInvokeUnary node, String op) { | 1129 visitInvokeUnary(HInvokeUnary node, String op) { |
| 1115 if (node.builtin) { | 1130 if (node.builtin) { |
| 1116 beginExpression(JSPrecedence.PREFIX_PRECEDENCE); | 1131 beginExpression(JSPrecedence.PREFIX_PRECEDENCE); |
| 1117 buffer.add('$op'); | 1132 buffer.add('$op'); |
| 1118 use(node.operand, JSPrecedence.PREFIX_PRECEDENCE); | 1133 use(node.operand, JSPrecedence.PREFIX_PRECEDENCE); |
| 1119 endExpression(JSPrecedence.PREFIX_PRECEDENCE); | 1134 endExpression(JSPrecedence.PREFIX_PRECEDENCE); |
| 1120 } else { | 1135 } else { |
| 1121 visitInvokeStatic(node); | 1136 visitInvokeStatic(node); |
| 1122 } | 1137 } |
| 1123 } | 1138 } |
| 1124 | 1139 |
| 1140 // We want the outcome of bit-operations to be positive. We use the unsigned |
| 1141 // shift operator to achieve this. |
| 1142 visitBitInvokeUnary(HInvokeUnary node, String op) { |
| 1143 if (node.builtin){ |
| 1144 beginExpression(unsignedShiftPrecedences.precedence); |
| 1145 visitInvokeUnary(node, op); |
| 1146 buffer.add(' >>> 0'); |
| 1147 endExpression(unsignedShiftPrecedences.precedence); |
| 1148 } else { |
| 1149 visitInvokeUnary(node, op); |
| 1150 } |
| 1151 } |
| 1152 |
| 1125 visitEquals(HEquals node) { | 1153 visitEquals(HEquals node) { |
| 1126 if (node.builtin) { | 1154 if (node.builtin) { |
| 1127 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 1155 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1128 use(node.left, JSPrecedence.EQUALITY_PRECEDENCE); | 1156 use(node.left, JSPrecedence.EQUALITY_PRECEDENCE); |
| 1129 buffer.add(' === '); | 1157 buffer.add(' === '); |
| 1130 use(node.right, JSPrecedence.RELATIONAL_PRECEDENCE); | 1158 use(node.right, JSPrecedence.RELATIONAL_PRECEDENCE); |
| 1131 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 1159 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1132 } else if (node.element === equalsNullElement || | 1160 } else if (node.element === equalsNullElement || |
| 1133 node.element === boolifiedEqualsNullElement) { | 1161 node.element === boolifiedEqualsNullElement) { |
| 1134 beginExpression(JSPrecedence.CALL_PRECEDENCE); | 1162 beginExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1135 use(node.target, JSPrecedence.CALL_PRECEDENCE); | 1163 use(node.target, JSPrecedence.CALL_PRECEDENCE); |
| 1136 buffer.add('('); | 1164 buffer.add('('); |
| 1137 use(node.left, JSPrecedence.ASSIGNMENT_PRECEDENCE); | 1165 use(node.left, JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| 1138 buffer.add(')'); | 1166 buffer.add(')'); |
| 1139 endExpression(JSPrecedence.CALL_PRECEDENCE); | 1167 endExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1140 } else { | 1168 } else { |
| 1141 visitInvokeStatic(node); | 1169 visitInvokeStatic(node); |
| 1142 } | 1170 } |
| 1143 } | 1171 } |
| 1144 | 1172 |
| 1145 visitAdd(HAdd node) => visitInvokeBinary(node, '+'); | 1173 visitAdd(HAdd node) => visitInvokeBinary(node, '+'); |
| 1146 visitDivide(HDivide node) => visitInvokeBinary(node, '/'); | 1174 visitDivide(HDivide node) => visitInvokeBinary(node, '/'); |
| 1147 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*'); | 1175 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*'); |
| 1148 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-'); | 1176 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-'); |
| 1149 // Truncating divide does not have a JS equivalent. | 1177 // Truncating divide does not have a JS equivalent. |
| 1150 visitTruncatingDivide(HTruncatingDivide node) => visitInvokeStatic(node); | 1178 visitTruncatingDivide(HTruncatingDivide node) => visitInvokeStatic(node); |
| 1151 // Modulo cannot be mapped to the native operator (different semantics). | 1179 // Modulo cannot be mapped to the native operator (different semantics). |
| 1152 visitModulo(HModulo node) => visitInvokeStatic(node); | 1180 visitModulo(HModulo node) => visitInvokeStatic(node); |
| 1153 | 1181 |
| 1154 visitBitAnd(HBitAnd node) => visitInvokeBinary(node, '&'); | 1182 visitBitAnd(HBitAnd node) => visitBitInvokeBinary(node, '&'); |
| 1155 visitBitNot(HBitNot node) => visitInvokeUnary(node, '~'); | 1183 visitBitNot(HBitNot node) => visitBitInvokeUnary(node, '~'); |
| 1156 visitBitOr(HBitOr node) => visitInvokeBinary(node, '|'); | 1184 visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|'); |
| 1157 visitBitXor(HBitXor node) => visitInvokeBinary(node, '^'); | 1185 visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^'); |
| 1158 | 1186 |
| 1159 // We need to check if the left operand is negative in order to use | 1187 // We need to check if the left operand is negative in order to use |
| 1160 // the native operator. | 1188 // the native operator. |
| 1161 visitShiftRight(HShiftRight node) => visitInvokeStatic(node); | 1189 visitShiftRight(HShiftRight node) => visitInvokeStatic(node); |
| 1162 | 1190 |
| 1163 // Shift left cannot be mapped to the native operator (different semantics). | 1191 // Shift left cannot be mapped to the native operator (different semantics). |
| 1164 visitShiftLeft(HShiftLeft node) => visitInvokeStatic(node); | 1192 visitShiftLeft(HShiftLeft node) => visitInvokeStatic(node); |
| 1165 | 1193 |
| 1166 visitNegate(HNegate node) => visitInvokeUnary(node, '-'); | 1194 visitNegate(HNegate node) => visitInvokeUnary(node, '-'); |
| 1167 | 1195 |
| (...skipping 1232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2400 startBailoutSwitch(); | 2428 startBailoutSwitch(); |
| 2401 } | 2429 } |
| 2402 } | 2430 } |
| 2403 | 2431 |
| 2404 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2432 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 2405 if (labeledBlockInfo.body.start.hasGuards()) { | 2433 if (labeledBlockInfo.body.start.hasGuards()) { |
| 2406 endBailoutSwitch(); | 2434 endBailoutSwitch(); |
| 2407 } | 2435 } |
| 2408 } | 2436 } |
| 2409 } | 2437 } |
| OLD | NEW |