| Index: src/arm/full-codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/full-codegen-arm.cc (revision 6955)
|
| +++ src/arm/full-codegen-arm.cc (working copy)
|
| @@ -517,16 +517,16 @@
|
| }
|
|
|
|
|
| -void FullCodeGenerator::Split(Condition cc,
|
| +void FullCodeGenerator::Split(Condition cond,
|
| Label* if_true,
|
| Label* if_false,
|
| Label* fall_through) {
|
| if (if_false == fall_through) {
|
| - __ b(cc, if_true);
|
| + __ b(cond, if_true);
|
| } else if (if_true == fall_through) {
|
| - __ b(NegateCondition(cc), if_false);
|
| + __ b(NegateCondition(cond), if_false);
|
| } else {
|
| - __ b(cc, if_true);
|
| + __ b(cond, if_true);
|
| __ b(if_false);
|
| }
|
| }
|
| @@ -735,6 +735,8 @@
|
| // Compile all the tests with branches to their bodies.
|
| for (int i = 0; i < clauses->length(); i++) {
|
| CaseClause* clause = clauses->at(i);
|
| + clause->body_target()->entry_label()->Unuse();
|
| +
|
| // The default is not a test, but remember it as final fall through.
|
| if (clause->is_default()) {
|
| default_clause = clause;
|
| @@ -818,7 +820,7 @@
|
|
|
| // Convert the object to a JS object.
|
| Label convert, done_convert;
|
| - __ BranchOnSmi(r0, &convert);
|
| + __ JumpIfSmi(r0, &convert);
|
| __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
|
| __ b(hs, &done_convert);
|
| __ bind(&convert);
|
| @@ -1558,8 +1560,13 @@
|
| void FullCodeGenerator::EmitBinaryOp(Token::Value op,
|
| OverwriteMode mode) {
|
| __ pop(r1);
|
| - GenericBinaryOpStub stub(op, mode, r1, r0);
|
| - __ CallStub(&stub);
|
| + if (op == Token::ADD || op == Token::SUB) {
|
| + TypeRecordingBinaryOpStub stub(op, mode);
|
| + __ CallStub(&stub);
|
| + } else {
|
| + GenericBinaryOpStub stub(op, mode, r1, r0);
|
| + __ CallStub(&stub);
|
| + }
|
| context()->Plug(r0);
|
| }
|
|
|
| @@ -2005,16 +2012,21 @@
|
| // Call to a keyed property.
|
| // For a synthetic property use keyed load IC followed by function call,
|
| // for a regular property use keyed CallIC.
|
| - { PreservePositionScope scope(masm()->positions_recorder());
|
| - VisitForStackValue(prop->obj());
|
| - }
|
| if (prop->is_synthetic()) {
|
| - { PreservePositionScope scope(masm()->positions_recorder());
|
| - VisitForAccumulatorValue(prop->key());
|
| - }
|
| + // Do not visit the object and key subexpressions (they are shared
|
| + // by all occurrences of the same rewritten parameter).
|
| + ASSERT(prop->obj()->AsVariableProxy() != NULL);
|
| + ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
|
| + Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot();
|
| + MemOperand operand = EmitSlotSearch(slot, r1);
|
| + __ ldr(r1, operand);
|
| +
|
| + ASSERT(prop->key()->AsLiteral() != NULL);
|
| + ASSERT(prop->key()->AsLiteral()->handle()->IsSmi());
|
| + __ mov(r0, Operand(prop->key()->AsLiteral()->handle()));
|
| +
|
| // Record source code position for IC call.
|
| SetSourcePosition(prop->position());
|
| - __ pop(r1); // We do not need to keep the receiver.
|
|
|
| Handle<Code> ic(isolate()->builtins()->builtin(
|
| Builtins::KeyedLoadIC_Initialize));
|
| @@ -2024,6 +2036,9 @@
|
| __ Push(r0, r1); // Function, receiver.
|
| EmitCallWithStub(expr);
|
| } else {
|
| + { PreservePositionScope scope(masm()->positions_recorder());
|
| + VisitForStackValue(prop->obj());
|
| + }
|
| EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
|
| }
|
| }
|
| @@ -2141,7 +2156,7 @@
|
| context()->PrepareTest(&materialize_true, &materialize_false,
|
| &if_true, &if_false, &fall_through);
|
|
|
| - __ BranchOnSmi(r0, if_false);
|
| + __ JumpIfSmi(r0, if_false);
|
| __ LoadRoot(ip, Heap::kNullValueRootIndex);
|
| __ cmp(r0, ip);
|
| __ b(eq, if_true);
|
| @@ -2173,7 +2188,7 @@
|
| context()->PrepareTest(&materialize_true, &materialize_false,
|
| &if_true, &if_false, &fall_through);
|
|
|
| - __ BranchOnSmi(r0, if_false);
|
| + __ JumpIfSmi(r0, if_false);
|
| __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
|
| PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
| Split(ge, if_true, if_false, fall_through);
|
| @@ -2194,7 +2209,7 @@
|
| context()->PrepareTest(&materialize_true, &materialize_false,
|
| &if_true, &if_false, &fall_through);
|
|
|
| - __ BranchOnSmi(r0, if_false);
|
| + __ JumpIfSmi(r0, if_false);
|
| __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
|
| __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
|
| __ tst(r1, Operand(1 << Map::kIsUndetectable));
|
| @@ -2240,7 +2255,7 @@
|
| context()->PrepareTest(&materialize_true, &materialize_false,
|
| &if_true, &if_false, &fall_through);
|
|
|
| - __ BranchOnSmi(r0, if_false);
|
| + __ JumpIfSmi(r0, if_false);
|
| __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
|
| PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
| Split(eq, if_true, if_false, fall_through);
|
| @@ -2261,7 +2276,7 @@
|
| context()->PrepareTest(&materialize_true, &materialize_false,
|
| &if_true, &if_false, &fall_through);
|
|
|
| - __ BranchOnSmi(r0, if_false);
|
| + __ JumpIfSmi(r0, if_false);
|
| __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
|
| PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
| Split(eq, if_true, if_false, fall_through);
|
| @@ -2282,7 +2297,7 @@
|
| context()->PrepareTest(&materialize_true, &materialize_false,
|
| &if_true, &if_false, &fall_through);
|
|
|
| - __ BranchOnSmi(r0, if_false);
|
| + __ JumpIfSmi(r0, if_false);
|
| __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
|
| PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
| Split(eq, if_true, if_false, fall_through);
|
| @@ -2389,7 +2404,7 @@
|
| VisitForAccumulatorValue(args->at(0));
|
|
|
| // If the object is a smi, we return null.
|
| - __ BranchOnSmi(r0, &null);
|
| + __ JumpIfSmi(r0, &null);
|
|
|
| // Check that the object is a JS object but take special care of JS
|
| // functions to make sure they have 'Function' as their class.
|
| @@ -2540,7 +2555,7 @@
|
|
|
| Label done;
|
| // If the object is a smi return the object.
|
| - __ BranchOnSmi(r0, &done);
|
| + __ JumpIfSmi(r0, &done);
|
| // If the object is not a value type, return the object.
|
| __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE);
|
| __ b(ne, &done);
|
| @@ -2570,7 +2585,7 @@
|
|
|
| Label done;
|
| // If the object is a smi, return the value.
|
| - __ BranchOnSmi(r1, &done);
|
| + __ JumpIfSmi(r1, &done);
|
|
|
| // If the object is not a value type, return the value.
|
| __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE);
|
| @@ -3004,22 +3019,20 @@
|
| if (prop != NULL) {
|
| VisitForStackValue(prop->obj());
|
| VisitForStackValue(prop->key());
|
| + __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
|
| } else if (var->is_global()) {
|
| __ ldr(r1, GlobalObjectOperand());
|
| __ mov(r0, Operand(var->name()));
|
| __ Push(r1, r0);
|
| + __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
|
| } else {
|
| - // Non-global variable. Call the runtime to look up the context
|
| - // where the variable was introduced.
|
| + // Non-global variable. Call the runtime to delete from the
|
| + // context where the variable was introduced.
|
| __ push(context_register());
|
| __ mov(r2, Operand(var->name()));
|
| __ push(r2);
|
| - __ CallRuntime(Runtime::kLookupContext, 2);
|
| - __ push(r0);
|
| - __ mov(r2, Operand(var->name()));
|
| - __ push(r2);
|
| + __ CallRuntime(Runtime::kDeleteContextSlot, 2);
|
| }
|
| - __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
|
| context()->Plug(r0);
|
| }
|
| break;
|
| @@ -3096,7 +3109,7 @@
|
| bool inline_smi_code = ShouldInlineSmiCase(expr->op());
|
| if (inline_smi_code) {
|
| Label call_stub;
|
| - __ BranchOnNotSmi(r0, &call_stub);
|
| + __ JumpIfNotSmi(r0, &call_stub);
|
| __ mvn(r0, Operand(r0));
|
| // Bit-clear inverted smi-tag.
|
| __ bic(r0, r0, Operand(kSmiTagMask));
|
| @@ -3183,7 +3196,7 @@
|
|
|
| // Call ToNumber only if operand is not a smi.
|
| Label no_conversion;
|
| - __ BranchOnSmi(r0, &no_conversion);
|
| + __ JumpIfSmi(r0, &no_conversion);
|
| __ push(r0);
|
| __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
|
| __ bind(&no_conversion);
|
| @@ -3217,7 +3230,7 @@
|
| __ b(vs, &stub_call);
|
| // We could eliminate this smi check if we split the code at
|
| // the first smi check before calling ToNumber.
|
| - __ BranchOnSmi(r0, &done);
|
| + __ JumpIfSmi(r0, &done);
|
| __ bind(&stub_call);
|
| // Call stub. Undo operation first.
|
| __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
|
| @@ -3473,34 +3486,34 @@
|
|
|
| default: {
|
| VisitForAccumulatorValue(expr->right());
|
| - Condition cc = eq;
|
| + Condition cond = eq;
|
| bool strict = false;
|
| switch (op) {
|
| case Token::EQ_STRICT:
|
| strict = true;
|
| // Fall through
|
| case Token::EQ:
|
| - cc = eq;
|
| + cond = eq;
|
| __ pop(r1);
|
| break;
|
| case Token::LT:
|
| - cc = lt;
|
| + cond = lt;
|
| __ pop(r1);
|
| break;
|
| case Token::GT:
|
| // Reverse left and right sides to obtain ECMA-262 conversion order.
|
| - cc = lt;
|
| + cond = lt;
|
| __ mov(r1, result_register());
|
| __ pop(r0);
|
| break;
|
| case Token::LTE:
|
| // Reverse left and right sides to obtain ECMA-262 conversion order.
|
| - cc = ge;
|
| + cond = ge;
|
| __ mov(r1, result_register());
|
| __ pop(r0);
|
| break;
|
| case Token::GTE:
|
| - cc = ge;
|
| + cond = ge;
|
| __ pop(r1);
|
| break;
|
| case Token::IN:
|
| @@ -3513,19 +3526,19 @@
|
| if (inline_smi_code) {
|
| Label slow_case;
|
| __ orr(r2, r0, Operand(r1));
|
| - __ BranchOnNotSmi(r2, &slow_case);
|
| + __ JumpIfNotSmi(r2, &slow_case);
|
| __ cmp(r1, r0);
|
| - Split(cc, if_true, if_false, NULL);
|
| + Split(cond, if_true, if_false, NULL);
|
| __ bind(&slow_case);
|
| }
|
| CompareFlags flags = inline_smi_code
|
| ? NO_SMI_COMPARE_IN_STUB
|
| : NO_COMPARE_FLAGS;
|
| - CompareStub stub(cc, strict, flags, r1, r0);
|
| + CompareStub stub(cond, strict, flags, r1, r0);
|
| __ CallStub(&stub);
|
| PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
|
| __ cmp(r0, Operand(0, RelocInfo::NONE));
|
| - Split(cc, if_true, if_false, fall_through);
|
| + Split(cond, if_true, if_false, fall_through);
|
| }
|
| }
|
|
|
|
|