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

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

Issue 14404004: Throw NoSuchMethod or ArgumentError instead of generating a bailout, when we know the next instruct… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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
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 2388 matching lines...) Expand 10 before | Expand all | Expand 10 after
2399 if (negative) { 2399 if (negative) {
2400 checkNonNull(input); 2400 checkNonNull(input);
2401 push(new js.Binary('&&', pop(), pop()), node); 2401 push(new js.Binary('&&', pop(), pop()), node);
2402 } else { 2402 } else {
2403 checkNull(input); 2403 checkNull(input);
2404 push(new js.Binary('||', pop(), pop()), node); 2404 push(new js.Binary('||', pop(), pop()), node);
2405 } 2405 }
2406 } 2406 }
2407 } 2407 }
2408 2408
2409 js.Expression generateTest(HCheck node) {
2410 HInstruction input = node.checkedInput;
2411 DartType indexingBehavior =
2412 backend.jsIndexingBehaviorInterface.computeType(compiler);
2413 js.Expression test;
2414 if (node.isInteger()) {
2415 // input is !int
2416 checkInt(input, '!==');
2417 test = pop();
2418 } else if (node.isNumber()) {
2419 // input is !num
2420 checkNum(input, '!==');
2421 test = pop();
2422 } else if (node.isBoolean()) {
2423 // input is !bool
2424 checkBool(input, '!==');
2425 test = pop();
2426 } else if (node.isString()) {
2427 // input is !string
2428 checkString(input, '!==');
2429 test = pop();
2430 } else if (node.isExtendableArray()) {
2431 // input is !Object || input is !Array || input.isFixed
2432 checkObject(input, '!==');
2433 js.Expression objectTest = pop();
2434 checkArray(input, '!==');
2435 js.Expression arrayTest = pop();
2436 checkFixedArray(input);
2437 test = new js.Binary('||', objectTest, arrayTest);
2438 test = new js.Binary('||', test, pop());
2439 } else if (node.isMutableArray()) {
2440 // input is !Object
2441 // || ((input is !Array || input.isImmutable)
2442 // && input is !JsIndexingBehavior)
2443 checkObject(input, '!==');
2444 js.Expression objectTest = pop();
2445 checkArray(input, '!==');
2446 js.Expression arrayTest = pop();
2447 checkImmutableArray(input);
2448 js.Binary notArrayOrImmutable = new js.Binary('||', arrayTest, pop());
2449 checkType(input, indexingBehavior, negative: true);
2450 js.Binary notIndexing = new js.Binary('&&', notArrayOrImmutable, pop());
2451 test = new js.Binary('||', objectTest, notIndexing);
2452 } else if (node.isReadableArray()) {
2453 // input is !Object
2454 // || (input is !Array && input is !JsIndexingBehavior)
2455 checkObject(input, '!==');
2456 js.Expression objectTest = pop();
2457 checkArray(input, '!==');
2458 js.Expression arrayTest = pop();
2459 checkType(input, indexingBehavior, negative: true);
2460 js.Expression notIndexing = new js.Binary('&&', arrayTest, pop());
2461 test = new js.Binary('||', objectTest, notIndexing);
2462 } else if (node.isIndexablePrimitive()) {
2463 // input is !String
2464 // && (input is !Object
2465 // || (input is !Array && input is !JsIndexingBehavior))
2466 checkString(input, '!==');
2467 js.Expression stringTest = pop();
2468 checkObject(input, '!==');
2469 js.Expression objectTest = pop();
2470 checkArray(input, '!==');
2471 js.Expression arrayTest = pop();
2472 checkType(input, indexingBehavior, negative: true);
2473 js.Binary notIndexingTest = new js.Binary('&&', arrayTest, pop());
2474 js.Binary notObjectOrIndexingTest =
2475 new js.Binary('||', objectTest, notIndexingTest);
2476 test = new js.Binary('&&', stringTest, notObjectOrIndexingTest);
2477 } else {
2478 compiler.internalError('Unexpected type guard', instruction: input);
2479 }
2480 return test;
2481 }
2482
2409 void visitTypeConversion(HTypeConversion node) { 2483 void visitTypeConversion(HTypeConversion node) {
2410 if (node.isChecked) { 2484 if (node.isChecked) {
2411 if (node.isArgumentTypeCheck) { 2485 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
2412 if (node.isInteger()) { 2486 js.Expression test = generateTest(node);
2413 checkInt(node.checkedInput, '!==');
2414 } else {
2415 assert(node.isNumber());
2416 checkNum(node.checkedInput, '!==');
2417 }
2418 js.Expression test = pop();
2419 js.Block oldContainer = currentContainer; 2487 js.Block oldContainer = currentContainer;
2420 js.Statement body = new js.Block.empty(); 2488 js.Statement body = new js.Block.empty();
2421 currentContainer = body; 2489 currentContainer = body;
2422 generateThrowWithHelper('iae', node.checkedInput); 2490 if (node.isArgumentTypeCheck) {
2491 generateThrowWithHelper('iae', node.checkedInput);
2492 } else if (node.isReceiverTypeCheck) {
2493 use(node.checkedInput);
2494 String methodName =
2495 backend.namer.invocationName(node.receiverTypeCheckSelector);
2496 js.Expression call = jsPropertyCall(pop(), methodName, []);
2497 pushStatement(new js.Throw(call));
2498 }
2423 currentContainer = oldContainer; 2499 currentContainer = oldContainer;
2424 body = unwrapStatement(body); 2500 body = unwrapStatement(body);
2425 pushStatement(new js.If.noElse(test, body), node); 2501 pushStatement(new js.If.noElse(test, body), node);
2426 return; 2502 return;
2427 } 2503 }
2428 2504
2429 assert(node.isCheckedModeCheck || node.isCastTypeCheck); 2505 assert(node.isCheckedModeCheck || node.isCastTypeCheck);
2430 DartType type = node.typeExpression; 2506 DartType type = node.typeExpression;
2431 world.registerIsCheck(type, work.resolutionTree); 2507 world.registerIsCheck(type, work.resolutionTree);
2432 2508
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
2481 SsaOptimizedCodeGenerator(backend, work) : super(backend, work); 2557 SsaOptimizedCodeGenerator(backend, work) : super(backend, work);
2482 2558
2483 HBasicBlock beginGraph(HGraph graph) { 2559 HBasicBlock beginGraph(HGraph graph) {
2484 return graph.entry; 2560 return graph.entry;
2485 } 2561 }
2486 2562
2487 void endGraph(HGraph graph) {} 2563 void endGraph(HGraph graph) {}
2488 2564
2489 // Called by visitTypeGuard to generate the actual bailout call, something 2565 // Called by visitTypeGuard to generate the actual bailout call, something
2490 // like "return $.foo$bailout(t0, t1);" 2566 // like "return $.foo$bailout(t0, t1);"
2491 js.Statement bailout(HTypeGuard guard, String reason) { 2567 js.Statement bailout(HTypeGuard guard) {
2492 HBailoutTarget target = guard.bailoutTarget; 2568 HBailoutTarget target = guard.bailoutTarget;
2493 List<js.Expression> arguments = <js.Expression>[]; 2569 List<js.Expression> arguments = <js.Expression>[];
2494 arguments.add(new js.LiteralNumber("${guard.state}")); 2570 arguments.add(new js.LiteralNumber("${guard.state}"));
2495 2571
2496 for (int i = 0; i < target.inputs.length; i++) { 2572 for (int i = 0; i < target.inputs.length; i++) {
2497 HInstruction parameter = target.inputs[i]; 2573 HInstruction parameter = target.inputs[i];
2498 for (int pad = target.padding[i]; pad != 0; pad--) { 2574 for (int pad = target.padding[i]; pad != 0; pad--) {
2499 // This argument will not be used by the bailout function, because 2575 // This argument will not be used by the bailout function, because
2500 // of the control flow (controlled by the state argument passed 2576 // of the control flow (controlled by the state argument passed
2501 // above). We need to pass it to get later arguments in the right 2577 // above). We need to pass it to get later arguments in the right
(...skipping 20 matching lines...) Expand all
2522 bailoutTarget = new js.VariableUse(namer.isolateBailoutAccess(method)); 2598 bailoutTarget = new js.VariableUse(namer.isolateBailoutAccess(method));
2523 } 2599 }
2524 js.Call call = new js.Call(bailoutTarget, arguments); 2600 js.Call call = new js.Call(bailoutTarget, arguments);
2525 attachLocation(call, guard); 2601 attachLocation(call, guard);
2526 return new js.Return(call); 2602 return new js.Return(call);
2527 } 2603 }
2528 2604
2529 // Generate a type guard, something like "if (typeof t0 == 'number')" and the 2605 // Generate a type guard, something like "if (typeof t0 == 'number')" and the
2530 // corresponding bailout call, something like "return $.foo$bailout(t0, t1);" 2606 // corresponding bailout call, something like "return $.foo$bailout(t0, t1);"
2531 void visitTypeGuard(HTypeGuard node) { 2607 void visitTypeGuard(HTypeGuard node) {
2532 HInstruction input = node.guarded; 2608 js.Expression test = generateTest(node);
2533 DartType indexingBehavior = 2609 pushStatement(new js.If.noElse(test, bailout(node)), node);
2534 backend.jsIndexingBehaviorInterface.computeType(compiler);
2535 String message;
2536 js.Expression test;
2537 if (node.isInteger()) {
2538 // if (input is !int) bailout
2539 checkInt(input, '!==');
2540 test = pop();
2541 message = 'Not an integer';
2542 } else if (node.isNumber()) {
2543 // if (input is !num) bailout
2544 checkNum(input, '!==');
2545 test = pop();
2546 message = 'Not a number';
2547 } else if (node.isBoolean()) {
2548 // if (input is !bool) bailout
2549 checkBool(input, '!==');
2550 test = pop();
2551 message = 'Not a boolean';
2552 } else if (node.isString()) {
2553 // if (input is !string) bailout
2554 checkString(input, '!==');
2555 test = pop();
2556 message = 'Not a string';
2557 } else if (node.isExtendableArray()) {
2558 // if (input is !Object || input is !Array || input.isFixed) bailout
2559 checkObject(input, '!==');
2560 js.Expression objectTest = pop();
2561 checkArray(input, '!==');
2562 js.Expression arrayTest = pop();
2563 checkFixedArray(input);
2564 test = new js.Binary('||', objectTest, arrayTest);
2565 test = new js.Binary('||', test, pop());
2566 message = 'Not an extendable array';
2567 } else if (node.isMutableArray()) {
2568 // if (input is !Object
2569 // || ((input is !Array || input.isImmutable)
2570 // && input is !JsIndexingBehavior)) bailout
2571 checkObject(input, '!==');
2572 js.Expression objectTest = pop();
2573 checkArray(input, '!==');
2574 js.Expression arrayTest = pop();
2575 checkImmutableArray(input);
2576 js.Binary notArrayOrImmutable = new js.Binary('||', arrayTest, pop());
2577 checkType(input, indexingBehavior, negative: true);
2578 js.Binary notIndexing = new js.Binary('&&', notArrayOrImmutable, pop());
2579 test = new js.Binary('||', objectTest, notIndexing);
2580 message = 'Not a mutable array';
2581 } else if (node.isReadableArray()) {
2582 // if (input is !Object
2583 // || (input is !Array && input is !JsIndexingBehavior)) bailout
2584 checkObject(input, '!==');
2585 js.Expression objectTest = pop();
2586 checkArray(input, '!==');
2587 js.Expression arrayTest = pop();
2588 checkType(input, indexingBehavior, negative: true);
2589 js.Expression notIndexing = new js.Binary('&&', arrayTest, pop());
2590 test = new js.Binary('||', objectTest, notIndexing);
2591 message = 'Not an array';
2592 } else if (node.isIndexablePrimitive()) {
2593 // if (input is !String
2594 // && (input is !Object
2595 // || (input is !Array && input is !JsIndexingBehavior))) bailout
2596 checkString(input, '!==');
2597 js.Expression stringTest = pop();
2598 checkObject(input, '!==');
2599 js.Expression objectTest = pop();
2600 checkArray(input, '!==');
2601 js.Expression arrayTest = pop();
2602 checkType(input, indexingBehavior, negative: true);
2603 js.Binary notIndexingTest = new js.Binary('&&', arrayTest, pop());
2604 js.Binary notObjectOrIndexingTest =
2605 new js.Binary('||', objectTest, notIndexingTest);
2606 test = new js.Binary('&&', stringTest, notObjectOrIndexingTest);
2607 message = 'Not a string or array';
2608 } else {
2609 compiler.internalError('Unexpected type guard', instruction: input);
2610 }
2611 pushStatement(new js.If.noElse(test, bailout(node, message)), node);
2612 } 2610 }
2613 2611
2614 void visitBailoutTarget(HBailoutTarget target) { 2612 void visitBailoutTarget(HBailoutTarget target) {
2615 // Do nothing. Bailout targets are only used in the non-optimized version. 2613 // Do nothing. Bailout targets are only used in the non-optimized version.
2616 } 2614 }
2617 2615
2618 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2616 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2619 } 2617 }
2620 2618
2621 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2619 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
2992 if (leftType.canBeNull() && rightType.canBeNull()) { 2990 if (leftType.canBeNull() && rightType.canBeNull()) {
2993 if (left.isConstantNull() || right.isConstantNull() || 2991 if (left.isConstantNull() || right.isConstantNull() ||
2994 (leftType.isPrimitive() && leftType == rightType)) { 2992 (leftType.isPrimitive() && leftType == rightType)) {
2995 return '=='; 2993 return '==';
2996 } 2994 }
2997 return null; 2995 return null;
2998 } else { 2996 } else {
2999 return '==='; 2997 return '===';
3000 } 2998 }
3001 } 2999 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698