| 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) {
|
|
|