aboutsummaryrefslogtreecommitdiff
path: root/src/ic
diff options
context:
space:
mode:
Diffstat (limited to 'src/ic')
-rw-r--r--src/ic/arm/handler-compiler-arm.cc44
-rw-r--r--src/ic/arm/ic-arm.cc14
-rw-r--r--src/ic/arm64/handler-compiler-arm64.cc45
-rw-r--r--src/ic/arm64/ic-arm64.cc15
-rw-r--r--src/ic/handler-compiler.cc103
-rw-r--r--src/ic/handler-compiler.h22
-rw-r--r--src/ic/ia32/handler-compiler-ia32.cc107
-rw-r--r--src/ic/ia32/ic-compiler-ia32.cc21
-rw-r--r--src/ic/ia32/ic-ia32.cc95
-rw-r--r--src/ic/ia32/stub-cache-ia32.cc29
-rw-r--r--src/ic/ic-inl.h1
-rw-r--r--src/ic/ic-state.cc44
-rw-r--r--src/ic/ic-state.h13
-rw-r--r--src/ic/ic.cc208
-rw-r--r--src/ic/ic.h7
-rw-r--r--src/ic/mips/handler-compiler-mips.cc46
-rw-r--r--src/ic/mips/ic-mips.cc27
-rw-r--r--src/ic/mips64/handler-compiler-mips64.cc46
-rw-r--r--src/ic/mips64/ic-mips64.cc27
-rw-r--r--src/ic/ppc/handler-compiler-ppc.cc44
-rw-r--r--src/ic/ppc/ic-ppc.cc14
-rw-r--r--src/ic/s390/handler-compiler-s390.cc42
-rw-r--r--src/ic/s390/ic-s390.cc15
-rw-r--r--src/ic/stub-cache.cc1
-rw-r--r--src/ic/stub-cache.h1
-rw-r--r--src/ic/x64/handler-compiler-x64.cc56
-rw-r--r--src/ic/x64/ic-x64.cc24
-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
31 files changed, 653 insertions, 710 deletions
diff --git a/src/ic/arm/handler-compiler-arm.cc b/src/ic/arm/handler-compiler-arm.cc
index 4ed765e7..691fe3d2 100644
--- a/src/ic/arm/handler-compiler-arm.cc
+++ b/src/ic/arm/handler-compiler-arm.cc
@@ -111,15 +111,21 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
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);
}
@@ -129,6 +135,13 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
__ add(sp, sp, Operand(2 * kPointerSize));
}
+void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
+ // No-op. Return address is in lr register.
+}
+
+void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
+ // No-op. Return address is in lr register.
+}
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
MacroAssembler* masm, Label* miss_label, Register receiver,
@@ -330,24 +343,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
__ TailCallStub(&stub);
}
-
-static void StoreIC_PushArgs(MacroAssembler* masm) {
- __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
- StoreDescriptor::ValueRegister(),
- StoreWithVectorDescriptor::SlotRegister(),
- StoreWithVectorDescriptor::VectorRegister());
-}
-
-
-void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) {
- StoreIC_PushArgs(masm);
-
- // The slow case calls into the runtime to complete the store without causing
- // an IC miss that would otherwise cause a transition to the generic stub.
- __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
-}
-
-
#undef __
#define __ ACCESS_MASM(masm())
@@ -366,12 +361,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
}
-void NamedStoreHandlerCompiler::RearrangeVectorAndSlot(
- Register current_map, Register destination_map) {
- DCHECK(false); // Not implemented.
-}
-
-
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
Register map_reg,
Register scratch,
@@ -629,6 +618,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
__ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor);
}
+void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() {
+ STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack);
+}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback,
diff --git a/src/ic/arm/ic-arm.cc b/src/ic/arm/ic-arm.cc
index fee6ebf2..10ec578f 100644
--- a/src/ic/arm/ic-arm.cc
+++ b/src/ic/arm/ic-arm.cc
@@ -441,10 +441,11 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
static void StoreIC_PushArgs(MacroAssembler* masm) {
- __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
- StoreDescriptor::ValueRegister(),
+ __ Push(StoreWithVectorDescriptor::ValueRegister(),
StoreWithVectorDescriptor::SlotRegister(),
- StoreWithVectorDescriptor::VectorRegister());
+ StoreWithVectorDescriptor::VectorRegister(),
+ StoreWithVectorDescriptor::ReceiverRegister(),
+ StoreWithVectorDescriptor::NameRegister());
}
@@ -454,6 +455,13 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kKeyedStoreIC_Miss);
}
+void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
+ StoreIC_PushArgs(masm);
+
+ // The slow case calls into the runtime to complete the store without causing
+ // an IC miss that would otherwise cause a transition to the generic stub.
+ __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
+}
static void KeyedStoreGenerateMegamorphicHelper(
MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow,
diff --git a/src/ic/arm64/handler-compiler-arm64.cc b/src/ic/arm64/handler-compiler-arm64.cc
index 277b4e71..3f97fddc 100644
--- a/src/ic/arm64/handler-compiler-arm64.cc
+++ b/src/ic/arm64/handler-compiler-arm64.cc
@@ -20,15 +20,21 @@ namespace internal {
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);
}
@@ -38,6 +44,13 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
__ Drop(2);
}
+void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
+ // No-op. Return address is in lr register.
+}
+
+void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
+ // No-op. Return address is in lr register.
+}
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
MacroAssembler* masm, Label* miss_label, Register receiver,
@@ -323,25 +336,6 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
__ Ret();
}
-
-static void StoreIC_PushArgs(MacroAssembler* masm) {
- __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
- StoreDescriptor::ValueRegister(),
- StoreWithVectorDescriptor::SlotRegister(),
- StoreWithVectorDescriptor::VectorRegister());
-}
-
-
-void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) {
- ASM_LOCATION("ElementHandlerCompiler::GenerateStoreSlow");
- StoreIC_PushArgs(masm);
-
- // The slow case calls into the runtime to complete the store without causing
- // an IC miss that would otherwise cause a transition to the generic stub.
- __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
-}
-
-
#undef __
#define __ ACCESS_MASM(masm())
@@ -398,12 +392,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
}
-void NamedStoreHandlerCompiler::RearrangeVectorAndSlot(
- Register current_map, Register destination_map) {
- DCHECK(false); // Not implemented.
-}
-
-
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
Register map_reg,
Register scratch,
@@ -664,6 +652,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
__ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor);
}
+void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() {
+ STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack);
+}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback,
diff --git a/src/ic/arm64/ic-arm64.cc b/src/ic/arm64/ic-arm64.cc
index 9d66eb24..fa9d7c16 100644
--- a/src/ic/arm64/ic-arm64.cc
+++ b/src/ic/arm64/ic-arm64.cc
@@ -445,10 +445,11 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
static void StoreIC_PushArgs(MacroAssembler* masm) {
- __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
- StoreDescriptor::ValueRegister(),
+ __ Push(StoreWithVectorDescriptor::ValueRegister(),
StoreWithVectorDescriptor::SlotRegister(),
- StoreWithVectorDescriptor::VectorRegister());
+ StoreWithVectorDescriptor::VectorRegister(),
+ StoreWithVectorDescriptor::ReceiverRegister(),
+ StoreWithVectorDescriptor::NameRegister());
}
@@ -458,6 +459,14 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kKeyedStoreIC_Miss);
}
+void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
+ ASM_LOCATION("KeyedStoreIC::GenerateSlow");
+ StoreIC_PushArgs(masm);
+
+ // The slow case calls into the runtime to complete the store without causing
+ // an IC miss that would otherwise cause a transition to the generic stub.
+ __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
+}
static void KeyedStoreGenerateMegamorphicHelper(
MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow,
diff --git a/src/ic/handler-compiler.cc b/src/ic/handler-compiler.cc
index b6b81def..3b2e115b 100644
--- a/src/ic/handler-compiler.cc
+++ b/src/ic/handler-compiler.cc
@@ -129,13 +129,13 @@ Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg,
Register PropertyHandlerCompiler::Frontend(Handle<Name> name) {
Label miss;
- if (IC::ICUseVector(kind())) {
+ if (IC::ShouldPushPopSlotAndVector(kind())) {
PushVectorAndSlot();
}
Register reg = FrontendHeader(receiver(), name, &miss, RETURN_HOLDER);
FrontendFooter(name, &miss);
// The footer consumes the vector and slot from the stack if miss occurs.
- if (IC::ICUseVector(kind())) {
+ if (IC::ShouldPushPopSlotAndVector(kind())) {
DiscardVectorAndSlot();
}
return reg;
@@ -209,12 +209,12 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(Handle<Name> name,
Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
Handle<Name> name) {
Label miss;
- if (IC::ICUseVector(kind())) {
+ if (IC::ShouldPushPopSlotAndVector(kind())) {
DCHECK(kind() == Code::LOAD_IC);
PushVectorAndSlot();
}
NonexistentFrontendHeader(name, &miss, scratch2(), scratch3());
- if (IC::ICUseVector(kind())) {
+ if (IC::ShouldPushPopSlotAndVector(kind())) {
DiscardVectorAndSlot();
}
GenerateLoadConstant(isolate()->factory()->undefined_value());
@@ -247,7 +247,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
void NamedLoadHandlerCompiler::InterceptorVectorSlotPush(Register holder_reg) {
- if (IC::ICUseVector(kind())) {
+ if (IC::ShouldPushPopSlotAndVector(kind())) {
if (holder_reg.is(receiver())) {
PushVectorAndSlot();
} else {
@@ -260,7 +260,7 @@ void NamedLoadHandlerCompiler::InterceptorVectorSlotPush(Register holder_reg) {
void NamedLoadHandlerCompiler::InterceptorVectorSlotPop(Register holder_reg,
PopMode mode) {
- if (IC::ICUseVector(kind())) {
+ if (IC::ShouldPushPopSlotAndVector(kind())) {
if (mode == DISCARD) {
DiscardVectorAndSlot();
} else {
@@ -438,7 +438,31 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
Handle<Map> transition, Handle<Name> name) {
Label miss;
- PushVectorAndSlot();
+ // Ensure that the StoreTransitionStub we are going to call has the same
+ // number of stack arguments. This means that we don't have to adapt them
+ // if we decide to call the transition or miss stub.
+ STATIC_ASSERT(Descriptor::kStackArgumentsCount ==
+ StoreTransitionDescriptor::kStackArgumentsCount);
+ STATIC_ASSERT(Descriptor::kStackArgumentsCount == 0 ||
+ Descriptor::kStackArgumentsCount == 3);
+ STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kValue ==
+ StoreTransitionDescriptor::kParameterCount -
+ StoreTransitionDescriptor::kValue);
+ STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kSlot ==
+ StoreTransitionDescriptor::kParameterCount -
+ StoreTransitionDescriptor::kSlot);
+ STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kVector ==
+ StoreTransitionDescriptor::kParameterCount -
+ StoreTransitionDescriptor::kVector);
+
+ if (Descriptor::kPassLastArgsOnStack) {
+ __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue);
+ }
+
+ bool need_save_restore = IC::ShouldPushPopSlotAndVector(kind());
+ if (need_save_restore) {
+ PushVectorAndSlot();
+ }
// Check that we are allowed to write this.
bool is_nonexistent = holder()->map() == transition->GetBackPointer();
@@ -470,23 +494,17 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
DCHECK(!transition->is_access_check_needed());
// Call to respective StoreTransitionStub.
- bool virtual_args = StoreTransitionHelper::HasVirtualSlotArg();
- Register map_reg = StoreTransitionHelper::MapRegister();
+ Register map_reg = StoreTransitionDescriptor::MapRegister();
if (details.type() == DATA_CONSTANT) {
DCHECK(descriptors->GetValue(descriptor)->IsJSFunction());
- Register tmp =
- virtual_args ? StoreWithVectorDescriptor::VectorRegister() : map_reg;
- GenerateRestoreMap(transition, tmp, scratch2(), &miss);
- GenerateConstantCheck(tmp, descriptor, value(), scratch2(), &miss);
- if (virtual_args) {
- // This will move the map from tmp into map_reg.
- RearrangeVectorAndSlot(tmp, map_reg);
- } else {
+ GenerateRestoreMap(transition, map_reg, scratch1(), &miss);
+ GenerateConstantCheck(map_reg, descriptor, value(), scratch1(), &miss);
+ if (need_save_restore) {
PopVectorAndSlot();
}
GenerateRestoreName(name);
- StoreTransitionStub stub(isolate());
+ StoreMapStub stub(isolate());
GenerateTailCall(masm(), stub.GetCode());
} else {
@@ -498,24 +516,29 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
Map::cast(transition->GetBackPointer())->unused_property_fields() == 0
? StoreTransitionStub::ExtendStorageAndStoreMapAndValue
: StoreTransitionStub::StoreMapAndValue;
-
- Register tmp =
- virtual_args ? StoreWithVectorDescriptor::VectorRegister() : map_reg;
- GenerateRestoreMap(transition, tmp, scratch2(), &miss);
- if (virtual_args) {
- RearrangeVectorAndSlot(tmp, map_reg);
- } else {
+ GenerateRestoreMap(transition, map_reg, scratch1(), &miss);
+ if (need_save_restore) {
PopVectorAndSlot();
}
- GenerateRestoreName(name);
- StoreTransitionStub stub(isolate(),
- FieldIndex::ForDescriptor(*transition, descriptor),
- representation, store_mode);
+ // We need to pass name on the stack.
+ PopReturnAddress(this->name());
+ __ Push(name);
+ PushReturnAddress(this->name());
+
+ FieldIndex index = FieldIndex::ForDescriptor(*transition, descriptor);
+ __ Move(StoreNamedTransitionDescriptor::FieldOffsetRegister(),
+ Smi::FromInt(index.index() << kPointerSizeLog2));
+
+ StoreTransitionStub stub(isolate(), index.is_inobject(), representation,
+ store_mode);
GenerateTailCall(masm(), stub.GetCode());
}
- GenerateRestoreName(&miss, name);
- PopVectorAndSlot();
+ __ bind(&miss);
+ if (need_save_restore) {
+ PopVectorAndSlot();
+ }
+ GenerateRestoreName(name);
TailCallBuiltin(masm(), MissBuiltin(kind()));
return GetCode(kind(), name);
@@ -534,7 +557,10 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupIterator* it) {
FieldType* field_type = *it->GetFieldType();
bool need_save_restore = false;
if (RequiresFieldTypeChecks(field_type)) {
- need_save_restore = IC::ICUseVector(kind());
+ need_save_restore = IC::ShouldPushPopSlotAndVector(kind());
+ if (Descriptor::kPassLastArgsOnStack) {
+ __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue);
+ }
if (need_save_restore) PushVectorAndSlot();
GenerateFieldTypeChecks(field_type, value(), &miss);
if (need_save_restore) PopVectorAndSlot();
@@ -568,6 +594,9 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
GenerateTailCall(masm(), slow_stub);
}
Register holder = Frontend(name);
+ if (Descriptor::kPassLastArgsOnStack) {
+ __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue);
+ }
GenerateApiAccessorCall(masm(), call_optimization, handle(object->map()),
receiver(), scratch2(), true, value(), holder,
accessor_index);
@@ -601,13 +630,21 @@ Handle<Object> ElementHandlerCompiler::GetKeyedLoadHandler(
TRACE_HANDLER_STATS(isolate, KeyedLoadIC_KeyedLoadSloppyArgumentsStub);
return KeyedLoadSloppyArgumentsStub(isolate).GetCode();
}
+ bool is_js_array = instance_type == JS_ARRAY_TYPE;
if (elements_kind == DICTIONARY_ELEMENTS) {
+ if (FLAG_tf_load_ic_stub) {
+ int config = KeyedLoadElementsKind::encode(elements_kind) |
+ KeyedLoadConvertHole::encode(false) |
+ KeyedLoadIsJsArray::encode(is_js_array) |
+ LoadHandlerTypeBit::encode(kLoadICHandlerForElements);
+ return handle(Smi::FromInt(config), isolate);
+ }
TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadDictionaryElementStub);
return LoadDictionaryElementStub(isolate).GetCode();
}
DCHECK(IsFastElementsKind(elements_kind) ||
IsFixedTypedArrayElementsKind(elements_kind));
- bool is_js_array = instance_type == JS_ARRAY_TYPE;
+ // TODO(jkummerow): Use IsHoleyElementsKind(elements_kind).
bool convert_hole_to_undefined =
is_js_array && elements_kind == FAST_HOLEY_ELEMENTS &&
*receiver_map == isolate->get_initial_js_array_map(elements_kind);
diff --git a/src/ic/handler-compiler.h b/src/ic/handler-compiler.h
index 525889b8..63ca050c 100644
--- a/src/ic/handler-compiler.h
+++ b/src/ic/handler-compiler.h
@@ -53,6 +53,9 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler {
void DiscardVectorAndSlot();
+ void PushReturnAddress(Register tmp);
+ void PopReturnAddress(Register tmp);
+
// TODO(verwaest): Make non-static.
static void GenerateApiAccessorCall(MacroAssembler* masm,
const CallOptimization& optimization,
@@ -212,13 +215,24 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
public:
+ // All store handlers use StoreWithVectorDescriptor calling convention.
+ typedef StoreWithVectorDescriptor Descriptor;
+
explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<Map> map,
Handle<JSObject> holder)
: PropertyHandlerCompiler(isolate, Code::STORE_IC, map, holder,
- kCacheOnReceiver) {}
+ kCacheOnReceiver) {
+#ifdef DEBUG
+ if (Descriptor::kPassLastArgsOnStack) {
+ ZapStackArgumentsRegisterAliases();
+ }
+#endif
+ }
virtual ~NamedStoreHandlerCompiler() {}
+ void ZapStackArgumentsRegisterAliases();
+
Handle<Code> CompileStoreTransition(Handle<Map> transition,
Handle<Name> name);
Handle<Code> CompileStoreField(LookupIterator* it);
@@ -249,10 +263,6 @@ class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
virtual void FrontendFooter(Handle<Name> name, Label* miss);
void GenerateRestoreName(Label* label, Handle<Name> name);
- // Pop the vector and slot into appropriate registers, moving the map in
- // the process. (This is an accomodation for register pressure on ia32).
- void RearrangeVectorAndSlot(Register current_map, Register destination_map);
-
private:
void GenerateRestoreName(Handle<Name> name);
void GenerateRestoreMap(Handle<Map> transition, Register map_reg,
@@ -283,8 +293,6 @@ class ElementHandlerCompiler : public PropertyHandlerCompiler {
Isolate* isolate);
void CompileElementHandlers(MapHandleList* receiver_maps,
List<Handle<Object>>* handlers);
-
- static void GenerateStoreSlow(MacroAssembler* masm);
};
} // namespace internal
} // namespace v8
diff --git a/src/ic/ia32/handler-compiler-ia32.cc b/src/ic/ia32/handler-compiler-ia32.cc
index b332f117..06c58b8a 100644
--- a/src/ic/ia32/handler-compiler-ia32.cc
+++ b/src/ic/ia32/handler-compiler-ia32.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/ia32/ic-compiler-ia32.cc b/src/ic/ia32/ic-compiler-ia32.cc
index d93b67bf..a52f0468 100644
--- a/src/ic/ia32/ic-compiler-ia32.cc
+++ b/src/ic/ia32/ic-compiler-ia32.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/ia32/ic-ia32.cc b/src/ic/ia32/ic-ia32.cc
index 0550d92e..b7496d46 100644
--- a/src/ic/ia32/ic-ia32.cc
+++ b/src/ic/ia32/ic-ia32.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/ia32/stub-cache-ia32.cc b/src/ic/ia32/stub-cache-ia32.cc
index 939e7fc0..82700d34 100644
--- a/src/ic/ia32/stub-cache-ia32.cc
+++ b/src/ic/ia32/stub-cache-ia32.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);
diff --git a/src/ic/ic-inl.h b/src/ic/ic-inl.h
index f77c40a3..4fc8ada8 100644
--- a/src/ic/ic-inl.h
+++ b/src/ic/ic-inl.h
@@ -7,7 +7,6 @@
#include "src/ic/ic.h"
-#include "src/compiler.h"
#include "src/debug/debug.h"
#include "src/macro-assembler.h"
#include "src/prototype.h"
diff --git a/src/ic/ic-state.cc b/src/ic/ic-state.cc
index d157c926..ea1f16c8 100644
--- a/src/ic/ic-state.cc
+++ b/src/ic/ic-state.cc
@@ -189,15 +189,14 @@ void BinaryOpICState::GenerateAheadOfTime(
#undef GENERATE
}
-
-Type* BinaryOpICState::GetResultType() const {
+AstType* BinaryOpICState::GetResultType() const {
Kind result_kind = result_kind_;
if (HasSideEffects()) {
result_kind = NONE;
} else if (result_kind == GENERIC && op_ == Token::ADD) {
- return Type::NumberOrString();
+ return AstType::NumberOrString();
} else if (result_kind == NUMBER && op_ == Token::SHR) {
- return Type::Unsigned32();
+ return AstType::Unsigned32();
}
DCHECK_NE(GENERIC, result_kind);
return KindToType(result_kind);
@@ -318,20 +317,20 @@ const char* BinaryOpICState::KindToString(Kind kind) {
// static
-Type* BinaryOpICState::KindToType(Kind kind) {
+AstType* BinaryOpICState::KindToType(Kind kind) {
switch (kind) {
case NONE:
- return Type::None();
+ return AstType::None();
case SMI:
- return Type::SignedSmall();
+ return AstType::SignedSmall();
case INT32:
- return Type::Signed32();
+ return AstType::Signed32();
case NUMBER:
- return Type::Number();
+ return AstType::Number();
case STRING:
- return Type::String();
+ return AstType::String();
case GENERIC:
- return Type::Any();
+ return AstType::Any();
}
UNREACHABLE();
return NULL;
@@ -365,29 +364,28 @@ const char* CompareICState::GetStateName(State state) {
return NULL;
}
-
-Type* CompareICState::StateToType(Zone* zone, State state, Handle<Map> map) {
+AstType* CompareICState::StateToType(Zone* zone, State state, Handle<Map> map) {
switch (state) {
case UNINITIALIZED:
- return Type::None();
+ return AstType::None();
case BOOLEAN:
- return Type::Boolean();
+ return AstType::Boolean();
case SMI:
- return Type::SignedSmall();
+ return AstType::SignedSmall();
case NUMBER:
- return Type::Number();
+ return AstType::Number();
case STRING:
- return Type::String();
+ return AstType::String();
case INTERNALIZED_STRING:
- return Type::InternalizedString();
+ return AstType::InternalizedString();
case UNIQUE_NAME:
- return Type::UniqueName();
+ return AstType::UniqueName();
case RECEIVER:
- return Type::Receiver();
+ return AstType::Receiver();
case KNOWN_RECEIVER:
- return map.is_null() ? Type::Receiver() : Type::Class(map, zone);
+ return map.is_null() ? AstType::Receiver() : AstType::Class(map, zone);
case GENERIC:
- return Type::Any();
+ return AstType::Any();
}
UNREACHABLE();
return NULL;
diff --git a/src/ic/ic-state.h b/src/ic/ic-state.h
index 6888a7ab..38be57ac 100644
--- a/src/ic/ic-state.h
+++ b/src/ic/ic-state.h
@@ -6,6 +6,7 @@
#define V8_IC_STATE_H_
#include "src/macro-assembler.h"
+#include "src/parsing/token.h"
namespace v8 {
namespace internal {
@@ -120,9 +121,9 @@ class BinaryOpICState final BASE_EMBEDDED {
Token::Value op() const { return op_; }
Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
- Type* GetLeftType() const { return KindToType(left_kind_); }
- Type* GetRightType() const { return KindToType(right_kind_); }
- Type* GetResultType() const;
+ AstType* GetLeftType() const { return KindToType(left_kind_); }
+ AstType* GetRightType() const { return KindToType(right_kind_); }
+ AstType* GetResultType() const;
void Update(Handle<Object> left, Handle<Object> right, Handle<Object> result);
@@ -140,7 +141,7 @@ class BinaryOpICState final BASE_EMBEDDED {
Kind UpdateKind(Handle<Object> object, Kind kind) const;
static const char* KindToString(Kind kind);
- static Type* KindToType(Kind kind);
+ static AstType* KindToType(Kind kind);
static bool KindMaybeSmi(Kind kind) {
return (kind >= SMI && kind <= NUMBER) || kind == GENERIC;
}
@@ -202,8 +203,8 @@ class CompareICState {
GENERIC
};
- static Type* StateToType(Zone* zone, State state,
- Handle<Map> map = Handle<Map>());
+ static AstType* StateToType(Zone* zone, State state,
+ Handle<Map> map = Handle<Map>());
static State NewInputState(State old_state, Handle<Object> value);
diff --git a/src/ic/ic.cc b/src/ic/ic.cc
index b72791aa..0e751bd3 100644
--- a/src/ic/ic.cc
+++ b/src/ic/ic.cc
@@ -183,6 +183,19 @@ IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus)
extra_ic_state_ = target->extra_ic_state();
}
+// The ICs that don't pass slot and vector through the stack have to
+// save/restore them in the dispatcher.
+bool IC::ShouldPushPopSlotAndVector(Code::Kind kind) {
+ if (kind == Code::LOAD_IC || kind == Code::LOAD_GLOBAL_IC ||
+ kind == Code::KEYED_LOAD_IC || kind == Code::CALL_IC) {
+ return true;
+ }
+ if (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC) {
+ return !StoreWithVectorDescriptor::kPassLastArgsOnStack;
+ }
+ return false;
+}
+
InlineCacheState IC::StateFromCode(Code* code) {
Isolate* isolate = code->GetIsolate();
switch (code->kind()) {
@@ -231,13 +244,6 @@ Code* IC::GetCode() const {
return code;
}
-
-bool IC::AddressIsOptimizedCode() const {
- Code* host =
- isolate()->inner_pointer_to_code_cache()->GetCacheEntry(address())->code;
- return host->kind() == Code::OPTIMIZED_FUNCTION;
-}
-
static void LookupForRead(LookupIterator* it) {
for (; it->IsFound(); it->Next()) {
switch (it->state()) {
@@ -270,7 +276,7 @@ static void LookupForRead(LookupIterator* it) {
}
}
-bool IC::ShouldRecomputeHandler(Handle<Object> receiver, Handle<String> name) {
+bool IC::ShouldRecomputeHandler(Handle<String> name) {
if (!RecomputeHandlerForName(name)) return false;
DCHECK(UseVector());
@@ -320,7 +326,7 @@ void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
// Remove the target from the code cache if it became invalid
// because of changes in the prototype chain to avoid hitting it
// again.
- if (ShouldRecomputeHandler(receiver, Handle<String>::cast(name))) {
+ if (ShouldRecomputeHandler(Handle<String>::cast(name))) {
MarkRecomputeHandler(name);
}
}
@@ -728,7 +734,6 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> code) {
number_of_valid_maps++;
if (number_of_valid_maps > 1 && is_keyed()) return false;
- Handle<Code> ic;
if (number_of_valid_maps == 1) {
ConfigureVectorState(name, receiver_map(), code);
} else {
@@ -1413,17 +1418,18 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
Object);
} else if (FLAG_use_ic && !object->IsAccessCheckNeeded() &&
!object->IsJSValue()) {
- if (object->IsJSObject() || (object->IsString() && key->IsNumber())) {
- Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
- if (object->IsString() || key->IsSmi()) UpdateLoadElement(receiver);
+ if ((object->IsJSObject() && key->IsSmi()) ||
+ (object->IsString() && key->IsNumber())) {
+ UpdateLoadElement(Handle<HeapObject>::cast(object));
+ TRACE_IC("LoadIC", key);
}
}
if (!is_vector_set()) {
ConfigureVectorState(MEGAMORPHIC, key);
TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
+ TRACE_IC("LoadIC", key);
}
- TRACE_IC("LoadIC", key);
if (!load_handle.is_null()) return load_handle;
@@ -2237,7 +2243,8 @@ void CallIC::HandleMiss(Handle<Object> function) {
RUNTIME_FUNCTION(Runtime_CallIC_Miss) {
TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
- DCHECK(args.length() == 3);
+ DCHECK_EQ(3, args.length());
+ // Runtime functions don't follow the IC's calling convention.
Handle<Object> function = args.at<Object>(0);
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1);
Handle<Smi> slot = args.at<Smi>(2);
@@ -2253,9 +2260,9 @@ RUNTIME_FUNCTION(Runtime_CallIC_Miss) {
RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
- Handle<Object> receiver = args.at<Object>(0);
-
DCHECK_EQ(4, args.length());
+ // Runtime functions don't follow the IC's calling convention.
+ Handle<Object> receiver = args.at<Object>(0);
Handle<Smi> slot = args.at<Smi>(2);
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
@@ -2294,6 +2301,7 @@ RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) {
TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
+ // Runtime functions don't follow the IC's calling convention.
Handle<JSGlobalObject> global = isolate->global_object();
Handle<Smi> slot = args.at<Smi>(0);
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1);
@@ -2364,10 +2372,10 @@ RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Slow) {
RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) {
TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
+ DCHECK_EQ(4, args.length());
+ // Runtime functions don't follow the IC's calling convention.
Handle<Object> receiver = args.at<Object>(0);
Handle<Object> key = args.at<Object>(1);
-
- DCHECK(args.length() == 4);
Handle<Smi> slot = args.at<Smi>(2);
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
@@ -2381,8 +2389,8 @@ RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) {
RUNTIME_FUNCTION(Runtime_KeyedLoadIC_MissFromStubFailure) {
TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
- DCHECK_EQ(4, args.length());
typedef LoadWithVectorDescriptor Descriptor;
+ DCHECK_EQ(Descriptor::kParameterCount, args.length());
Handle<Object> receiver = args.at<Object>(Descriptor::kReceiver);
Handle<Object> key = args.at<Object>(Descriptor::kName);
Handle<Smi> slot = args.at<Smi>(Descriptor::kSlot);
@@ -2400,13 +2408,13 @@ RUNTIME_FUNCTION(Runtime_KeyedLoadIC_MissFromStubFailure) {
RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
- Handle<Object> receiver = args.at<Object>(0);
- Handle<Name> key = args.at<Name>(1);
- Handle<Object> value = args.at<Object>(2);
-
- DCHECK(args.length() == 5 || args.length() == 6);
- Handle<Smi> slot = args.at<Smi>(3);
- Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
+ DCHECK_EQ(5, args.length());
+ // Runtime functions don't follow the IC's calling convention.
+ Handle<Object> value = args.at<Object>(0);
+ Handle<Smi> slot = args.at<Smi>(1);
+ Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2);
+ Handle<Object> receiver = args.at<Object>(3);
+ Handle<Name> key = args.at<Name>(4);
FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) {
StoreICNexus nexus(vector, vector_slot);
@@ -2424,88 +2432,17 @@ RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
}
-RUNTIME_FUNCTION(Runtime_StoreIC_MissFromStubFailure) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
- HandleScope scope(isolate);
- DCHECK_EQ(5, args.length());
- typedef StoreWithVectorDescriptor Descriptor;
- Handle<Object> receiver = args.at<Object>(Descriptor::kReceiver);
- Handle<Name> key = args.at<Name>(Descriptor::kName);
- Handle<Object> value = args.at<Object>(Descriptor::kValue);
- Handle<Smi> slot = args.at<Smi>(Descriptor::kSlot);
- Handle<TypeFeedbackVector> vector =
- args.at<TypeFeedbackVector>(Descriptor::kVector);
-
- FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
- if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) {
- StoreICNexus nexus(vector, vector_slot);
- StoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
- ic.UpdateState(receiver, key);
- RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
- } else {
- DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC,
- vector->GetKind(vector_slot));
- KeyedStoreICNexus nexus(vector, vector_slot);
- KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
- ic.UpdateState(receiver, key);
- RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
- }
-}
-
-RUNTIME_FUNCTION(Runtime_TransitionStoreIC_MissFromStubFailure) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
- HandleScope scope(isolate);
- Handle<Object> receiver = args.at<Object>(0);
- Handle<Name> key = args.at<Name>(1);
- Handle<Object> value = args.at<Object>(2);
-
- int length = args.length();
- DCHECK(length == 5 || length == 6);
- // TODO(ishell): use VectorStoreTransitionDescriptor indices here and update
- // this comment:
- //
- // We might have slot and vector, for a normal miss (slot(3), vector(4)).
- // Or, map and vector for a transitioning store miss (map(3), vector(4)).
- // In this case, we need to recover the slot from a virtual register.
- // If length == 6, then a map is included (map(3), slot(4), vector(5)).
- Handle<Smi> slot;
- Handle<TypeFeedbackVector> vector;
- if (length == 5) {
- vector = args.at<TypeFeedbackVector>(4);
- slot = handle(
- *reinterpret_cast<Smi**>(isolate->virtual_slot_register_address()),
- isolate);
- } else {
- vector = args.at<TypeFeedbackVector>(5);
- slot = args.at<Smi>(4);
- }
-
- FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
- if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) {
- StoreICNexus nexus(vector, vector_slot);
- StoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
- ic.UpdateState(receiver, key);
- RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
- } else {
- DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC,
- vector->GetKind(vector_slot));
- KeyedStoreICNexus nexus(vector, vector_slot);
- KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
- ic.UpdateState(receiver, key);
- RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
- }
-}
-
// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {
TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK_EQ(5, args.length());
- Handle<Object> receiver = args.at<Object>(0);
- Handle<Object> key = args.at<Object>(1);
- Handle<Object> value = args.at<Object>(2);
- Handle<Smi> slot = args.at<Smi>(3);
- Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
+ // Runtime functions don't follow the IC's calling convention.
+ Handle<Object> value = args.at<Object>(0);
+ Handle<Smi> slot = args.at<Smi>(1);
+ Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2);
+ Handle<Object> receiver = args.at<Object>(3);
+ Handle<Object> key = args.at<Object>(4);
FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
KeyedStoreICNexus nexus(vector, vector_slot);
KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
@@ -2514,31 +2451,14 @@ RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {
}
-RUNTIME_FUNCTION(Runtime_KeyedStoreIC_MissFromStubFailure) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
- HandleScope scope(isolate);
- DCHECK_EQ(5, args.length());
- typedef StoreWithVectorDescriptor Descriptor;
- Handle<Object> receiver = args.at<Object>(Descriptor::kReceiver);
- Handle<Object> key = args.at<Object>(Descriptor::kName);
- Handle<Object> value = args.at<Object>(Descriptor::kValue);
- Handle<Smi> slot = args.at<Smi>(Descriptor::kSlot);
- Handle<TypeFeedbackVector> vector =
- args.at<TypeFeedbackVector>(Descriptor::kVector);
- FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
- KeyedStoreICNexus nexus(vector, vector_slot);
- KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
- ic.UpdateState(receiver, key);
- RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
-}
-
-
RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
HandleScope scope(isolate);
DCHECK_EQ(5, args.length());
- Handle<Object> object = args.at<Object>(0);
- Handle<Object> key = args.at<Object>(1);
- Handle<Object> value = args.at<Object>(2);
+ // Runtime functions don't follow the IC's calling convention.
+ Handle<Object> value = args.at<Object>(0);
+ // slot and vector parameters are not used.
+ Handle<Object> object = args.at<Object>(3);
+ Handle<Object> key = args.at<Object>(4);
LanguageMode language_mode;
KeyedStoreICNexus nexus(isolate);
KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
@@ -2552,16 +2472,14 @@ RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) {
TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
- // Length == 5 or 6, depending on whether the vector slot
- // is passed in a virtual register or not.
- DCHECK(args.length() == 5 || args.length() == 6);
+ // Runtime functions don't follow the IC's calling convention.
Handle<Object> object = args.at<Object>(0);
Handle<Object> key = args.at<Object>(1);
Handle<Object> value = args.at<Object>(2);
Handle<Map> map = args.at<Map>(3);
LanguageMode language_mode;
KeyedStoreICNexus nexus(isolate);
- KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
+ KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
language_mode = ic.language_mode();
if (object->IsJSObject()) {
JSObject::TransitionElementsKind(Handle<JSObject>::cast(object),
@@ -3000,35 +2918,5 @@ RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) {
return *result;
}
-
-
-RUNTIME_FUNCTION(Runtime_LoadIC_MissFromStubFailure) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
- HandleScope scope(isolate);
- DCHECK_EQ(4, args.length());
- typedef LoadWithVectorDescriptor Descriptor;
- Handle<Object> receiver = args.at<Object>(Descriptor::kReceiver);
- Handle<Name> key = args.at<Name>(Descriptor::kName);
- Handle<Smi> slot = args.at<Smi>(Descriptor::kSlot);
- Handle<TypeFeedbackVector> vector =
- args.at<TypeFeedbackVector>(Descriptor::kVector);
- FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
- // A monomorphic or polymorphic KeyedLoadIC with a string key can call the
- // LoadIC miss handler if the handler misses. Since the vector Nexus is
- // set up outside the IC, handle that here.
- if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::LOAD_IC) {
- LoadICNexus nexus(vector, vector_slot);
- LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
- ic.UpdateState(receiver, key);
- RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
- } else {
- DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC,
- vector->GetKind(vector_slot));
- KeyedLoadICNexus nexus(vector, vector_slot);
- KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
- ic.UpdateState(receiver, key);
- RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
- }
-}
} // namespace internal
} // namespace v8
diff --git a/src/ic/ic.h b/src/ic/ic.h
index 35f38444..bf395f1f 100644
--- a/src/ic/ic.h
+++ b/src/ic/ic.h
@@ -75,6 +75,10 @@ class IC {
kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC;
}
+ // The ICs that don't pass slot and vector through the stack have to
+ // save/restore them in the dispatcher.
+ static bool ShouldPushPopSlotAndVector(Code::Kind kind);
+
static InlineCacheState StateFromCode(Code* code);
protected:
@@ -87,7 +91,6 @@ class IC {
// Get the code object of the caller.
Code* GetCode() const;
- bool AddressIsOptimizedCode() const;
inline bool AddressIsDeoptimizedCode() const;
inline static bool AddressIsDeoptimizedCode(Isolate* isolate,
Address address);
@@ -168,7 +171,7 @@ class IC {
kind_ == Code::KEYED_STORE_IC);
return kind_;
}
- bool ShouldRecomputeHandler(Handle<Object> receiver, Handle<String> name);
+ bool ShouldRecomputeHandler(Handle<String> name);
ExtraICState extra_ic_state() const { return extra_ic_state_; }
diff --git a/src/ic/mips/handler-compiler-mips.cc b/src/ic/mips/handler-compiler-mips.cc
index f4e0f0ba..df7a0df1 100644
--- a/src/ic/mips/handler-compiler-mips.cc
+++ b/src/ic/mips/handler-compiler-mips.cc
@@ -107,13 +107,19 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
void PropertyHandlerCompiler::PushVectorAndSlot(Register vector,
Register slot) {
MacroAssembler* masm = this->masm();
- __ Push(vector, slot);
+ STATIC_ASSERT(LoadWithVectorDescriptor::kSlot <
+ LoadWithVectorDescriptor::kVector);
+ STATIC_ASSERT(StoreWithVectorDescriptor::kSlot <
+ StoreWithVectorDescriptor::kVector);
+ STATIC_ASSERT(StoreTransitionDescriptor::kSlot <
+ StoreTransitionDescriptor::kVector);
+ __ Push(slot, vector);
}
void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) {
MacroAssembler* masm = this->masm();
- __ Pop(vector, slot);
+ __ Pop(slot, vector);
}
@@ -123,6 +129,13 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
__ Addu(sp, sp, Operand(2 * kPointerSize));
}
+void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
+ // No-op. Return address is in ra register.
+}
+
+void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
+ // No-op. Return address is in ra register.
+}
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
MacroAssembler* masm, Label* miss_label, Register receiver,
@@ -317,24 +330,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
__ TailCallStub(&stub);
}
-
-static void StoreIC_PushArgs(MacroAssembler* masm) {
- __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
- StoreDescriptor::ValueRegister(),
- StoreWithVectorDescriptor::SlotRegister(),
- StoreWithVectorDescriptor::VectorRegister());
-}
-
-
-void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) {
- StoreIC_PushArgs(masm);
-
- // The slow case calls into the runtime to complete the store without causing
- // an IC miss that would otherwise cause a transition to the generic stub.
- __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
-}
-
-
#undef __
#define __ ACCESS_MASM(masm())
@@ -353,12 +348,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
}
-void NamedStoreHandlerCompiler::RearrangeVectorAndSlot(
- Register current_map, Register destination_map) {
- DCHECK(false); // Not implemented.
-}
-
-
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
Register map_reg,
Register scratch,
@@ -615,6 +604,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
__ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor);
}
+void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() {
+ STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack);
+}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback,
@@ -675,7 +667,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
DiscardVectorAndSlot();
}
__ Ret(USE_DELAY_SLOT);
- __ mov(v0, result);
+ __ Move(v0, result); // Ensure the stub returns correct value.
FrontendFooter(name, &miss);
diff --git a/src/ic/mips/ic-mips.cc b/src/ic/mips/ic-mips.cc
index 3a28b13b..ce9e3d94 100644
--- a/src/ic/mips/ic-mips.cc
+++ b/src/ic/mips/ic-mips.cc
@@ -494,7 +494,8 @@ static void KeyedStoreGenerateMegamorphicHelper(
__ Addu(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
__ Lsa(address, address, key, kPointerSizeLog2 - kSmiTagSize);
__ sw(value, MemOperand(address));
- __ Ret();
+ __ Ret(USE_DELAY_SLOT);
+ __ Move(v0, value); // Ensure the stub returns correct value.
__ bind(&non_smi_value);
// Escape to elements kind transition case.
@@ -514,7 +515,8 @@ static void KeyedStoreGenerateMegamorphicHelper(
__ mov(scratch, value); // Preserve the value which is returned.
__ RecordWrite(elements, address, scratch, kRAHasNotBeenSaved,
kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
- __ Ret();
+ __ Ret(USE_DELAY_SLOT);
+ __ Move(v0, value); // Ensure the stub returns correct value.
__ bind(fast_double);
if (check_map == kCheckMap) {
@@ -543,7 +545,8 @@ static void KeyedStoreGenerateMegamorphicHelper(
__ Addu(scratch, key, Operand(Smi::FromInt(1)));
__ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
}
- __ Ret();
+ __ Ret(USE_DELAY_SLOT);
+ __ Move(v0, value); // Ensure the stub returns correct value.
__ bind(&transition_smi_elements);
// Transition the array appropriately depending on the value type.
@@ -710,10 +713,11 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm,
static void StoreIC_PushArgs(MacroAssembler* masm) {
- __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
- StoreDescriptor::ValueRegister(),
+ __ Push(StoreWithVectorDescriptor::ValueRegister(),
StoreWithVectorDescriptor::SlotRegister(),
- StoreWithVectorDescriptor::VectorRegister());
+ StoreWithVectorDescriptor::VectorRegister(),
+ StoreWithVectorDescriptor::ReceiverRegister(),
+ StoreWithVectorDescriptor::NameRegister());
}
@@ -723,6 +727,14 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kKeyedStoreIC_Miss);
}
+void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
+ StoreIC_PushArgs(masm);
+
+ // The slow case calls into the runtime to complete the store without causing
+ // an IC miss that would otherwise cause a transition to the generic stub.
+ __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
+}
+
void StoreIC::GenerateMiss(MacroAssembler* masm) {
StoreIC_PushArgs(masm);
@@ -748,7 +760,8 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) {
GenerateDictionaryStore(masm, &miss, dictionary, name, value, t2, t5);
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->ic_store_normal_hit(), 1, t2, t5);
- __ Ret();
+ __ Ret(USE_DELAY_SLOT);
+ __ Move(v0, value); // Ensure the stub returns correct value.
__ bind(&miss);
__ IncrementCounter(counters->ic_store_normal_miss(), 1, t2, t5);
diff --git a/src/ic/mips64/handler-compiler-mips64.cc b/src/ic/mips64/handler-compiler-mips64.cc
index 53b097f8..2190f6d6 100644
--- a/src/ic/mips64/handler-compiler-mips64.cc
+++ b/src/ic/mips64/handler-compiler-mips64.cc
@@ -107,13 +107,19 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
void PropertyHandlerCompiler::PushVectorAndSlot(Register vector,
Register slot) {
MacroAssembler* masm = this->masm();
- __ Push(vector, slot);
+ STATIC_ASSERT(LoadWithVectorDescriptor::kSlot <
+ LoadWithVectorDescriptor::kVector);
+ STATIC_ASSERT(StoreWithVectorDescriptor::kSlot <
+ StoreWithVectorDescriptor::kVector);
+ STATIC_ASSERT(StoreTransitionDescriptor::kSlot <
+ StoreTransitionDescriptor::kVector);
+ __ Push(slot, vector);
}
void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) {
MacroAssembler* masm = this->masm();
- __ Pop(vector, slot);
+ __ Pop(slot, vector);
}
@@ -123,6 +129,13 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
__ Daddu(sp, sp, Operand(2 * kPointerSize));
}
+void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
+ // No-op. Return address is in ra register.
+}
+
+void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
+ // No-op. Return address is in ra register.
+}
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
MacroAssembler* masm, Label* miss_label, Register receiver,
@@ -317,24 +330,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
__ TailCallStub(&stub);
}
-
-static void StoreIC_PushArgs(MacroAssembler* masm) {
- __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
- StoreDescriptor::ValueRegister(),
- StoreWithVectorDescriptor::SlotRegister(),
- StoreWithVectorDescriptor::VectorRegister());
-}
-
-
-void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) {
- StoreIC_PushArgs(masm);
-
- // The slow case calls into the runtime to complete the store without causing
- // an IC miss that would otherwise cause a transition to the generic stub.
- __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
-}
-
-
#undef __
#define __ ACCESS_MASM(masm())
@@ -353,12 +348,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
}
-void NamedStoreHandlerCompiler::RearrangeVectorAndSlot(
- Register current_map, Register destination_map) {
- DCHECK(false); // Not implemented.
-}
-
-
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
Register map_reg,
Register scratch,
@@ -615,6 +604,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
__ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor);
}
+void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() {
+ STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack);
+}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback,
@@ -675,7 +667,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
DiscardVectorAndSlot();
}
__ Ret(USE_DELAY_SLOT);
- __ mov(v0, result);
+ __ Move(v0, result); // Ensure the stub returns correct value.
FrontendFooter(name, &miss);
diff --git a/src/ic/mips64/ic-mips64.cc b/src/ic/mips64/ic-mips64.cc
index b551bc70..c2f3cb60 100644
--- a/src/ic/mips64/ic-mips64.cc
+++ b/src/ic/mips64/ic-mips64.cc
@@ -496,7 +496,8 @@ static void KeyedStoreGenerateMegamorphicHelper(
__ SmiScale(scratch, key, kPointerSizeLog2);
__ Daddu(address, address, scratch);
__ sd(value, MemOperand(address));
- __ Ret();
+ __ Ret(USE_DELAY_SLOT);
+ __ Move(v0, value); // Ensure the stub returns correct value.
__ bind(&non_smi_value);
// Escape to elements kind transition case.
@@ -518,7 +519,8 @@ static void KeyedStoreGenerateMegamorphicHelper(
__ mov(scratch, value); // Preserve the value which is returned.
__ RecordWrite(elements, address, scratch, kRAHasNotBeenSaved,
kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
- __ Ret();
+ __ Ret(USE_DELAY_SLOT);
+ __ Move(v0, value); // Ensure the stub returns correct value.
__ bind(fast_double);
if (check_map == kCheckMap) {
@@ -549,7 +551,8 @@ static void KeyedStoreGenerateMegamorphicHelper(
__ Daddu(scratch, key, Operand(Smi::FromInt(1)));
__ sd(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
}
- __ Ret();
+ __ Ret(USE_DELAY_SLOT);
+ __ Move(v0, value); // Ensure the stub returns correct value.
__ bind(&transition_smi_elements);
// Transition the array appropriately depending on the value type.
@@ -714,10 +717,11 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm,
static void StoreIC_PushArgs(MacroAssembler* masm) {
- __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
- StoreDescriptor::ValueRegister(),
+ __ Push(StoreWithVectorDescriptor::ValueRegister(),
StoreWithVectorDescriptor::SlotRegister(),
- StoreWithVectorDescriptor::VectorRegister());
+ StoreWithVectorDescriptor::VectorRegister(),
+ StoreWithVectorDescriptor::ReceiverRegister(),
+ StoreWithVectorDescriptor::NameRegister());
}
@@ -727,6 +731,14 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kKeyedStoreIC_Miss);
}
+void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
+ StoreIC_PushArgs(masm);
+
+ // The slow case calls into the runtime to complete the store without causing
+ // an IC miss that would otherwise cause a transition to the generic stub.
+ __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
+}
+
void StoreIC::GenerateMiss(MacroAssembler* masm) {
StoreIC_PushArgs(masm);
@@ -750,7 +762,8 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) {
GenerateDictionaryStore(masm, &miss, dictionary, name, value, a6, a7);
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->ic_store_normal_hit(), 1, a6, a7);
- __ Ret();
+ __ Ret(USE_DELAY_SLOT);
+ __ Move(v0, value); // Ensure the stub returns correct value.
__ bind(&miss);
__ IncrementCounter(counters->ic_store_normal_miss(), 1, a6, a7);
diff --git a/src/ic/ppc/handler-compiler-ppc.cc b/src/ic/ppc/handler-compiler-ppc.cc
index 22c0608c..aafdc77c 100644
--- a/src/ic/ppc/handler-compiler-ppc.cc
+++ b/src/ic/ppc/handler-compiler-ppc.cc
@@ -108,13 +108,19 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
void PropertyHandlerCompiler::PushVectorAndSlot(Register vector,
Register slot) {
MacroAssembler* masm = this->masm();
- __ Push(vector, slot);
+ STATIC_ASSERT(LoadWithVectorDescriptor::kSlot <
+ LoadWithVectorDescriptor::kVector);
+ STATIC_ASSERT(StoreWithVectorDescriptor::kSlot <
+ StoreWithVectorDescriptor::kVector);
+ STATIC_ASSERT(StoreTransitionDescriptor::kSlot <
+ StoreTransitionDescriptor::kVector);
+ __ Push(slot, vector);
}
void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) {
MacroAssembler* masm = this->masm();
- __ Pop(vector, slot);
+ __ Pop(slot, vector);
}
@@ -124,6 +130,13 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
__ addi(sp, sp, Operand(2 * kPointerSize));
}
+void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
+ // No-op. Return address is in lr register.
+}
+
+void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
+ // No-op. Return address is in lr register.
+}
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
MacroAssembler* masm, Label* miss_label, Register receiver,
@@ -325,24 +338,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
__ TailCallStub(&stub);
}
-
-static void StoreIC_PushArgs(MacroAssembler* masm) {
- __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
- StoreDescriptor::ValueRegister(),
- StoreWithVectorDescriptor::SlotRegister(),
- StoreWithVectorDescriptor::VectorRegister());
-}
-
-
-void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) {
- StoreIC_PushArgs(masm);
-
- // The slow case calls into the runtime to complete the store without causing
- // an IC miss that would otherwise cause a transition to the generic stub.
- __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
-}
-
-
#undef __
#define __ ACCESS_MASM(masm())
@@ -361,12 +356,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
}
-void NamedStoreHandlerCompiler::RearrangeVectorAndSlot(
- Register current_map, Register destination_map) {
- DCHECK(false); // Not implemented.
-}
-
-
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
Register map_reg,
Register scratch,
@@ -624,6 +613,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
__ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor);
}
+void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() {
+ STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack);
+}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback,
diff --git a/src/ic/ppc/ic-ppc.cc b/src/ic/ppc/ic-ppc.cc
index fd2962d0..6dd78814 100644
--- a/src/ic/ppc/ic-ppc.cc
+++ b/src/ic/ppc/ic-ppc.cc
@@ -451,10 +451,11 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
static void StoreIC_PushArgs(MacroAssembler* masm) {
- __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
- StoreDescriptor::ValueRegister(),
+ __ Push(StoreWithVectorDescriptor::ValueRegister(),
StoreWithVectorDescriptor::SlotRegister(),
- StoreWithVectorDescriptor::VectorRegister());
+ StoreWithVectorDescriptor::VectorRegister(),
+ StoreWithVectorDescriptor::ReceiverRegister(),
+ StoreWithVectorDescriptor::NameRegister());
}
@@ -464,6 +465,13 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kKeyedStoreIC_Miss);
}
+void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
+ StoreIC_PushArgs(masm);
+
+ // The slow case calls into the runtime to complete the store without causing
+ // an IC miss that would otherwise cause a transition to the generic stub.
+ __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
+}
static void KeyedStoreGenerateMegamorphicHelper(
MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow,
diff --git a/src/ic/s390/handler-compiler-s390.cc b/src/ic/s390/handler-compiler-s390.cc
index b399c5a6..504baceb 100644
--- a/src/ic/s390/handler-compiler-s390.cc
+++ b/src/ic/s390/handler-compiler-s390.cc
@@ -105,12 +105,18 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
void PropertyHandlerCompiler::PushVectorAndSlot(Register vector,
Register slot) {
MacroAssembler* masm = this->masm();
- __ Push(vector, slot);
+ STATIC_ASSERT(LoadWithVectorDescriptor::kSlot <
+ LoadWithVectorDescriptor::kVector);
+ STATIC_ASSERT(StoreWithVectorDescriptor::kSlot <
+ StoreWithVectorDescriptor::kVector);
+ STATIC_ASSERT(StoreTransitionDescriptor::kSlot <
+ StoreTransitionDescriptor::kVector);
+ __ Push(slot, vector);
}
void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) {
MacroAssembler* masm = this->masm();
- __ Pop(vector, slot);
+ __ Pop(slot, vector);
}
void PropertyHandlerCompiler::DiscardVectorAndSlot() {
@@ -119,6 +125,14 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
__ la(sp, MemOperand(sp, 2 * kPointerSize));
}
+void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
+ // No-op. Return address is in lr register.
+}
+
+void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
+ // No-op. Return address is in lr register.
+}
+
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
MacroAssembler* masm, Label* miss_label, Register receiver,
Handle<Name> name, Register scratch0, Register scratch1) {
@@ -310,21 +324,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
__ TailCallStub(&stub);
}
-static void StoreIC_PushArgs(MacroAssembler* masm) {
- __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
- StoreDescriptor::ValueRegister(),
- StoreWithVectorDescriptor::SlotRegister(),
- StoreWithVectorDescriptor::VectorRegister());
-}
-
-void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) {
- StoreIC_PushArgs(masm);
-
- // The slow case calls into the runtime to complete the store without causing
- // an IC miss that would otherwise cause a transition to the generic stub.
- __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
-}
-
#undef __
#define __ ACCESS_MASM(masm())
@@ -340,11 +339,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
__ mov(this->name(), Operand(name));
}
-void NamedStoreHandlerCompiler::RearrangeVectorAndSlot(
- Register current_map, Register destination_map) {
- DCHECK(false); // Not implemented.
-}
-
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
Register map_reg,
Register scratch,
@@ -593,6 +587,10 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
__ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor);
}
+void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() {
+ STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack);
+}
+
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback,
LanguageMode language_mode) {
diff --git a/src/ic/s390/ic-s390.cc b/src/ic/s390/ic-s390.cc
index 6bb484a2..08eb3e4f 100644
--- a/src/ic/s390/ic-s390.cc
+++ b/src/ic/s390/ic-s390.cc
@@ -437,10 +437,11 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
}
static void StoreIC_PushArgs(MacroAssembler* masm) {
- __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
- StoreDescriptor::ValueRegister(),
+ __ Push(StoreWithVectorDescriptor::ValueRegister(),
StoreWithVectorDescriptor::SlotRegister(),
- StoreWithVectorDescriptor::VectorRegister());
+ StoreWithVectorDescriptor::VectorRegister(),
+ StoreWithVectorDescriptor::ReceiverRegister(),
+ StoreWithVectorDescriptor::NameRegister());
}
void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
@@ -449,6 +450,14 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kKeyedStoreIC_Miss);
}
+void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
+ StoreIC_PushArgs(masm);
+
+ // The slow case calls into the runtime to complete the store without causing
+ // an IC miss that would otherwise cause a transition to the generic stub.
+ __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
+}
+
static void KeyedStoreGenerateMegamorphicHelper(
MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow,
KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length,
diff --git a/src/ic/stub-cache.cc b/src/ic/stub-cache.cc
index 31d7e2e0..fe1adaaa 100644
--- a/src/ic/stub-cache.cc
+++ b/src/ic/stub-cache.cc
@@ -4,6 +4,7 @@
#include "src/ic/stub-cache.h"
+#include "src/ast/ast.h"
#include "src/base/bits.h"
#include "src/type-info.h"
diff --git a/src/ic/stub-cache.h b/src/ic/stub-cache.h
index a053555d..ebcff448 100644
--- a/src/ic/stub-cache.h
+++ b/src/ic/stub-cache.h
@@ -10,6 +10,7 @@
namespace v8 {
namespace internal {
+class SmallMapList;
// The stub cache is used for megamorphic property accesses.
// It maps (map, name, type) to property access handlers. The cache does not
diff --git a/src/ic/x64/handler-compiler-x64.cc b/src/ic/x64/handler-compiler-x64.cc
index ba4daed3..f386fc5b 100644
--- a/src/ic/x64/handler-compiler-x64.cc
+++ b/src/ic/x64/handler-compiler-x64.cc
@@ -20,15 +20,21 @@ namespace internal {
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);
}
@@ -38,6 +44,15 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
__ addp(rsp, 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,
@@ -321,34 +336,6 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
__ ret(0);
}
-
-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();
-
- __ PopReturnAddressTo(r11);
- __ Push(receiver);
- __ Push(name);
- __ Push(value);
- __ Push(slot);
- __ Push(vector);
- __ PushReturnAddressFrom(r11);
-}
-
-
-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()))
@@ -367,12 +354,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
}
-void NamedStoreHandlerCompiler::RearrangeVectorAndSlot(
- Register current_map, Register destination_map) {
- DCHECK(false); // Not implemented.
-}
-
-
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
Register map_reg,
Register scratch,
@@ -638,6 +619,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
__ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor);
}
+void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() {
+ STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack);
+}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback,
diff --git a/src/ic/x64/ic-x64.cc b/src/ic/x64/ic-x64.cc
index 21a11483..d0445a22 100644
--- a/src/ic/x64/ic-x64.cc
+++ b/src/ic/x64/ic-x64.cc
@@ -706,21 +706,20 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
}
static void StoreIC_PushArgs(MacroAssembler* masm) {
- Register receiver = StoreDescriptor::ReceiverRegister();
- Register name = StoreDescriptor::NameRegister();
- Register value = StoreDescriptor::ValueRegister();
+ Register receiver = StoreWithVectorDescriptor::ReceiverRegister();
+ Register name = StoreWithVectorDescriptor::NameRegister();
+ Register value = StoreWithVectorDescriptor::ValueRegister();
+ Register slot = StoreWithVectorDescriptor::SlotRegister();
+ Register vector = StoreWithVectorDescriptor::VectorRegister();
Register temp = r11;
- DCHECK(!temp.is(receiver) && !temp.is(name) && !temp.is(value));
+ DCHECK(!AreAliased(receiver, name, value, slot, vector, temp));
__ PopReturnAddressTo(temp);
- __ Push(receiver);
- __ Push(name);
__ Push(value);
- Register slot = StoreWithVectorDescriptor::SlotRegister();
- Register vector = StoreWithVectorDescriptor::VectorRegister();
- DCHECK(!temp.is(slot) && !temp.is(vector));
__ Push(slot);
__ Push(vector);
+ __ Push(receiver);
+ __ Push(name);
__ PushReturnAddressFrom(temp);
}
@@ -764,6 +763,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/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);