Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(340)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/codegen.dart

Issue 188433002: Instruction selection before removing HTypeKnown (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 248
249 js.Node attachLocationRange(js.Node jsNode, 249 js.Node attachLocationRange(js.Node jsNode,
250 SourceFileLocation sourcePosition, 250 SourceFileLocation sourcePosition,
251 SourceFileLocation endSourcePosition) { 251 SourceFileLocation endSourcePosition) {
252 jsNode.sourcePosition = sourcePosition; 252 jsNode.sourcePosition = sourcePosition;
253 jsNode.endSourcePosition = endSourcePosition; 253 jsNode.endSourcePosition = endSourcePosition;
254 return jsNode; 254 return jsNode;
255 } 255 }
256 256
257 void preGenerateMethod(HGraph graph) { 257 void preGenerateMethod(HGraph graph) {
258 new SsaInstructionSelection(compiler).visitGraph(graph);
258 new SsaTypeKnownRemover().visitGraph(graph); 259 new SsaTypeKnownRemover().visitGraph(graph);
259 new SsaInstructionMerger(generateAtUseSite, compiler).visitGraph(graph); 260 new SsaInstructionMerger(generateAtUseSite, compiler).visitGraph(graph);
260 new SsaConditionMerger( 261 new SsaConditionMerger(
261 generateAtUseSite, controlFlowOperators).visitGraph(graph); 262 generateAtUseSite, controlFlowOperators).visitGraph(graph);
262 SsaLiveIntervalBuilder intervalBuilder = new SsaLiveIntervalBuilder( 263 SsaLiveIntervalBuilder intervalBuilder = new SsaLiveIntervalBuilder(
263 compiler, generateAtUseSite, controlFlowOperators); 264 compiler, generateAtUseSite, controlFlowOperators);
264 intervalBuilder.visitGraph(graph); 265 intervalBuilder.visitGraph(graph);
265 SsaVariableAllocator allocator = new SsaVariableAllocator( 266 SsaVariableAllocator allocator = new SsaVariableAllocator(
266 compiler, 267 compiler,
267 intervalBuilder.liveInstructions, 268 intervalBuilder.liveInstructions,
(...skipping 924 matching lines...) Expand 10 before | Expand all | Expand 10 after
1192 1193
1193 // We want the outcome of bit-operations to be positive. We use the unsigned 1194 // We want the outcome of bit-operations to be positive. We use the unsigned
1194 // shift operator to achieve this. 1195 // shift operator to achieve this.
1195 visitBitInvokeUnary(HInvokeUnary node, String op) { 1196 visitBitInvokeUnary(HInvokeUnary node, String op) {
1196 visitInvokeUnary(node, op); 1197 visitInvokeUnary(node, op);
1197 if (requiresUintConversion(node)) { 1198 if (requiresUintConversion(node)) {
1198 push(new js.Binary(">>>", pop(), new js.LiteralNumber("0")), node); 1199 push(new js.Binary(">>>", pop(), new js.LiteralNumber("0")), node);
1199 } 1200 }
1200 } 1201 }
1201 1202
1202 void emitIdentityComparison(HInstruction left, 1203 void emitIdentityComparison(HIdentity instruction, bool inverse) {
1203 HInstruction right, 1204 String op = instruction.singleComparisonOp;
1204 bool inverse) { 1205 HInstruction left = instruction.left;
1205 String op = singleIdentityComparison(left, right, compiler); 1206 HInstruction right = instruction.right;
1206 if (op != null) { 1207 if (op != null) {
1207 use(left); 1208 use(left);
1208 js.Expression jsLeft = pop(); 1209 js.Expression jsLeft = pop();
1209 use(right); 1210 use(right);
1210 push(new js.Binary(mapRelationalOperator(op, inverse), jsLeft, pop())); 1211 push(new js.Binary(mapRelationalOperator(op, inverse), jsLeft, pop()));
1211 } else { 1212 } else {
1212 assert(NullConstant.JsNull == 'null'); 1213 assert(NullConstant.JsNull == 'null');
1213 use(left); 1214 use(left);
1214 js.Binary leftEqualsNull = 1215 js.Binary leftEqualsNull =
1215 new js.Binary("==", pop(), new js.LiteralNull()); 1216 new js.Binary("==", pop(), new js.LiteralNull());
1216 use(right); 1217 use(right);
1217 js.Binary rightEqualsNull = 1218 js.Binary rightEqualsNull =
1218 new js.Binary(mapRelationalOperator("==", inverse), 1219 new js.Binary(mapRelationalOperator("==", inverse),
1219 pop(), new js.LiteralNull()); 1220 pop(), new js.LiteralNull());
1220 use(right); 1221 use(right);
1221 use(left); 1222 use(left);
1222 js.Binary tripleEq = new js.Binary(mapRelationalOperator("===", inverse), 1223 js.Binary tripleEq = new js.Binary(mapRelationalOperator("===", inverse),
1223 pop(), pop()); 1224 pop(), pop());
1224 1225
1225 push(new js.Conditional(leftEqualsNull, rightEqualsNull, tripleEq)); 1226 push(new js.Conditional(leftEqualsNull, rightEqualsNull, tripleEq));
1226 } 1227 }
1227 } 1228 }
1228 1229
1229 visitIdentity(HIdentity node) { 1230 visitIdentity(HIdentity node) {
1230 emitIdentityComparison(node.left, node.right, false); 1231 emitIdentityComparison(node, false);
1231 } 1232 }
1232 1233
1233 visitAdd(HAdd node) => visitInvokeBinary(node, '+'); 1234 visitAdd(HAdd node) => visitInvokeBinary(node, '+');
1234 visitDivide(HDivide node) => visitInvokeBinary(node, '/'); 1235 visitDivide(HDivide node) => visitInvokeBinary(node, '/');
1235 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*'); 1236 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*');
1236 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-'); 1237 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-');
1237 visitBitAnd(HBitAnd node) => visitBitInvokeBinary(node, '&'); 1238 visitBitAnd(HBitAnd node) => visitBitInvokeBinary(node, '&');
1238 visitBitNot(HBitNot node) => visitBitInvokeUnary(node, '~'); 1239 visitBitNot(HBitNot node) => visitBitInvokeUnary(node, '~');
1239 visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|'); 1240 visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|');
1240 visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^'); 1241 visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^');
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after
1805 // This optimization doesn't work for NaN, so we only do it if the 1806 // This optimization doesn't work for NaN, so we only do it if the
1806 // type is known to be an integer. 1807 // type is known to be an integer.
1807 return left.isInteger(compiler) && right.isInteger(compiler); 1808 return left.isInteger(compiler) && right.isInteger(compiler);
1808 } 1809 }
1809 1810
1810 bool handledBySpecialCase = false; 1811 bool handledBySpecialCase = false;
1811 if (isGenerateAtUseSite(input)) { 1812 if (isGenerateAtUseSite(input)) {
1812 handledBySpecialCase = true; 1813 handledBySpecialCase = true;
1813 if (input is HIs) { 1814 if (input is HIs) {
1814 emitIs(input, '!=='); 1815 emitIs(input, '!==');
1816 } else if (input is HIsViaInterceptor) {
1817 emitIsViaInterceptor(input, true);
1815 } else if (input is HNot) { 1818 } else if (input is HNot) {
1816 use(input.inputs[0]); 1819 use(input.inputs[0]);
1817 } else if (input is HIdentity) { 1820 } else if (input is HIdentity) {
1818 HIdentity identity = input; 1821 emitIdentityComparison(input, true);
1819 emitIdentityComparison(identity.left, identity.right, true);
1820 } else if (input is HBoolify) { 1822 } else if (input is HBoolify) {
1821 use(input.inputs[0]); 1823 use(input.inputs[0]);
1822 push(new js.Binary("!==", pop(), newLiteralBool(true)), input); 1824 push(new js.Binary("!==", pop(), newLiteralBool(true)), input);
1823 } else if (canGenerateOptimizedComparison(input)) { 1825 } else if (canGenerateOptimizedComparison(input)) {
1824 HRelational relational = input; 1826 HRelational relational = input;
1825 BinaryOperation operation = 1827 BinaryOperation operation =
1826 relational.operation(backend.constantSystem); 1828 relational.operation(backend.constantSystem);
1827 String op = mapRelationalOperator(operation.name, true); 1829 String op = mapRelationalOperator(operation.name, true);
1828 visitRelational(input, op); 1830 visitRelational(input, op);
1829 } else { 1831 } else {
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
2233 return; 2235 return;
2234 } else if (element == backend.jsFixedArrayClass) { 2236 } else if (element == backend.jsFixedArrayClass) {
2235 if (negative) { 2237 if (negative) {
2236 checkExtendableArray(input); 2238 checkExtendableArray(input);
2237 } else { 2239 } else {
2238 checkFixedArray(input); 2240 checkFixedArray(input);
2239 } 2241 }
2240 return; 2242 return;
2241 } 2243 }
2242 if (interceptor != null) { 2244 if (interceptor != null) {
2243 use(interceptor); 2245 checkTypeViaProperty(interceptor, type, negative);
2244 } else { 2246 } else {
2245 use(input); 2247 checkTypeViaProperty(input, type, negative);
2246 } 2248 }
2249 }
2247 2250
2251 void checkTypeViaProperty(HInstruction input, DartType type, bool negative) {
2248 world.registerIsCheck(type, work.resolutionTree); 2252 world.registerIsCheck(type, work.resolutionTree);
2249 2253
2254 use(input);
2255
2250 js.PropertyAccess field = 2256 js.PropertyAccess field =
2251 new js.PropertyAccess.field(pop(), backend.namer.operatorIsType(type)); 2257 new js.PropertyAccess.field(pop(), backend.namer.operatorIsType(type));
2252 // We always negate at least once so that the result is boolified. 2258 // We always negate at least once so that the result is boolified.
2253 push(new js.Prefix('!', field)); 2259 push(new js.Prefix('!', field));
2254 // If the result is not negated, put another '!' in front. 2260 // If the result is not negated, put another '!' in front.
2255 if (!negative) push(new js.Prefix('!', pop())); 2261 if (!negative) push(new js.Prefix('!', pop()));
2256 } 2262 }
2257 2263
2258 void handleNumberOrStringSupertypeCheck(HInstruction input, 2264 void handleNumberOrStringSupertypeCheck(HInstruction input,
2259 HInstruction interceptor, 2265 HInstruction interceptor,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2312 String combiner = negative ? '&&' : '||'; 2318 String combiner = negative ? '&&' : '||';
2313 push(new js.Binary(negative ? '||' : '&&', 2319 push(new js.Binary(negative ? '||' : '&&',
2314 objectTest, 2320 objectTest,
2315 new js.Binary(combiner, arrayTest, pop()))); 2321 new js.Binary(combiner, arrayTest, pop())));
2316 } 2322 }
2317 2323
2318 void visitIs(HIs node) { 2324 void visitIs(HIs node) {
2319 emitIs(node, "==="); 2325 emitIs(node, "===");
2320 } 2326 }
2321 2327
2328 void visitIsViaInterceptor(HIsViaInterceptor node) {
2329 emitIsViaInterceptor(node, false);
2330 }
2331
2322 void emitIs(HIs node, String relation) { 2332 void emitIs(HIs node, String relation) {
2323 DartType type = node.typeExpression; 2333 DartType type = node.typeExpression;
2324 world.registerIsCheck(type, work.resolutionTree); 2334 world.registerIsCheck(type, work.resolutionTree);
2325 HInstruction input = node.expression; 2335 HInstruction input = node.expression;
2326 2336
2327 // If this is changed to single == there are several places below that must 2337 // If this is changed to single == there are several places below that must
2328 // be changed to match. 2338 // be changed to match.
2329 assert(relation == '===' || relation == '!=='); 2339 assert(relation == '===' || relation == '!==');
2330 bool negative = relation == '!=='; 2340 bool negative = relation == '!==';
2331 2341
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2391 js.Expression objectTest = pop(); 2401 js.Expression objectTest = pop();
2392 checkType(input, interceptor, type, negative: negative); 2402 checkType(input, interceptor, type, negative: negative);
2393 push(new js.Binary(negative ? '||' : '&&', objectTest, pop()), node); 2403 push(new js.Binary(negative ? '||' : '&&', objectTest, pop()), node);
2394 } else { 2404 } else {
2395 checkType(input, interceptor, type, negative: negative); 2405 checkType(input, interceptor, type, negative: negative);
2396 attachLocationToLast(node); 2406 attachLocationToLast(node);
2397 } 2407 }
2398 } 2408 }
2399 } 2409 }
2400 2410
2411 void emitIsViaInterceptor(HIsViaInterceptor node, bool negative) {
2412 checkTypeViaProperty(node.interceptor, node.typeExpression, negative);
2413 attachLocationToLast(node);
2414 }
2415
2401 js.Expression generateTest(HInstruction input, TypeMask checkedType) { 2416 js.Expression generateTest(HInstruction input, TypeMask checkedType) {
2402 TypeMask receiver = input.instructionType; 2417 TypeMask receiver = input.instructionType;
2403 // Figure out if it is beneficial to turn this into a null check. 2418 // Figure out if it is beneficial to turn this into a null check.
2404 // V8 generally prefers 'typeof' checks, but for integers and 2419 // V8 generally prefers 'typeof' checks, but for integers and
2405 // indexable primitives we cannot compile this test into a single 2420 // indexable primitives we cannot compile this test into a single
2406 // typeof check so the null check is cheaper. 2421 // typeof check so the null check is cheaper.
2407 bool turnIntoNumCheck = input.isIntegerOrNull(compiler) 2422 bool turnIntoNumCheck = input.isIntegerOrNull(compiler)
2408 && checkedType.containsOnlyInt(compiler); 2423 && checkedType.containsOnlyInt(compiler);
2409 bool turnIntoNullCheck = !turnIntoNumCheck 2424 bool turnIntoNullCheck = !turnIntoNumCheck
2410 && (checkedType.nullable() == receiver) 2425 && (checkedType.nullable() == receiver)
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
2644 js.PropertyAccess accessHelper(String name) { 2659 js.PropertyAccess accessHelper(String name) {
2645 Element helper = compiler.findHelper(name); 2660 Element helper = compiler.findHelper(name);
2646 if (helper == null) { 2661 if (helper == null) {
2647 // For mocked-up tests. 2662 // For mocked-up tests.
2648 return js.js('(void 0).$name'); 2663 return js.js('(void 0).$name');
2649 } 2664 }
2650 world.registerStaticUse(helper); 2665 world.registerStaticUse(helper);
2651 return backend.namer.elementAccess(helper); 2666 return backend.namer.elementAccess(helper);
2652 } 2667 }
2653 } 2668 }
2654
2655 String singleIdentityComparison(HInstruction left,
2656 HInstruction right,
2657 Compiler compiler) {
2658 // Returns the single identity comparison (== or ===) or null if a more
2659 // complex expression is required.
2660 if (left.canBeNull() && right.canBeNull()) {
2661 if (left.isConstantNull() || right.isConstantNull() ||
2662 (left.isPrimitive(compiler) &&
2663 left.instructionType == right.instructionType)) {
2664 return '==';
2665 }
2666 return null;
2667 } else {
2668 return '===';
2669 }
2670 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698