| Index: src/x64/lithium-codegen-x64.cc
|
| diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
|
| index bedf1be4371ef960bed101e30e299ebbb5d6d8a5..cf4de7a014228715ef1d7021d1591220ab1b033c 100644
|
| --- a/src/x64/lithium-codegen-x64.cc
|
| +++ b/src/x64/lithium-codegen-x64.cc
|
| @@ -216,11 +216,8 @@ bool LCodeGen::GeneratePrologue() {
|
| // Store it in the context.
|
| int context_offset = Context::SlotOffset(var->index());
|
| __ movq(Operand(rsi, context_offset), rax);
|
| - // Update the write barrier. This clobbers all involved
|
| - // registers, so we have use a third register to avoid
|
| - // clobbering rsi.
|
| - __ movq(rcx, rsi);
|
| - __ RecordWrite(rcx, context_offset, rax, rbx);
|
| + // Update the write barrier.
|
| + __ RecordWrite(rsi, context_offset, rax, rbx);
|
| }
|
| }
|
| Comment(";;; End allocate local context");
|
| @@ -511,8 +508,18 @@ void LCodeGen::CallRuntime(const Runtime::Function* function,
|
|
|
| void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
|
| int argc,
|
| - LInstruction* instr) {
|
| - __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + LInstruction* instr,
|
| + LOperand* context) {
|
| + ASSERT(context->IsRegister() || context->IsStackSlot());
|
| + if (context->IsRegister()) {
|
| + if (!ToRegister(context).is(rsi)) {
|
| + __ movq(rsi, ToRegister(context));
|
| + }
|
| + } else {
|
| + // Context is stack slot.
|
| + __ movq(rsi, ToOperand(context));
|
| + }
|
| +
|
| __ CallRuntimeSaveDoubles(id);
|
| RecordSafepointWithRegisters(
|
| instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex);
|
| @@ -678,10 +685,6 @@ void LCodeGen::RecordSafepoint(
|
| safepoint.DefinePointerRegister(ToRegister(pointer));
|
| }
|
| }
|
| - if (kind & Safepoint::kWithRegisters) {
|
| - // Register rsi always contains a pointer to the context.
|
| - safepoint.DefinePointerRegister(rsi);
|
| - }
|
| }
|
|
|
|
|
| @@ -1262,7 +1265,7 @@ void LCodeGen::DoBitNotI(LBitNotI* instr) {
|
|
|
|
|
| void LCodeGen::DoThrow(LThrow* instr) {
|
| - __ push(ToRegister(instr->InputAt(0)));
|
| + __ push(ToRegister(instr->value()));
|
| CallRuntime(Runtime::kThrow, 1, instr);
|
|
|
| if (FLAG_debug_code) {
|
| @@ -1318,6 +1321,7 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
|
| __ CallCFunction(
|
| ExternalReference::double_fp_operation(Token::MOD, isolate()), 2);
|
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + __ movq(rsi, Immediate(0));
|
| __ movaps(result, xmm0);
|
| break;
|
| default:
|
| @@ -1328,8 +1332,9 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
|
|
|
|
|
| void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
|
| - ASSERT(ToRegister(instr->InputAt(0)).is(rdx));
|
| - ASSERT(ToRegister(instr->InputAt(1)).is(rax));
|
| + ASSERT(ToRegister(instr->context()).is(rsi));
|
| + ASSERT(ToRegister(instr->left()).is(rdx));
|
| + ASSERT(ToRegister(instr->right()).is(rax));
|
| ASSERT(ToRegister(instr->result()).is(rax));
|
|
|
| BinaryOpStub stub(instr->op(), NO_OVERWRITE);
|
| @@ -1829,8 +1834,8 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
|
|
|
| void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
|
| InstanceofStub stub(InstanceofStub::kNoFlags);
|
| - __ push(ToRegister(instr->InputAt(0)));
|
| - __ push(ToRegister(instr->InputAt(1)));
|
| + __ push(ToRegister(instr->left()));
|
| + __ push(ToRegister(instr->right()));
|
| CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
| Label true_value, done;
|
| __ testq(rax, rax);
|
| @@ -1865,7 +1870,7 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
|
| deferred = new DeferredInstanceOfKnownGlobal(this, instr);
|
|
|
| Label done, false_result;
|
| - Register object = ToRegister(instr->InputAt(0));
|
| + Register object = ToRegister(instr->value());
|
|
|
| // A Smi is not an instance of anything.
|
| __ JumpIfSmi(object, &false_result);
|
| @@ -1917,7 +1922,7 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
| InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck);
|
| InstanceofStub stub(flags);
|
|
|
| - __ push(ToRegister(instr->InputAt(0)));
|
| + __ push(ToRegister(instr->value()));
|
| __ Push(instr->function());
|
|
|
| static const int kAdditionalDelta = 10;
|
| @@ -1953,6 +1958,12 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
|
|
|
|
| void LCodeGen::DoCmpT(LCmpT* instr) {
|
| + ASSERT(ToRegister(instr->context()).is(rsi));
|
| + ASSERT((ToRegister(instr->left()).is(rax) &&
|
| + ToRegister(instr->right()).is(rdx)) ||
|
| + (ToRegister(instr->left()).is(rdx) &&
|
| + ToRegister(instr->right()).is(rax)));
|
| + ASSERT(ToRegister(instr->result()).is(rax));
|
| Token::Value op = instr->op();
|
|
|
| Handle<Code> ic = CompareIC::GetUninitialized(op);
|
| @@ -2003,6 +2014,7 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
|
|
|
|
|
| void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
| + ASSERT(ToRegister(instr->context()).is(rsi));
|
| ASSERT(ToRegister(instr->global_object()).is(rax));
|
| ASSERT(ToRegister(instr->result()).is(rax));
|
|
|
| @@ -2015,7 +2027,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
|
|
|
|
| void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
|
| - Register value = ToRegister(instr->InputAt(0));
|
| + Register value = ToRegister(instr->value());
|
| Register temp = ToRegister(instr->TempAt(0));
|
| ASSERT(!value.is(temp));
|
| bool check_hole = instr->hydrogen()->check_hole_value();
|
| @@ -2478,7 +2490,8 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
|
| // TODO(kmillikin): We have a hydrogen value for the global object. See
|
| // if it's better to use it than to explicitly fetch it from the context
|
| // here.
|
| - __ movq(receiver, ContextOperand(rsi, Context::GLOBAL_INDEX));
|
| + __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX));
|
| __ movq(receiver,
|
| FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
|
| __ bind(&receiver_ok);
|
| @@ -2517,6 +2530,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
|
| __ InvokeFunction(function, actual, CALL_FUNCTION,
|
| safepoint_generator, CALL_AS_METHOD);
|
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + __ movq(rsi, Immediate(0));
|
| }
|
|
|
|
|
| @@ -2534,7 +2548,7 @@ void LCodeGen::DoThisFunction(LThisFunction* instr) {
|
|
|
| void LCodeGen::DoContext(LContext* instr) {
|
| Register result = ToRegister(instr->result());
|
| - __ movq(result, rsi);
|
| + __ movq(result, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| }
|
|
|
|
|
| @@ -2547,8 +2561,10 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) {
|
|
|
|
|
| void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
|
| + Register context = ToRegister(instr->context());
|
| Register result = ToRegister(instr->result());
|
| - __ movq(result, GlobalObjectOperand());
|
| + __ movq(result,
|
| + Operand(context, Context::SlotOffset(Context::GLOBAL_INDEX)));
|
| }
|
|
|
|
|
| @@ -2570,6 +2586,8 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
| (scope()->num_heap_slots() > 0);
|
| if (change_context) {
|
| __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
|
| + } else {
|
| + __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| }
|
|
|
| // Set rax to arguments count if adaption is not needed. Assumes that rax
|
| @@ -2594,6 +2612,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
|
|
| // Restore context.
|
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + __ movq(rsi, Immediate(0));
|
| }
|
|
|
|
|
| @@ -2608,7 +2627,7 @@ void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
|
|
|
|
|
| void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
|
| - Register input_reg = ToRegister(instr->InputAt(0));
|
| + Register input_reg = ToRegister(instr->value());
|
| __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
|
| Heap::kHeapNumberMapRootIndex);
|
| DeoptimizeIf(not_equal, instr->environment());
|
| @@ -2639,7 +2658,8 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
|
| // Slow case: Call the runtime system to do the number allocation.
|
| __ bind(&slow);
|
|
|
| - CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
|
| + CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr,
|
| + instr->context());
|
| // Set the pointer to the new heap number in tmp.
|
| if (!tmp.is(rax)) {
|
| __ movq(tmp, rax);
|
| @@ -2660,7 +2680,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
|
|
|
|
|
| void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
|
| - Register input_reg = ToRegister(instr->InputAt(0));
|
| + Register input_reg = ToRegister(instr->value());
|
| __ testl(input_reg, input_reg);
|
| Label is_positive;
|
| __ j(not_sign, &is_positive);
|
| @@ -2684,12 +2704,12 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
|
| LUnaryMathOperation* instr_;
|
| };
|
|
|
| - ASSERT(instr->InputAt(0)->Equals(instr->result()));
|
| + ASSERT(instr->value()->Equals(instr->result()));
|
| Representation r = instr->hydrogen()->value()->representation();
|
|
|
| if (r.IsDouble()) {
|
| XMMRegister scratch = xmm0;
|
| - XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
|
| + XMMRegister input_reg = ToDoubleRegister(instr->value());
|
| __ xorps(scratch, scratch);
|
| __ subsd(scratch, input_reg);
|
| __ andpd(input_reg, scratch);
|
| @@ -2698,7 +2718,7 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
|
| } else { // Tagged case.
|
| DeferredMathAbsTaggedHeapNumber* deferred =
|
| new DeferredMathAbsTaggedHeapNumber(this, instr);
|
| - Register input_reg = ToRegister(instr->InputAt(0));
|
| + Register input_reg = ToRegister(instr->value());
|
| // Smi check.
|
| __ JumpIfNotSmi(input_reg, deferred->entry());
|
| __ SmiToInteger32(input_reg, input_reg);
|
| @@ -2712,7 +2732,7 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
|
| void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
|
| XMMRegister xmm_scratch = xmm0;
|
| Register output_reg = ToRegister(instr->result());
|
| - XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
|
| + XMMRegister input_reg = ToDoubleRegister(instr->value());
|
| Label done;
|
|
|
| if (CpuFeatures::IsSupported(SSE4_1)) {
|
| @@ -2758,7 +2778,7 @@ void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
|
| void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
|
| const XMMRegister xmm_scratch = xmm0;
|
| Register output_reg = ToRegister(instr->result());
|
| - XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
|
| + XMMRegister input_reg = ToDoubleRegister(instr->value());
|
|
|
| Label done;
|
| // xmm_scratch = 0.5
|
| @@ -2803,7 +2823,7 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
|
|
|
|
|
| void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
|
| - XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
|
| + XMMRegister input_reg = ToDoubleRegister(instr->value());
|
| ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
|
| __ sqrtsd(input_reg, input_reg);
|
| }
|
| @@ -2811,7 +2831,7 @@ void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
|
|
|
| void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
|
| XMMRegister xmm_scratch = xmm0;
|
| - XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
|
| + XMMRegister input_reg = ToDoubleRegister(instr->value());
|
| ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
|
| __ xorps(xmm_scratch, xmm_scratch);
|
| __ addsd(input_reg, xmm_scratch); // Convert -0 to +0.
|
| @@ -2872,6 +2892,7 @@ void LCodeGen::DoPower(LPower* instr) {
|
| __ movaps(result_reg, xmm0);
|
| // Restore context register.
|
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + __ movq(rsi, Immediate(0));
|
| }
|
|
|
|
|
| @@ -2944,6 +2965,7 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
|
| ParameterCount count(instr->arity());
|
| __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
|
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + __ movq(rsi, Immediate(0));
|
| }
|
|
|
|
|
| @@ -2956,6 +2978,7 @@ void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
|
| arity, NOT_IN_LOOP);
|
| CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + __ movq(rsi, Immediate(0));
|
| }
|
|
|
|
|
| @@ -2969,6 +2992,7 @@ void LCodeGen::DoCallNamed(LCallNamed* instr) {
|
| __ Move(rcx, instr->name());
|
| CallCode(ic, mode, instr);
|
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + __ movq(rsi, Immediate(0));
|
| }
|
|
|
|
|
| @@ -2979,6 +3003,7 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) {
|
| CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_IMPLICIT);
|
| CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + __ movq(rsi, Immediate(0));
|
| __ Drop(1);
|
| }
|
|
|
| @@ -2991,7 +3016,9 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
|
| isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode);
|
| __ Move(rcx, instr->name());
|
| CallCode(ic, mode, instr);
|
| + __ movq(rsi, Immediate(0));
|
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + __ movq(rsi, Immediate(0));
|
| }
|
|
|
|
|
| @@ -3003,7 +3030,8 @@ void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
|
|
|
|
|
| void LCodeGen::DoCallNew(LCallNew* instr) {
|
| - ASSERT(ToRegister(instr->InputAt(0)).is(rdi));
|
| + ASSERT(ToRegister(instr->context()).is(rsi));
|
| + ASSERT(ToRegister(instr->constructor()).is(rdi));
|
| ASSERT(ToRegister(instr->result()).is(rax));
|
|
|
| Handle<Code> builtin = isolate()->builtins()->JSConstructCall();
|
| @@ -3048,6 +3076,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
|
|
|
|
|
| void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
|
| + ASSERT(ToRegister(instr->context()).is(rsi));
|
| ASSERT(ToRegister(instr->object()).is(rdx));
|
| ASSERT(ToRegister(instr->value()).is(rax));
|
|
|
| @@ -3170,6 +3199,7 @@ void LCodeGen::DoStoreKeyedFastDoubleElement(
|
| }
|
|
|
| void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
|
| + ASSERT(ToRegister(instr->context()).is(rsi));
|
| ASSERT(ToRegister(instr->object()).is(rdx));
|
| ASSERT(ToRegister(instr->key()).is(rcx));
|
| ASSERT(ToRegister(instr->value()).is(rax));
|
| @@ -3300,7 +3330,8 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
|
| __ Integer32ToSmi(index, index);
|
| __ push(index);
|
| }
|
| - CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr);
|
| + CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2,
|
| + instr, instr->context());
|
| if (FLAG_debug_code) {
|
| __ AbortIfNotSmi(rax);
|
| }
|
| @@ -3351,7 +3382,7 @@ void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
|
| PushSafepointRegistersScope scope(this);
|
| __ Integer32ToSmi(char_code, char_code);
|
| __ push(char_code);
|
| - CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr);
|
| + CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context());
|
| __ StoreToSafepointRegisterSlot(result, rax);
|
| }
|
|
|
| @@ -3419,7 +3450,15 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
|
|
|
| {
|
| PushSafepointRegistersScope scope(this);
|
| - CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
|
| + // NumberTagD uses the context from the frame, rather than
|
| + // the environment's HContext or HInlinedContext value.
|
| + // It only calls Runtime::kAllocateHeapNumber.
|
| + // The corresponding HChange instructions are added in a phase that does
|
| + // not have easy access to the local context.
|
| + __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
|
| + RecordSafepointWithRegisters(instr->pointer_map(), 0,
|
| + Safepoint::kNoDeoptimizationIndex);
|
| // Ensure that value in rax survives popping registers.
|
| __ movq(kScratchRegister, rax);
|
| }
|
| @@ -3884,6 +3923,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
|
|
|
|
|
| void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
|
| + ASSERT(ToRegister(instr->context()).is(rsi));
|
| // Use the fast case closure allocation code that allocates in new
|
| // space for nested functions that don't need literals cloning.
|
| Handle<SharedFunctionInfo> shared_info = instr->shared_info();
|
| @@ -3905,7 +3945,7 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
|
|
|
|
|
| void LCodeGen::DoTypeof(LTypeof* instr) {
|
| - LOperand* input = instr->InputAt(0);
|
| + LOperand* input = instr->value();
|
| EmitPushTaggedOperand(input);
|
| CallRuntime(Runtime::kTypeof, 1, instr);
|
| }
|
| @@ -4090,6 +4130,7 @@ void LCodeGen::DoIn(LIn* instr) {
|
|
|
| void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
|
| {
|
| +
|
| PushSafepointRegistersScope scope(this);
|
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
|
|
|