aboutsummaryrefslogtreecommitdiff
path: root/src/ic/x87
diff options
context:
space:
mode:
Diffstat (limited to 'src/ic/x87')
-rw-r--r--src/ic/x87/handler-compiler-x87.cc107
-rw-r--r--src/ic/x87/ic-compiler-x87.cc21
-rw-r--r--src/ic/x87/ic-x87.cc95
-rw-r--r--src/ic/x87/stub-cache-x87.cc29
4 files changed, 126 insertions, 126 deletions
diff --git a/src/ic/x87/handler-compiler-x87.cc b/src/ic/x87/handler-compiler-x87.cc
index 4bf0af25..5eca3dc0 100644
--- a/src/ic/x87/handler-compiler-x87.cc
+++ b/src/ic/x87/handler-compiler-x87.cc
@@ -59,15 +59,21 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
void PropertyHandlerCompiler::PushVectorAndSlot(Register vector,
Register slot) {
MacroAssembler* masm = this->masm();
- __ push(vector);
+ STATIC_ASSERT(LoadWithVectorDescriptor::kSlot <
+ LoadWithVectorDescriptor::kVector);
+ STATIC_ASSERT(StoreWithVectorDescriptor::kSlot <
+ StoreWithVectorDescriptor::kVector);
+ STATIC_ASSERT(StoreTransitionDescriptor::kSlot <
+ StoreTransitionDescriptor::kVector);
__ push(slot);
+ __ push(vector);
}
void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) {
MacroAssembler* masm = this->masm();
- __ pop(slot);
__ pop(vector);
+ __ pop(slot);
}
@@ -77,6 +83,15 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
__ add(esp, Immediate(2 * kPointerSize));
}
+void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
+ MacroAssembler* masm = this->masm();
+ __ push(tmp);
+}
+
+void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
+ MacroAssembler* masm = this->masm();
+ __ pop(tmp);
+}
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
MacroAssembler* masm, Label* miss_label, Register receiver,
@@ -150,12 +165,16 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
DCHECK(!accessor_holder.is(scratch));
// Copy return value.
__ pop(scratch);
- // receiver
+
+ if (is_store) {
+ // Discard stack arguments.
+ __ add(esp, Immediate(StoreWithVectorDescriptor::kStackArgumentsCount *
+ kPointerSize));
+ }
+ // Write the receiver and arguments to stack frame.
__ push(receiver);
- // Write the arguments to stack frame.
if (is_store) {
- DCHECK(!receiver.is(store_parameter));
- DCHECK(!scratch.is(store_parameter));
+ DCHECK(!AreAliased(receiver, scratch, store_parameter));
__ push(store_parameter);
}
__ push(scratch);
@@ -252,8 +271,13 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments, Register scratch) {
// ----------- S t a t e -------------
- // -- esp[0] : return address
+ // -- esp[12] : value
+ // -- esp[8] : slot
+ // -- esp[4] : vector
+ // -- esp[0] : return address
// -----------------------------------
+ __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue);
+
{
FrameScope scope(masm, StackFrame::INTERNAL);
@@ -290,7 +314,14 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
// Restore context register.
__ pop(esi);
}
- __ ret(0);
+ if (accessor_index >= 0) {
+ __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize);
+ } else {
+ // If we generate a global code snippet for deoptimization only, don't try
+ // to drop stack arguments for the StoreIC because they are not a part of
+ // expression stack and deoptimizer does not reconstruct them.
+ __ ret(0);
+ }
}
@@ -316,32 +347,6 @@ static void CompileCallLoadPropertyWithInterceptor(
__ CallRuntime(id);
}
-
-static void StoreIC_PushArgs(MacroAssembler* masm) {
- Register receiver = StoreDescriptor::ReceiverRegister();
- Register name = StoreDescriptor::NameRegister();
- Register value = StoreDescriptor::ValueRegister();
- Register slot = StoreWithVectorDescriptor::SlotRegister();
- Register vector = StoreWithVectorDescriptor::VectorRegister();
-
- __ xchg(receiver, Operand(esp, 0));
- __ push(name);
- __ push(value);
- __ push(slot);
- __ push(vector);
- __ push(receiver); // which contains the return address.
-}
-
-
-void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) {
- // Return address is on the stack.
- StoreIC_PushArgs(masm);
-
- // Do tail-call to runtime routine.
- __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
-}
-
-
#undef __
#define __ ACCESS_MASM(masm())
@@ -360,19 +365,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
}
-void NamedStoreHandlerCompiler::RearrangeVectorAndSlot(
- Register current_map, Register destination_map) {
- DCHECK(destination_map.is(StoreTransitionHelper::MapRegister()));
- DCHECK(current_map.is(StoreTransitionHelper::VectorRegister()));
- ExternalReference virtual_slot =
- ExternalReference::virtual_slot_register(isolate());
- __ mov(destination_map, current_map);
- __ pop(current_map);
- __ mov(Operand::StaticVariable(virtual_slot), current_map);
- __ pop(current_map); // put vector in place.
-}
-
-
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
Register map_reg,
Register scratch,
@@ -532,7 +524,7 @@ void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
Label success;
__ jmp(&success);
__ bind(miss);
- if (IC::ICUseVector(kind())) {
+ if (IC::ShouldPushPopSlotAndVector(kind())) {
DCHECK(kind() == Code::LOAD_IC);
PopVectorAndSlot();
}
@@ -547,7 +539,7 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
Label success;
__ jmp(&success);
GenerateRestoreName(miss, name);
- if (IC::ICUseVector(kind())) PopVectorAndSlot();
+ DCHECK(!IC::ShouldPushPopSlotAndVector(kind()));
TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
}
@@ -641,13 +633,26 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
__ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor);
}
+void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() {
+ // Zap register aliases of the arguments passed on the stack to ensure they
+ // are properly loaded by the handler (debug-only).
+ STATIC_ASSERT(Descriptor::kPassLastArgsOnStack);
+ STATIC_ASSERT(Descriptor::kStackArgumentsCount == 3);
+ __ mov(Descriptor::ValueRegister(), Immediate(kDebugZapValue));
+ __ mov(Descriptor::SlotRegister(), Immediate(kDebugZapValue));
+ __ mov(Descriptor::VectorRegister(), Immediate(kDebugZapValue));
+}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback,
LanguageMode language_mode) {
Register holder_reg = Frontend(name);
+ __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue);
__ pop(scratch1()); // remove the return address
+ // Discard stack arguments.
+ __ add(esp, Immediate(StoreWithVectorDescriptor::kStackArgumentsCount *
+ kPointerSize));
__ push(receiver());
__ push(holder_reg);
// If the callback cannot leak, then push the callback directly,
@@ -679,7 +684,7 @@ Register NamedStoreHandlerCompiler::value() {
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
Label miss;
- if (IC::ICUseVector(kind())) {
+ if (IC::ShouldPushPopSlotAndVector(kind())) {
PushVectorAndSlot();
}
FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING);
@@ -701,7 +706,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->ic_named_load_global_stub(), 1);
// The code above already loads the result into the return register.
- if (IC::ICUseVector(kind())) {
+ if (IC::ShouldPushPopSlotAndVector(kind())) {
DiscardVectorAndSlot();
}
__ ret(0);
diff --git a/src/ic/x87/ic-compiler-x87.cc b/src/ic/x87/ic-compiler-x87.cc
index 9edf63b7..11a8cdcd 100644
--- a/src/ic/x87/ic-compiler-x87.cc
+++ b/src/ic/x87/ic-compiler-x87.cc
@@ -15,14 +15,21 @@ namespace internal {
void PropertyICCompiler::GenerateRuntimeSetProperty(
MacroAssembler* masm, LanguageMode language_mode) {
- // Return address is on the stack.
- DCHECK(!ebx.is(StoreDescriptor::ReceiverRegister()) &&
- !ebx.is(StoreDescriptor::NameRegister()) &&
- !ebx.is(StoreDescriptor::ValueRegister()));
+ typedef StoreWithVectorDescriptor Descriptor;
+ STATIC_ASSERT(Descriptor::kStackArgumentsCount == 3);
+ // ----------- S t a t e -------------
+ // -- esp[12] : value
+ // -- esp[8] : slot
+ // -- esp[4] : vector
+ // -- esp[0] : return address
+ // -----------------------------------
+ __ LoadParameterFromStack<Descriptor>(Descriptor::ValueRegister(),
+ Descriptor::kValue);
+
+ __ mov(Operand(esp, 12), Descriptor::ReceiverRegister());
+ __ mov(Operand(esp, 8), Descriptor::NameRegister());
+ __ mov(Operand(esp, 4), Descriptor::ValueRegister());
__ pop(ebx);
- __ push(StoreDescriptor::ReceiverRegister());
- __ push(StoreDescriptor::NameRegister());
- __ push(StoreDescriptor::ValueRegister());
__ push(Immediate(Smi::FromInt(language_mode)));
__ push(ebx); // return address
diff --git a/src/ic/x87/ic-x87.cc b/src/ic/x87/ic-x87.cc
index 76933f01..baf435e0 100644
--- a/src/ic/x87/ic-x87.cc
+++ b/src/ic/x87/ic-x87.cc
@@ -409,7 +409,7 @@ static void KeyedStoreGenerateMegamorphicHelper(
}
// It's irrelevant whether array is smi-only or not when writing a smi.
__ mov(FixedArrayElementOperand(ebx, key), value);
- __ ret(0);
+ __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize);
__ bind(&non_smi_value);
// Escape to elements kind transition case.
@@ -428,7 +428,7 @@ static void KeyedStoreGenerateMegamorphicHelper(
__ mov(edx, value); // Preserve the value which is returned.
__ RecordWriteArray(ebx, edx, key, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
- __ ret(0);
+ __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize);
__ bind(fast_double);
if (check_map == kCheckMap) {
@@ -457,7 +457,7 @@ static void KeyedStoreGenerateMegamorphicHelper(
__ add(FieldOperand(receiver, JSArray::kLengthOffset),
Immediate(Smi::FromInt(1)));
}
- __ ret(0);
+ __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize);
__ bind(&transition_smi_elements);
__ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset));
@@ -504,12 +504,13 @@ static void KeyedStoreGenerateMegamorphicHelper(
void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm,
LanguageMode language_mode) {
+ typedef StoreWithVectorDescriptor Descriptor;
// Return address is on the stack.
Label slow, fast_object, fast_object_grow;
Label fast_double, fast_double_grow;
Label array, extra, check_if_double_array, maybe_name_key, miss;
- Register receiver = StoreDescriptor::ReceiverRegister();
- Register key = StoreDescriptor::NameRegister();
+ Register receiver = Descriptor::ReceiverRegister();
+ Register key = Descriptor::NameRegister();
DCHECK(receiver.is(edx));
DCHECK(key.is(ecx));
@@ -522,6 +523,10 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm,
__ test_b(FieldOperand(edi, Map::kBitFieldOffset),
Immediate(1 << Map::kIsAccessCheckNeeded));
__ j(not_zero, &slow);
+
+ __ LoadParameterFromStack<Descriptor>(Descriptor::ValueRegister(),
+ Descriptor::kValue);
+
// Check that the key is a smi.
__ JumpIfNotSmi(key, &maybe_name_key);
__ CmpInstanceType(edi, JS_ARRAY_TYPE);
@@ -551,22 +556,9 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm,
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
__ JumpIfNotUniqueNameInstanceType(ebx, &slow);
-
- // The handlers in the stub cache expect a vector and slot. Since we won't
- // change the IC from any downstream misses, a dummy vector can be used.
- Handle<TypeFeedbackVector> dummy_vector =
- TypeFeedbackVector::DummyVector(masm->isolate());
- int slot = dummy_vector->GetIndex(
- FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot));
- __ push(Immediate(Smi::FromInt(slot)));
- __ push(Immediate(dummy_vector));
-
masm->isolate()->store_stub_cache()->GenerateProbe(masm, receiver, key, edi,
no_reg);
- __ pop(StoreWithVectorDescriptor::VectorRegister());
- __ pop(StoreWithVectorDescriptor::SlotRegister());
-
// Cache miss.
__ jmp(&miss);
@@ -705,18 +697,21 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
}
static void StoreIC_PushArgs(MacroAssembler* masm) {
- Register receiver = StoreDescriptor::ReceiverRegister();
- Register name = StoreDescriptor::NameRegister();
- Register value = StoreDescriptor::ValueRegister();
- Register slot = StoreWithVectorDescriptor::SlotRegister();
- Register vector = StoreWithVectorDescriptor::VectorRegister();
-
- __ xchg(receiver, Operand(esp, 0));
+ Register receiver = StoreWithVectorDescriptor::ReceiverRegister();
+ Register name = StoreWithVectorDescriptor::NameRegister();
+
+ STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3);
+ // Current stack layout:
+ // - esp[12] -- value
+ // - esp[8] -- slot
+ // - esp[4] -- vector
+ // - esp[0] -- return address
+
+ Register return_address = StoreWithVectorDescriptor::SlotRegister();
+ __ pop(return_address);
+ __ push(receiver);
__ push(name);
- __ push(value);
- __ push(slot);
- __ push(vector);
- __ push(receiver); // Contains the return address.
+ __ push(return_address);
}
@@ -730,32 +725,33 @@ void StoreIC::GenerateMiss(MacroAssembler* masm) {
void StoreIC::GenerateNormal(MacroAssembler* masm) {
+ typedef StoreWithVectorDescriptor Descriptor;
Label restore_miss;
- Register receiver = StoreDescriptor::ReceiverRegister();
- Register name = StoreDescriptor::NameRegister();
- Register value = StoreDescriptor::ValueRegister();
- Register vector = StoreWithVectorDescriptor::VectorRegister();
- Register slot = StoreWithVectorDescriptor::SlotRegister();
-
- // A lot of registers are needed for storing to slow case
- // objects. Push and restore receiver but rely on
- // GenerateDictionaryStore preserving the value and name.
+ Register receiver = Descriptor::ReceiverRegister();
+ Register name = Descriptor::NameRegister();
+ Register value = Descriptor::ValueRegister();
+ // Since the slot and vector values are passed on the stack we can use
+ // respective registers as scratch registers.
+ Register scratch1 = Descriptor::VectorRegister();
+ Register scratch2 = Descriptor::SlotRegister();
+
+ __ LoadParameterFromStack<Descriptor>(value, Descriptor::kValue);
+
+ // A lot of registers are needed for storing to slow case objects.
+ // Push and restore receiver but rely on GenerateDictionaryStore preserving
+ // the value and name.
__ push(receiver);
- __ push(vector);
- __ push(slot);
- Register dictionary = ebx;
+ Register dictionary = receiver;
__ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset));
GenerateDictionaryStore(masm, &restore_miss, dictionary, name, value,
- receiver, edi);
- __ Drop(3);
+ scratch1, scratch2);
+ __ Drop(1);
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->ic_store_normal_hit(), 1);
- __ ret(0);
+ __ ret(Descriptor::kStackArgumentsCount * kPointerSize);
__ bind(&restore_miss);
- __ pop(slot);
- __ pop(vector);
__ pop(receiver);
__ IncrementCounter(counters->ic_store_normal_miss(), 1);
GenerateMiss(masm);
@@ -770,6 +766,13 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kKeyedStoreIC_Miss);
}
+void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
+ // Return address is on the stack.
+ StoreIC_PushArgs(masm);
+
+ // Do tail-call to runtime routine.
+ __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
+}
#undef __
diff --git a/src/ic/x87/stub-cache-x87.cc b/src/ic/x87/stub-cache-x87.cc
index e0656f7c..68fa6154 100644
--- a/src/ic/x87/stub-cache-x87.cc
+++ b/src/ic/x87/stub-cache-x87.cc
@@ -22,8 +22,6 @@ static void ProbeTable(StubCache* stub_cache, MacroAssembler* masm,
ExternalReference key_offset(stub_cache->key_reference(table));
ExternalReference value_offset(stub_cache->value_reference(table));
ExternalReference map_offset(stub_cache->map_reference(table));
- ExternalReference virtual_register =
- ExternalReference::virtual_handler_register(masm->isolate());
Label miss;
Code::Kind ic_kind = stub_cache->ic_kind();
@@ -55,19 +53,15 @@ static void ProbeTable(StubCache* stub_cache, MacroAssembler* masm,
}
#endif
- // The vector and slot were pushed onto the stack before starting the
- // probe, and need to be dropped before calling the handler.
if (is_vector_store) {
- // The overlap here is rather embarrassing. One does what one must.
- Register vector = StoreWithVectorDescriptor::VectorRegister();
+ // The value, vector and slot were passed to the IC on the stack and
+ // they are still there. So we can just jump to the handler.
DCHECK(extra.is(StoreWithVectorDescriptor::SlotRegister()));
__ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag));
- __ pop(vector);
- __ mov(Operand::StaticVariable(virtual_register), extra);
- __ pop(extra); // Pop "slot".
- // Jump to the first instruction in the code stub.
- __ jmp(Operand::StaticVariable(virtual_register));
+ __ jmp(extra);
} else {
+ // The vector and slot were pushed onto the stack before starting the
+ // probe, and need to be dropped before calling the handler.
__ pop(LoadWithVectorDescriptor::VectorRegister());
__ pop(LoadDescriptor::SlotRegister());
__ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag));
@@ -110,19 +104,10 @@ static void ProbeTable(StubCache* stub_cache, MacroAssembler* masm,
// Jump to the first instruction in the code stub.
if (is_vector_store) {
- // The vector and slot were pushed onto the stack before starting the
- // probe, and need to be dropped before calling the handler.
- Register vector = StoreWithVectorDescriptor::VectorRegister();
DCHECK(offset.is(StoreWithVectorDescriptor::SlotRegister()));
- __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag));
- __ mov(Operand::StaticVariable(virtual_register), offset);
- __ pop(vector);
- __ pop(offset); // Pop "slot".
- __ jmp(Operand::StaticVariable(virtual_register));
- } else {
- __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag));
- __ jmp(offset);
}
+ __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag));
+ __ jmp(offset);
// Pop at miss.
__ bind(&miss);