diff options
Diffstat (limited to 'deps/v8/src/ia32/lithium-codegen-ia32.cc')
-rw-r--r-- | deps/v8/src/ia32/lithium-codegen-ia32.cc | 138 |
1 files changed, 112 insertions, 26 deletions
diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc index a59b1a5bad..d61ebdc0f6 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.cc +++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc @@ -55,7 +55,7 @@ class SafepointGenerator : public PostCallGenerator { // Ensure that we have enough space in the reloc info to patch // this with calls when doing deoptimization. if (ensure_reloc_space_) { - codegen_->masm()->RecordComment(RelocInfo::kFillerCommentString, true); + codegen_->EnsureRelocSpaceForDeoptimization(); } codegen_->RecordSafepoint(pointers_, deoptimization_index_); } @@ -78,6 +78,7 @@ bool LCodeGen::GenerateCode() { return GeneratePrologue() && GenerateBody() && GenerateDeferredCode() && + GenerateRelocPadding() && GenerateSafepointTable(); } @@ -122,6 +123,16 @@ void LCodeGen::Comment(const char* format, ...) { } +bool LCodeGen::GenerateRelocPadding() { + int reloc_size = masm()->relocation_writer_size(); + while (reloc_size < deoptimization_reloc_size.min_size) { + __ RecordComment(RelocInfo::kFillerCommentString, true); + reloc_size += RelocInfo::kRelocCommentSize; + } + return !is_aborted(); +} + + bool LCodeGen::GeneratePrologue() { ASSERT(is_generating()); @@ -163,6 +174,45 @@ bool LCodeGen::GeneratePrologue() { } } + // Possibly allocate a local context. + int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; + if (heap_slots > 0) { + Comment(";;; Allocate local context"); + // Argument to NewContext is the function, which is still in edi. + __ push(edi); + if (heap_slots <= FastNewContextStub::kMaximumSlots) { + FastNewContextStub stub(heap_slots); + __ CallStub(&stub); + } else { + __ CallRuntime(Runtime::kNewContext, 1); + } + RecordSafepoint(Safepoint::kNoDeoptimizationIndex); + // Context is returned in both eax and esi. It replaces the context + // passed to us. It's saved in the stack and kept live in esi. + __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); + + // Copy parameters into context if necessary. + int num_parameters = scope()->num_parameters(); + for (int i = 0; i < num_parameters; i++) { + Slot* slot = scope()->parameter(i)->AsSlot(); + if (slot != NULL && slot->type() == Slot::CONTEXT) { + int parameter_offset = StandardFrameConstants::kCallerSPOffset + + (num_parameters - 1 - i) * kPointerSize; + // Load parameter from stack. + __ mov(eax, Operand(ebp, parameter_offset)); + // Store it in the context. + int context_offset = Context::SlotOffset(slot->index()); + __ mov(Operand(esi, context_offset), eax); + // Update the write barrier. This clobbers all involved + // registers, so we have to use a third register to avoid + // clobbering esi. + __ mov(ecx, esi); + __ RecordWrite(ecx, context_offset, eax, ebx); + } + } + Comment(";;; End allocate local context"); + } + // Trace the call. if (FLAG_trace) { // We have not executed any compiled code yet, so esi still holds the @@ -335,6 +385,22 @@ void LCodeGen::WriteTranslation(LEnvironment* environment, } +void LCodeGen::EnsureRelocSpaceForDeoptimization() { + // Since we patch the reloc info with RUNTIME_ENTRY calls every patch + // site will take up 2 bytes + any pc-jumps. + // We are conservative and always reserver 6 bytes in case where a + // simple pc-jump is not enough. + uint32_t pc_delta = + masm()->pc_offset() - deoptimization_reloc_size.last_pc_offset; + if (is_uintn(pc_delta, 6)) { + deoptimization_reloc_size.min_size += 2; + } else { + deoptimization_reloc_size.min_size += 6; + } + deoptimization_reloc_size.last_pc_offset = masm()->pc_offset(); +} + + void LCodeGen::AddToTranslation(Translation* translation, LOperand* op, bool is_tagged) { @@ -382,10 +448,13 @@ void LCodeGen::CallCode(Handle<Code> code, ASSERT(instr != NULL); LPointerMap* pointers = instr->pointer_map(); RecordPosition(pointers->position()); + if (!adjusted) { __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); } __ call(code, mode); + + EnsureRelocSpaceForDeoptimization(); RegisterLazyDeoptimization(instr); // Signal that we don't inline smi code before these stubs in the @@ -595,6 +664,12 @@ void LCodeGen::RecordSafepoint(LPointerMap* pointers, } +void LCodeGen::RecordSafepoint(int deoptimization_index) { + LPointerMap empty_pointers(RelocInfo::kNoPosition); + RecordSafepoint(&empty_pointers, deoptimization_index); +} + + void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, int arguments, int deoptimization_index) { @@ -1836,7 +1911,7 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, Label before_push_delta; __ bind(&before_push_delta); __ mov(temp, Immediate(delta)); - __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp); + __ StoreToSafepointRegisterSlot(temp, temp); __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ call(stub.GetCode(), RelocInfo::CODE_TARGET); ASSERT_EQ(kAdditionalDelta, @@ -1844,8 +1919,7 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); // Put the result value into the eax slot and restore all registers. - __ mov(Operand(esp, EspIndexForPushAll(eax) * kPointerSize), eax); - + __ StoreToSafepointRegisterSlot(eax, eax); __ PopSafepointRegisters(); } @@ -2100,13 +2174,13 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) { - Register external_elements = ToRegister(instr->external_pointer()); + Register external_pointer = ToRegister(instr->external_pointer()); Register key = ToRegister(instr->key()); Register result = ToRegister(instr->result()); - ASSERT(result.is(external_elements)); + ASSERT(result.is(external_pointer)); // Load the result. - __ movzx_b(result, Operand(external_elements, key, times_1, 0)); + __ movzx_b(result, Operand(external_pointer, key, times_1, 0)); } @@ -2301,11 +2375,8 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, if (*function == *graph()->info()->closure()) { __ CallSelf(); } else { - // This is an indirect call and will not be recorded in the reloc info. - // Add a comment to the reloc info in case we need to patch this during - // deoptimization. - __ RecordComment(RelocInfo::kFillerCommentString, true); __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset)); + EnsureRelocSpaceForDeoptimization(); } // Setup deoptimization. @@ -2360,7 +2431,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { if (!tmp.is(eax)) __ mov(tmp, eax); // Restore input_reg after call to runtime. - __ mov(input_reg, Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize)); + __ LoadFromSafepointRegisterSlot(input_reg, input_reg); __ bind(&allocated); __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); @@ -2368,7 +2439,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2); - __ mov(Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize), tmp); + __ StoreToSafepointRegisterSlot(input_reg, tmp); __ bind(&done); __ PopSafepointRegisters(); @@ -2493,11 +2564,6 @@ void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { XMMRegister xmm_scratch = xmm0; XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); - ExternalReference negative_infinity = - ExternalReference::address_of_negative_infinity(); - __ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity)); - __ ucomisd(xmm_scratch, input_reg); - DeoptimizeIf(equal, instr->environment()); __ xorpd(xmm_scratch, xmm_scratch); __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. __ sqrtsd(input_reg, input_reg); @@ -2731,6 +2797,25 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { } +void LCodeGen::DoStorePixelArrayElement(LStorePixelArrayElement* instr) { + Register external_pointer = ToRegister(instr->external_pointer()); + Register key = ToRegister(instr->key()); + Register value = ToRegister(instr->value()); + ASSERT(ToRegister(instr->TempAt(0)).is(eax)); + + __ mov(eax, value); + { // Clamp the value to [0..255]. + NearLabel done; + __ test(eax, Immediate(0xFFFFFF00)); + __ j(zero, &done); + __ setcc(negative, eax); // 1 if negative, 0 if positive. + __ dec_b(eax); // 0 if negative, 255 if positive. + __ bind(&done); + } + __ mov_b(Operand(external_pointer, key, times_1, 0), eax); +} + + void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { Register value = ToRegister(instr->value()); Register elements = ToRegister(instr->object()); @@ -2840,19 +2925,20 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { __ test(result, Immediate(kStringRepresentationMask)); __ j(not_zero, deferred->entry()); - // Check for 1-byte or 2-byte string. + // Check for ASCII or two-byte string. __ bind(&flat_string); STATIC_ASSERT(kAsciiStringTag != 0); __ test(result, Immediate(kStringEncodingMask)); __ j(not_zero, &ascii_string); - // 2-byte string. - // Load the 2-byte character code into the result register. + // Two-byte string. + // Load the two-byte character code into the result register. STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); if (instr->index()->IsConstantOperand()) { __ movzx_w(result, FieldOperand(string, - SeqTwoByteString::kHeaderSize + 2 * const_index)); + SeqTwoByteString::kHeaderSize + + (kUC16Size * const_index))); } else { __ movzx_w(result, FieldOperand(string, index, @@ -2908,7 +2994,7 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { __ AbortIfNotSmi(eax); } __ SmiUntag(eax); - __ mov(Operand(esp, EspIndexForPushAll(result) * kPointerSize), eax); + __ StoreToSafepointRegisterSlot(result, eax); __ PopSafepointRegisters(); } @@ -2976,7 +3062,7 @@ void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { // TODO(3095996): Put a valid pointer value in the stack slot where the result // register is stored, as this register is in the pointer map, but contains an // integer value. - __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), Immediate(0)); + __ StoreToSafepointRegisterSlot(reg, Immediate(0)); __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); @@ -2988,7 +3074,7 @@ void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { // number. __ bind(&done); __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0); - __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), reg); + __ StoreToSafepointRegisterSlot(reg, reg); __ PopSafepointRegisters(); } @@ -3030,7 +3116,7 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); - __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), eax); + __ StoreToSafepointRegisterSlot(reg, eax); __ PopSafepointRegisters(); } |