summaryrefslogtreecommitdiff
path: root/deps/v8/src/ia32/lithium-codegen-ia32.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/ia32/lithium-codegen-ia32.cc')
-rw-r--r--deps/v8/src/ia32/lithium-codegen-ia32.cc138
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();
}