| Index: src/arm/lithium-codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/lithium-codegen-arm.cc (revision 7030)
|
| +++ src/arm/lithium-codegen-arm.cc (working copy)
|
| @@ -562,17 +562,11 @@
|
| void LCodeGen::CallCode(Handle<Code> code,
|
| RelocInfo::Mode mode,
|
| LInstruction* instr) {
|
| - if (instr != NULL) {
|
| - LPointerMap* pointers = instr->pointer_map();
|
| - RecordPosition(pointers->position());
|
| - __ Call(code, mode);
|
| - RegisterLazyDeoptimization(instr);
|
| - } else {
|
| - LPointerMap no_pointers(0);
|
| - RecordPosition(no_pointers.position());
|
| - __ Call(code, mode);
|
| - RecordSafepoint(&no_pointers, Safepoint::kNoDeoptimizationIndex);
|
| - }
|
| + ASSERT(instr != NULL);
|
| + LPointerMap* pointers = instr->pointer_map();
|
| + RecordPosition(pointers->position());
|
| + __ Call(code, mode);
|
| + RegisterLazyDeoptimization(instr);
|
| }
|
|
|
|
|
| @@ -585,15 +579,7 @@
|
| RecordPosition(pointers->position());
|
|
|
| __ CallRuntime(function, num_arguments);
|
| - // Runtime calls to Throw are not supposed to ever return at the
|
| - // call site, so don't register lazy deoptimization for these. We do
|
| - // however have to record a safepoint since throwing exceptions can
|
| - // cause garbage collections.
|
| - if (!instr->IsThrow()) {
|
| - RegisterLazyDeoptimization(instr);
|
| - } else {
|
| - RecordSafepoint(instr->pointer_map(), Safepoint::kNoDeoptimizationIndex);
|
| - }
|
| + RegisterLazyDeoptimization(instr);
|
| }
|
|
|
|
|
| @@ -736,37 +722,40 @@
|
| }
|
|
|
|
|
| -void LCodeGen::RecordSafepoint(LPointerMap* pointers,
|
| - int deoptimization_index) {
|
| +void LCodeGen::RecordSafepoint(
|
| + LPointerMap* pointers,
|
| + Safepoint::Kind kind,
|
| + int arguments,
|
| + int deoptimization_index) {
|
| const ZoneList<LOperand*>* operands = pointers->operands();
|
| Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
|
| - deoptimization_index);
|
| + kind, arguments, deoptimization_index);
|
| for (int i = 0; i < operands->length(); i++) {
|
| LOperand* pointer = operands->at(i);
|
| if (pointer->IsStackSlot()) {
|
| safepoint.DefinePointerSlot(pointer->index());
|
| + } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
|
| + safepoint.DefinePointerRegister(ToRegister(pointer));
|
| }
|
| }
|
| + if (kind & Safepoint::kWithRegisters) {
|
| + // Register cp always contains a pointer to the context.
|
| + safepoint.DefinePointerRegister(cp);
|
| + }
|
| }
|
|
|
|
|
| +void LCodeGen::RecordSafepoint(LPointerMap* pointers,
|
| + int deoptimization_index) {
|
| + RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index);
|
| +}
|
| +
|
| +
|
| void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
|
| int arguments,
|
| int deoptimization_index) {
|
| - const ZoneList<LOperand*>* operands = pointers->operands();
|
| - Safepoint safepoint =
|
| - safepoints_.DefineSafepointWithRegisters(
|
| - masm(), arguments, deoptimization_index);
|
| - for (int i = 0; i < operands->length(); i++) {
|
| - LOperand* pointer = operands->at(i);
|
| - if (pointer->IsStackSlot()) {
|
| - safepoint.DefinePointerSlot(pointer->index());
|
| - } else if (pointer->IsRegister()) {
|
| - safepoint.DefinePointerRegister(ToRegister(pointer));
|
| - }
|
| - }
|
| - // Register cp always contains a pointer to the context.
|
| - safepoint.DefinePointerRegister(cp);
|
| + RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments,
|
| + deoptimization_index);
|
| }
|
|
|
|
|
| @@ -774,20 +763,8 @@
|
| LPointerMap* pointers,
|
| int arguments,
|
| int deoptimization_index) {
|
| - const ZoneList<LOperand*>* operands = pointers->operands();
|
| - Safepoint safepoint =
|
| - safepoints_.DefineSafepointWithRegistersAndDoubles(
|
| - masm(), arguments, deoptimization_index);
|
| - for (int i = 0; i < operands->length(); i++) {
|
| - LOperand* pointer = operands->at(i);
|
| - if (pointer->IsStackSlot()) {
|
| - safepoint.DefinePointerSlot(pointer->index());
|
| - } else if (pointer->IsRegister()) {
|
| - safepoint.DefinePointerRegister(ToRegister(pointer));
|
| - }
|
| - }
|
| - // Register cp always contains a pointer to the context.
|
| - safepoint.DefinePointerRegister(cp);
|
| + RecordSafepoint(pointers, Safepoint::kWithRegistersAndDoubles, arguments,
|
| + deoptimization_index);
|
| }
|
|
|
|
|
| @@ -1062,11 +1039,8 @@
|
| }
|
|
|
| // Check for power of two on the right hand side.
|
| - __ sub(scratch, right, Operand(1), SetCC);
|
| - __ b(mi, &call_stub);
|
| - __ tst(scratch, right);
|
| - __ b(ne, &call_stub);
|
| - // Perform modulo operation.
|
| + __ JumpIfNotPowerOfTwoOrZero(right, scratch, &call_stub);
|
| + // Perform modulo operation (scratch contains right - 1).
|
| __ and_(result, scratch, Operand(left));
|
|
|
| __ bind(&call_stub);
|
| @@ -1183,8 +1157,7 @@
|
| 0,
|
| Safepoint::kNoDeoptimizationIndex);
|
| // Overwrite the stored value of r0 with the result of the stub.
|
| - __ str(r0, MemOperand(sp, DwVfpRegister::kNumAllocatableRegisters *
|
| - kDoubleSize));
|
| + __ StoreToSafepointRegistersAndDoublesSlot(r0);
|
| __ PopSafepointRegistersAndDoubles();
|
| }
|
|
|
| @@ -1425,7 +1398,18 @@
|
| __ vdiv(left, left, right);
|
| break;
|
| case Token::MOD: {
|
| - Abort("DoArithmeticD unimplemented for MOD.");
|
| + // Save r0-r3 on the stack.
|
| + __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
|
| +
|
| + __ PrepareCallCFunction(4, scratch0());
|
| + __ vmov(r0, r1, left);
|
| + __ vmov(r2, r3, right);
|
| + __ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 4);
|
| + // Move the result in the double result register.
|
| + __ vmov(ToDoubleRegister(instr->result()), r0, r1);
|
| +
|
| + // Restore r0-r3.
|
| + __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
|
| break;
|
| }
|
| default:
|
| @@ -2000,7 +1984,16 @@
|
|
|
|
|
| void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) {
|
| - Abort("DoInstanceOfAndBranch unimplemented.");
|
| + ASSERT(ToRegister(instr->InputAt(0)).is(r0)); // Object is in r0.
|
| + ASSERT(ToRegister(instr->InputAt(1)).is(r1)); // Function is in r1.
|
| +
|
| + int true_block = chunk_->LookupDestination(instr->true_block_id());
|
| + int false_block = chunk_->LookupDestination(instr->false_block_id());
|
| +
|
| + InstanceofStub stub(InstanceofStub::kArgsInRegisters);
|
| + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
| + __ tst(r0, Operand(r0));
|
| + EmitBranch(true_block, false_block, eq);
|
| }
|
|
|
|
|
| @@ -2195,8 +2188,26 @@
|
|
|
| void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) {
|
| Register value = ToRegister(instr->InputAt(0));
|
| - __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell())));
|
| - __ str(value, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
|
| + Register scratch = scratch0();
|
| +
|
| + // Load the cell.
|
| + __ mov(scratch, Operand(Handle<Object>(instr->hydrogen()->cell())));
|
| +
|
| + // If the cell we are storing to contains the hole it could have
|
| + // been deleted from the property dictionary. In that case, we need
|
| + // to update the property details in the property dictionary to mark
|
| + // it as no longer deleted.
|
| + if (instr->hydrogen()->check_hole_value()) {
|
| + Register scratch2 = ToRegister(instr->TempAt(0));
|
| + __ ldr(scratch2,
|
| + FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
|
| + __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
|
| + __ cmp(scratch2, ip);
|
| + DeoptimizeIf(eq, instr->environment());
|
| + }
|
| +
|
| + // Store the value.
|
| + __ str(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
|
| }
|
|
|
|
|
| @@ -2434,12 +2445,17 @@
|
| __ b(ne, &loop);
|
|
|
| __ bind(&invoke);
|
| - // Invoke the function. The number of arguments is stored in receiver
|
| - // which is r0, as expected by InvokeFunction.
|
| + ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
|
| + LPointerMap* pointers = instr->pointer_map();
|
| + LEnvironment* env = instr->deoptimization_environment();
|
| + RecordPosition(pointers->position());
|
| + RegisterEnvironmentForDeoptimization(env);
|
| + SafepointGenerator safepoint_generator(this,
|
| + pointers,
|
| + env->deoptimization_index());
|
| + // The number of arguments is stored in receiver which is r0, as expected
|
| + // by InvokeFunction.
|
| v8::internal::ParameterCount actual(receiver);
|
| - SafepointGenerator safepoint_generator(this,
|
| - instr->pointer_map(),
|
| - Safepoint::kNoDeoptimizationIndex);
|
| __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
|
| }
|
|
|
| @@ -2509,6 +2525,7 @@
|
|
|
|
|
| void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
|
| + ASSERT(instr->InputAt(0)->Equals(instr->result()));
|
| Register input = ToRegister(instr->InputAt(0));
|
| Register scratch = scratch0();
|
|
|
| @@ -2519,28 +2536,32 @@
|
| DeoptimizeIf(ne, instr->environment());
|
|
|
| Label done;
|
| -
|
| - Label negative;
|
| - __ ldr(scratch, FieldMemOperand(input, HeapNumber::kExponentOffset));
|
| + Register exponent = scratch0();
|
| + scratch = no_reg;
|
| + __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
|
| // Check the sign of the argument. If the argument is positive, just
|
| // return it. We do not need to patch the stack since |input| and
|
| - // |result| are the same register and |input| will be restored
|
| + // |result| are the same register and |input| would be restored
|
| // unchanged by popping safepoint registers.
|
| - __ tst(scratch, Operand(HeapNumber::kSignMask));
|
| - __ b(ne, &negative);
|
| - __ jmp(&done);
|
| + __ tst(exponent, Operand(HeapNumber::kSignMask));
|
| + __ b(eq, &done);
|
|
|
| - __ bind(&negative);
|
| + // Input is negative. Reverse its sign.
|
| // Preserve the value of all registers.
|
| __ PushSafepointRegisters();
|
|
|
| - Register tmp = input.is(r0) ? r1 : r0;
|
| - Register tmp2 = input.is(r2) ? r3 : r2;
|
| - Register tmp3 = input.is(r4) ? r5 : r4;
|
| + // Registers were saved at the safepoint, so we can use
|
| + // many scratch registers.
|
| + Register tmp1 = input.is(r1) ? r0 : r1;
|
| + Register tmp2 = input.is(r2) ? r0 : r2;
|
| + Register tmp3 = input.is(r3) ? r0 : r3;
|
| + Register tmp4 = input.is(r4) ? r0 : r4;
|
|
|
| + // exponent: floating point exponent value.
|
| +
|
| Label allocated, slow;
|
| - __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
|
| - __ AllocateHeapNumber(tmp, tmp2, tmp3, scratch, &slow);
|
| + __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex);
|
| + __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow);
|
| __ b(&allocated);
|
|
|
| // Slow case: Call the runtime system to do the number allocation.
|
| @@ -2550,20 +2571,20 @@
|
| RecordSafepointWithRegisters(
|
| instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
|
| // Set the pointer to the new heap number in tmp.
|
| - if (!tmp.is(r0)) __ mov(tmp, Operand(r0));
|
| -
|
| + if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0));
|
| // Restore input_reg after call to runtime.
|
| - MemOperand input_register_slot = masm()->SafepointRegisterSlot(input);
|
| - __ ldr(input, input_register_slot);
|
| + __ LoadFromSafepointRegisterSlot(input);
|
| + __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
|
|
|
| __ bind(&allocated);
|
| - __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kExponentOffset));
|
| - __ bic(tmp2, tmp2, Operand(HeapNumber::kSignMask));
|
| - __ str(tmp2, FieldMemOperand(tmp, HeapNumber::kExponentOffset));
|
| + // exponent: floating point exponent value.
|
| + // tmp1: allocated heap number.
|
| + __ bic(exponent, exponent, Operand(HeapNumber::kSignMask));
|
| + __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
|
| __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
|
| - __ str(tmp2, FieldMemOperand(tmp, HeapNumber::kMantissaOffset));
|
| + __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
|
|
|
| - __ str(tmp, input_register_slot);
|
| + __ str(tmp1, masm()->SafepointRegisterSlot(input));
|
| __ PopSafepointRegisters();
|
|
|
| __ bind(&done);
|
| @@ -2571,15 +2592,14 @@
|
|
|
|
|
| void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
|
| - Label is_positive;
|
| - uint32_t kSignMask = 0x80000000u;
|
| Register input = ToRegister(instr->InputAt(0));
|
| - __ tst(input, Operand(kSignMask));
|
| - __ b(eq, &is_positive);
|
| - __ rsb(input, input, Operand(0), SetCC);
|
| + __ cmp(input, Operand(0));
|
| + // We can make rsb conditional because the previous cmp instruction
|
| + // will clear the V (overflow) flag and rsb won't set this flag
|
| + // if input is positive.
|
| + __ rsb(input, input, Operand(0), SetCC, mi);
|
| // Deoptimize on overflow.
|
| DeoptimizeIf(vs, instr->environment());
|
| - __ bind(&is_positive);
|
| }
|
|
|
|
|
| @@ -2601,8 +2621,7 @@
|
| Representation r = instr->hydrogen()->value()->representation();
|
| if (r.IsDouble()) {
|
| DwVfpRegister input = ToDoubleRegister(instr->InputAt(0));
|
| - // __ vabs(input, input);
|
| - Abort("Double DoMathAbs unimplemented");
|
| + __ vabs(input, input);
|
| } else if (r.IsInteger32()) {
|
| EmitIntegerMathAbs(instr);
|
| } else {
|
| @@ -3659,10 +3678,14 @@
|
| Register object = ToRegister(instr->object());
|
| Register key = ToRegister(instr->key());
|
| __ Push(object, key);
|
| - RecordPosition(instr->pointer_map()->position());
|
| + ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
|
| + LPointerMap* pointers = instr->pointer_map();
|
| + LEnvironment* env = instr->deoptimization_environment();
|
| + RecordPosition(pointers->position());
|
| + RegisterEnvironmentForDeoptimization(env);
|
| SafepointGenerator safepoint_generator(this,
|
| - instr->pointer_map(),
|
| - Safepoint::kNoDeoptimizationIndex);
|
| + pointers,
|
| + env->deoptimization_index());
|
| __ InvokeBuiltin(Builtins::DELETE, CALL_JS, &safepoint_generator);
|
| }
|
|
|
|
|