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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
===================================================================
--- sdk/lib/_internal/compiler/implementation/ssa/codegen.dart (revision 21860)
+++ sdk/lib/_internal/compiler/implementation/ssa/codegen.dart (working copy)
@@ -2406,20 +2406,96 @@
}
}
+ js.Expression generateTest(HCheck node) {
+ HInstruction input = node.checkedInput;
+ DartType indexingBehavior =
+ backend.jsIndexingBehaviorInterface.computeType(compiler);
+ js.Expression test;
+ if (node.isInteger()) {
+ // input is !int
+ checkInt(input, '!==');
+ test = pop();
+ } else if (node.isNumber()) {
+ // input is !num
+ checkNum(input, '!==');
+ test = pop();
+ } else if (node.isBoolean()) {
+ // input is !bool
+ checkBool(input, '!==');
+ test = pop();
+ } else if (node.isString()) {
+ // input is !string
+ checkString(input, '!==');
+ test = pop();
+ } else if (node.isExtendableArray()) {
+ // input is !Object || input is !Array || input.isFixed
+ checkObject(input, '!==');
+ js.Expression objectTest = pop();
+ checkArray(input, '!==');
+ js.Expression arrayTest = pop();
+ checkFixedArray(input);
+ test = new js.Binary('||', objectTest, arrayTest);
+ test = new js.Binary('||', test, pop());
+ } else if (node.isMutableArray()) {
+ // input is !Object
+ // || ((input is !Array || input.isImmutable)
+ // && input is !JsIndexingBehavior)
+ checkObject(input, '!==');
+ js.Expression objectTest = pop();
+ checkArray(input, '!==');
+ js.Expression arrayTest = pop();
+ checkImmutableArray(input);
+ js.Binary notArrayOrImmutable = new js.Binary('||', arrayTest, pop());
+ checkType(input, indexingBehavior, negative: true);
+ js.Binary notIndexing = new js.Binary('&&', notArrayOrImmutable, pop());
+ test = new js.Binary('||', objectTest, notIndexing);
+ } else if (node.isReadableArray()) {
+ // input is !Object
+ // || (input is !Array && input is !JsIndexingBehavior)
+ checkObject(input, '!==');
+ js.Expression objectTest = pop();
+ checkArray(input, '!==');
+ js.Expression arrayTest = pop();
+ checkType(input, indexingBehavior, negative: true);
+ js.Expression notIndexing = new js.Binary('&&', arrayTest, pop());
+ test = new js.Binary('||', objectTest, notIndexing);
+ } else if (node.isIndexablePrimitive()) {
+ // input is !String
+ // && (input is !Object
+ // || (input is !Array && input is !JsIndexingBehavior))
+ checkString(input, '!==');
+ js.Expression stringTest = pop();
+ checkObject(input, '!==');
+ js.Expression objectTest = pop();
+ checkArray(input, '!==');
+ js.Expression arrayTest = pop();
+ checkType(input, indexingBehavior, negative: true);
+ js.Binary notIndexingTest = new js.Binary('&&', arrayTest, pop());
+ js.Binary notObjectOrIndexingTest =
+ new js.Binary('||', objectTest, notIndexingTest);
+ test = new js.Binary('&&', stringTest, notObjectOrIndexingTest);
+ } else {
+ compiler.internalError('Unexpected type guard', instruction: input);
+ }
+ return test;
+ }
+
void visitTypeConversion(HTypeConversion node) {
if (node.isChecked) {
- if (node.isArgumentTypeCheck) {
- if (node.isInteger()) {
- checkInt(node.checkedInput, '!==');
- } else {
- assert(node.isNumber());
- checkNum(node.checkedInput, '!==');
- }
- js.Expression test = pop();
+ if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
+ js.Expression test = generateTest(node);
js.Block oldContainer = currentContainer;
js.Statement body = new js.Block.empty();
currentContainer = body;
- generateThrowWithHelper('iae', node.checkedInput);
+ if (node.isArgumentTypeCheck) {
+ generateThrowWithHelper('iae', node.checkedInput);
+ } else if (node.isReceiverTypeCheck) {
+ use(node.checkedInput);
+ String methodName =
+ backend.namer.invocationName(node.receiverTypeCheckSelector);
+ js.Expression call = jsPropertyCall(pop(), methodName, []);
+ pushStatement(new js.Throw(call));
+ }
currentContainer = oldContainer;
body = unwrapStatement(body);
pushStatement(new js.If.noElse(test, body), node);
@@ -2488,7 +2564,7 @@
// Called by visitTypeGuard to generate the actual bailout call, something
// like "return $.foo$bailout(t0, t1);"
- js.Statement bailout(HTypeGuard guard, String reason) {
+ js.Statement bailout(HTypeGuard guard) {
HBailoutTarget target = guard.bailoutTarget;
List<js.Expression> arguments = <js.Expression>[];
arguments.add(new js.LiteralNumber("${guard.state}"));
@@ -2529,86 +2605,8 @@
// Generate a type guard, something like "if (typeof t0 == 'number')" and the
// corresponding bailout call, something like "return $.foo$bailout(t0, t1);"
void visitTypeGuard(HTypeGuard node) {
- HInstruction input = node.guarded;
- DartType indexingBehavior =
- backend.jsIndexingBehaviorInterface.computeType(compiler);
- String message;
- js.Expression test;
- if (node.isInteger()) {
- // if (input is !int) bailout
- checkInt(input, '!==');
- test = pop();
- message = 'Not an integer';
- } else if (node.isNumber()) {
- // if (input is !num) bailout
- checkNum(input, '!==');
- test = pop();
- message = 'Not a number';
- } else if (node.isBoolean()) {
- // if (input is !bool) bailout
- checkBool(input, '!==');
- test = pop();
- message = 'Not a boolean';
- } else if (node.isString()) {
- // if (input is !string) bailout
- checkString(input, '!==');
- test = pop();
- message = 'Not a string';
- } else if (node.isExtendableArray()) {
- // if (input is !Object || input is !Array || input.isFixed) bailout
- checkObject(input, '!==');
- js.Expression objectTest = pop();
- checkArray(input, '!==');
- js.Expression arrayTest = pop();
- checkFixedArray(input);
- test = new js.Binary('||', objectTest, arrayTest);
- test = new js.Binary('||', test, pop());
- message = 'Not an extendable array';
- } else if (node.isMutableArray()) {
- // if (input is !Object
- // || ((input is !Array || input.isImmutable)
- // && input is !JsIndexingBehavior)) bailout
- checkObject(input, '!==');
- js.Expression objectTest = pop();
- checkArray(input, '!==');
- js.Expression arrayTest = pop();
- checkImmutableArray(input);
- js.Binary notArrayOrImmutable = new js.Binary('||', arrayTest, pop());
- checkType(input, indexingBehavior, negative: true);
- js.Binary notIndexing = new js.Binary('&&', notArrayOrImmutable, pop());
- test = new js.Binary('||', objectTest, notIndexing);
- message = 'Not a mutable array';
- } else if (node.isReadableArray()) {
- // if (input is !Object
- // || (input is !Array && input is !JsIndexingBehavior)) bailout
- checkObject(input, '!==');
- js.Expression objectTest = pop();
- checkArray(input, '!==');
- js.Expression arrayTest = pop();
- checkType(input, indexingBehavior, negative: true);
- js.Expression notIndexing = new js.Binary('&&', arrayTest, pop());
- test = new js.Binary('||', objectTest, notIndexing);
- message = 'Not an array';
- } else if (node.isIndexablePrimitive()) {
- // if (input is !String
- // && (input is !Object
- // || (input is !Array && input is !JsIndexingBehavior))) bailout
- checkString(input, '!==');
- js.Expression stringTest = pop();
- checkObject(input, '!==');
- js.Expression objectTest = pop();
- checkArray(input, '!==');
- js.Expression arrayTest = pop();
- checkType(input, indexingBehavior, negative: true);
- js.Binary notIndexingTest = new js.Binary('&&', arrayTest, pop());
- js.Binary notObjectOrIndexingTest =
- new js.Binary('||', objectTest, notIndexingTest);
- test = new js.Binary('&&', stringTest, notObjectOrIndexingTest);
- message = 'Not a string or array';
- } else {
- compiler.internalError('Unexpected type guard', instruction: input);
- }
- pushStatement(new js.If.noElse(test, bailout(node, message)), node);
+ js.Expression test = generateTest(node);
+ pushStatement(new js.If.noElse(test, bailout(node)), node);
}
void visitBailoutTarget(HBailoutTarget target) {

Powered by Google App Engine
This is Rietveld 408576698