[ic][ia32][x87] Pass value, slot and vector to StoreIC and KeyedStoreIC through the stack.

The handlers cleanup will be done in a follow-up CL.

BUG=v8:5407

Review-Url: https://codereview.chromium.org/2357163003
Cr-Commit-Position: refs/heads/master@{#39617}
This commit is contained in:
ishell 2016-09-22 01:43:53 -07:00 committed by Commit bot
parent 502b9aa71b
commit 76cfb388de
15 changed files with 305 additions and 103 deletions

View File

@ -88,8 +88,10 @@ void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
CallDescriptor::Flags flags,
Operator::Properties properties) {
const CallInterfaceDescriptor& descriptor = callable.descriptor();
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), zone(), callable.descriptor(), 0, flags, properties);
isolate(), zone(), descriptor, descriptor.GetStackParameterCount(), flags,
properties);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(zone(), 0, stub_code);
NodeProperties::ChangeOp(node, common()->Call(desc));

View File

@ -237,6 +237,14 @@ void FullCodeGenerator::CallLoadGlobalIC(TypeofMode typeof_mode,
void FullCodeGenerator::CallStoreIC(TypeFeedbackId id) {
Handle<Code> ic = CodeFactory::StoreIC(isolate(), language_mode()).code();
STATIC_ASSERT(!StoreDescriptor::kPassLastArgsOnStack ||
StoreDescriptor::kStackArgumentsCount == 2);
if (StoreDescriptor::kPassLastArgsOnStack) {
__ Push(StoreDescriptor::ValueRegister());
__ Push(StoreDescriptor::SlotRegister());
}
CallIC(ic, id);
RestoreContext();
}
@ -244,6 +252,14 @@ void FullCodeGenerator::CallStoreIC(TypeFeedbackId id) {
void FullCodeGenerator::CallKeyedStoreIC() {
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
STATIC_ASSERT(!StoreDescriptor::kPassLastArgsOnStack ||
StoreDescriptor::kStackArgumentsCount == 2);
if (StoreDescriptor::kPassLastArgsOnStack) {
__ Push(StoreDescriptor::ValueRegister());
__ Push(StoreDescriptor::SlotRegister());
}
CallIC(ic);
RestoreContext();
}

View File

@ -3671,6 +3671,28 @@ void StoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
Register slot = StoreWithVectorDescriptor::SlotRegister(); // edi
Label miss;
if (StoreWithVectorDescriptor::kPassLastArgsOnStack) {
// Current stack layout:
// - esp[8] -- value
// - esp[4] -- slot
// - esp[0] -- return address
STATIC_ASSERT(StoreDescriptor::kStackArgumentsCount == 2);
STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3);
if (in_frame) {
__ RecordComment("[ StoreDescriptor -> StoreWithVectorDescriptor");
// If the vector is not on the stack, then insert the vector beneath
// return address in order to prepare for calling handler with
// StoreWithVector calling convention.
__ push(Operand(esp, 0));
__ mov(Operand(esp, 4), StoreWithVectorDescriptor::VectorRegister());
__ RecordComment("]");
} else {
__ mov(vector, Operand(esp, 1 * kPointerSize));
}
__ mov(slot, Operand(esp, 2 * kPointerSize));
__ mov(value, Operand(esp, 3 * kPointerSize));
}
__ push(value);
Register scratch = value;
@ -3812,12 +3834,23 @@ static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm,
__ pop(vector);
__ pop(receiver);
__ pop(value);
{
// Put vector and slot beneath return address.
__ push(vector);
__ push(Operand(esp, 1 * kPointerSize)); // push return address
__ mov(Operand(esp, 2 * kPointerSize), slot);
}
// Ensure that the transition handler we are going to call has the same
// number of stack arguments which means that we don't have to adapt them
// before the call.
STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3);
STATIC_ASSERT(StoreTransitionDescriptor::kStackArgumentsCount == 3);
STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount -
StoreWithVectorDescriptor::kValue ==
StoreTransitionDescriptor::kParameterCount -
StoreTransitionDescriptor::kValue);
STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount -
StoreWithVectorDescriptor::kSlot ==
StoreTransitionDescriptor::kParameterCount -
StoreTransitionDescriptor::kSlot);
STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount -
StoreWithVectorDescriptor::kVector ==
StoreTransitionDescriptor::kParameterCount -
StoreTransitionDescriptor::kVector);
__ jmp(Operand::StaticVariable(virtual_register));
__ bind(&prepare_next);
@ -3845,6 +3878,28 @@ void KeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
Register slot = StoreWithVectorDescriptor::SlotRegister(); // edi
Label miss;
if (StoreWithVectorDescriptor::kPassLastArgsOnStack) {
// Current stack layout:
// - esp[8] -- value
// - esp[4] -- slot
// - esp[0] -- return address
STATIC_ASSERT(StoreDescriptor::kStackArgumentsCount == 2);
STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3);
if (in_frame) {
__ RecordComment("[ StoreDescriptor -> StoreWithVectorDescriptor");
// If the vector is not on the stack, then insert the vector beneath
// return address in order to prepare for calling handler with
// StoreWithVector calling convention.
__ push(Operand(esp, 0));
__ mov(Operand(esp, 4), StoreWithVectorDescriptor::VectorRegister());
__ RecordComment("]");
} else {
__ mov(vector, Operand(esp, 1 * kPointerSize));
}
__ mov(slot, Operand(esp, 2 * kPointerSize));
__ mov(value, Operand(esp, 3 * kPointerSize));
}
__ push(value);
Register scratch = value;

View File

@ -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,16 +438,28 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
Handle<Map> transition, Handle<Name> name) {
Label miss;
bool vector_and_slot_on_stack =
StoreTransitionDescriptor::PassVectorAndSlotOnStack();
if (vector_and_slot_on_stack) {
// Speculatively prepare for calling StoreTransitionStub by converting
// StoreWithVectorDescriptor arguments to StoreTransitionDescriptor
// arguments.
PopReturnAddress(this->name());
PushVectorAndSlot();
PushReturnAddress(this->name());
} else {
// 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(StoreWithVectorDescriptor::kStackArgumentsCount ==
StoreTransitionDescriptor::kStackArgumentsCount);
STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 0 ||
StoreWithVectorDescriptor::kStackArgumentsCount == 3);
STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount -
StoreWithVectorDescriptor::kValue ==
StoreTransitionDescriptor::kParameterCount -
StoreTransitionDescriptor::kValue);
STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount -
StoreWithVectorDescriptor::kSlot ==
StoreTransitionDescriptor::kParameterCount -
StoreTransitionDescriptor::kSlot);
STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount -
StoreWithVectorDescriptor::kVector ==
StoreTransitionDescriptor::kParameterCount -
StoreTransitionDescriptor::kVector);
bool need_save_restore = IC::ShouldPushPopSlotAndVector(kind());
if (need_save_restore) {
PushVectorAndSlot();
}
@ -487,7 +499,7 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
DCHECK(descriptors->GetValue(descriptor)->IsJSFunction());
GenerateRestoreMap(transition, map_reg, scratch1(), &miss);
GenerateConstantCheck(map_reg, descriptor, value(), scratch1(), &miss);
if (!vector_and_slot_on_stack) {
if (need_save_restore) {
PopVectorAndSlot();
}
GenerateRestoreName(name);
@ -504,7 +516,7 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
? StoreTransitionStub::ExtendStorageAndStoreMapAndValue
: StoreTransitionStub::StoreMapAndValue;
GenerateRestoreMap(transition, map_reg, scratch1(), &miss);
if (!vector_and_slot_on_stack) {
if (need_save_restore) {
PopVectorAndSlot();
}
GenerateRestoreName(name);
@ -515,12 +527,7 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
}
__ bind(&miss);
if (vector_and_slot_on_stack) {
// Prepare for calling miss builtin with StoreWithVectorDescriptor.
PopReturnAddress(this->name());
PopVectorAndSlot();
PushReturnAddress(this->name());
} else {
if (need_save_restore) {
PopVectorAndSlot();
}
GenerateRestoreName(name);
@ -542,7 +549,7 @@ 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 (need_save_restore) PushVectorAndSlot();
GenerateFieldTypeChecks(field_type, value(), &miss);
if (need_save_restore) PopVectorAndSlot();

View File

@ -165,6 +165,13 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
DCHECK(!accessor_holder.is(scratch));
// Copy return value.
__ pop(scratch);
if (is_store) {
// Discard stack arguments.
__ add(esp, Immediate(StoreWithVectorDescriptor::kStackArgumentsCount *
kPointerSize));
}
// receiver
__ push(receiver);
// Write the arguments to stack frame.
@ -305,7 +312,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);
}
}
@ -508,7 +522,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();
}
@ -523,7 +537,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);
}
@ -624,6 +638,9 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Register holder_reg = Frontend(name);
__ 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,
@ -655,7 +672,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);
@ -677,7 +694,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);

View File

@ -15,14 +15,17 @@ 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()));
STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3);
// Current stack layout:
// - esp[12] -- value
// - esp[8] -- slot
// - esp[4] -- vector
// - esp[0] -- return address
__ mov(Operand(esp, 12), StoreDescriptor::ReceiverRegister());
__ mov(Operand(esp, 8), StoreDescriptor::NameRegister());
__ mov(Operand(esp, 4), StoreDescriptor::ValueRegister());
__ pop(ebx);
__ push(StoreDescriptor::ReceiverRegister());
__ push(StoreDescriptor::NameRegister());
__ push(StoreDescriptor::ValueRegister());
__ push(Immediate(Smi::FromInt(language_mode)));
__ push(ebx); // return address

View File

@ -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));
@ -705,18 +705,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();
Register receiver = StoreWithVectorDescriptor::ReceiverRegister();
Register name = StoreWithVectorDescriptor::NameRegister();
__ xchg(value, Operand(esp, 0));
__ push(slot);
__ push(vector);
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); // Contains the return address.
__ push(return_address);
}
@ -751,7 +754,7 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) {
__ Drop(3);
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->ic_store_normal_hit(), 1);
__ ret(0);
__ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize);
__ bind(&restore_miss);
__ pop(slot);

View File

@ -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()) {

View File

@ -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:

View File

@ -165,6 +165,13 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
DCHECK(!accessor_holder.is(scratch));
// Copy return value.
__ pop(scratch);
if (is_store) {
// Discard stack arguments.
__ add(esp, Immediate(StoreWithVectorDescriptor::kStackArgumentsCount *
kPointerSize));
}
// receiver
__ push(receiver);
// Write the arguments to stack frame.
@ -305,7 +312,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);
}
}
@ -508,7 +522,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();
}
@ -523,7 +537,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);
}
@ -624,6 +638,9 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Register holder_reg = Frontend(name);
__ 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,
@ -655,7 +672,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);
@ -677,7 +694,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);

View File

@ -15,14 +15,17 @@ 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()));
STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3);
// Current stack layout:
// - esp[12] -- value
// - esp[8] -- slot
// - esp[4] -- vector
// - esp[0] -- return address
__ mov(Operand(esp, 12), StoreDescriptor::ReceiverRegister());
__ mov(Operand(esp, 8), StoreDescriptor::NameRegister());
__ mov(Operand(esp, 4), StoreDescriptor::ValueRegister());
__ pop(ebx);
__ push(StoreDescriptor::ReceiverRegister());
__ push(StoreDescriptor::NameRegister());
__ push(StoreDescriptor::ValueRegister());
__ push(Immediate(Smi::FromInt(language_mode)));
__ push(ebx); // return address

View File

@ -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));
@ -705,18 +705,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();
Register receiver = StoreWithVectorDescriptor::ReceiverRegister();
Register name = StoreWithVectorDescriptor::NameRegister();
__ xchg(value, Operand(esp, 0));
__ push(slot);
__ push(vector);
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); // Contains the return address.
__ push(return_address);
}
@ -751,7 +754,7 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) {
__ Drop(3);
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->ic_store_normal_hit(), 1);
__ ret(0);
__ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize);
__ bind(&restore_miss);
__ pop(slot);

View File

@ -134,15 +134,9 @@ void StoreDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
SlotRegister()};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
bool StoreTransitionDescriptor::PassVectorAndSlotOnStack() {
#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
return true;
#else
return false;
#endif
int len = arraysize(registers) - kStackArgumentsCount;
data->InitializePlatformSpecific(len, registers);
}
void StoreTransitionDescriptor::InitializePlatformSpecific(
@ -151,11 +145,7 @@ void StoreTransitionDescriptor::InitializePlatformSpecific(
ReceiverRegister(), NameRegister(), MapRegister(),
ValueRegister(), SlotRegister(), VectorRegister(),
};
int len = arraysize(registers);
if (PassVectorAndSlotOnStack()) {
// Pass slot and vector on the stack.
len -= 2;
}
int len = arraysize(registers) - kStackArgumentsCount;
data->InitializePlatformSpecific(len, registers);
}
@ -243,7 +233,8 @@ void StoreWithVectorDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
SlotRegister(), VectorRegister()};
data->InitializePlatformSpecific(arraysize(registers), registers);
int len = arraysize(registers) - kStackArgumentsCount;
data->InitializePlatformSpecific(len, registers);
}
void BinaryOpWithVectorDescriptor::InitializePlatformIndependent(

View File

@ -324,6 +324,15 @@ class StoreDescriptor : public CallInterfaceDescriptor {
static const Register NameRegister();
static const Register ValueRegister();
static const Register SlotRegister();
#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
static const bool kPassLastArgsOnStack = true;
#else
static const bool kPassLastArgsOnStack = false;
#endif
// Pass value and slot through the stack.
static const int kStackArgumentsCount = kPassLastArgsOnStack ? 2 : 0;
};
class StoreTransitionDescriptor : public StoreDescriptor {
@ -336,7 +345,8 @@ class StoreTransitionDescriptor : public StoreDescriptor {
static const Register SlotRegister();
static const Register VectorRegister();
static bool PassVectorAndSlotOnStack();
// Pass value, slot and vector through the stack.
static const int kStackArgumentsCount = kPassLastArgsOnStack ? 3 : 0;
};
class StoreWithVectorDescriptor : public StoreDescriptor {
@ -346,6 +356,9 @@ class StoreWithVectorDescriptor : public StoreDescriptor {
StoreDescriptor)
static const Register VectorRegister();
// Pass value, slot and vector through the stack.
static const int kStackArgumentsCount = kPassLastArgsOnStack ? 3 : 0;
};
class LoadWithVectorDescriptor : public LoadDescriptor {

View File

@ -3483,6 +3483,28 @@ void StoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
Register slot = StoreWithVectorDescriptor::SlotRegister(); // edi
Label miss;
if (StoreWithVectorDescriptor::kPassLastArgsOnStack) {
// Current stack layout:
// - esp[8] -- value
// - esp[4] -- slot
// - esp[0] -- return address
STATIC_ASSERT(StoreDescriptor::kStackArgumentsCount == 2);
STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3);
if (in_frame) {
__ RecordComment("[ StoreDescriptor -> StoreWithVectorDescriptor");
// If the vector is not on the stack, then insert the vector beneath
// return address in order to prepare for calling handler with
// StoreWithVector calling convention.
__ push(Operand(esp, 0));
__ mov(Operand(esp, 4), StoreWithVectorDescriptor::VectorRegister());
__ RecordComment("]");
} else {
__ mov(vector, Operand(esp, 1 * kPointerSize));
}
__ mov(slot, Operand(esp, 2 * kPointerSize));
__ mov(value, Operand(esp, 3 * kPointerSize));
}
__ push(value);
Register scratch = value;
@ -3624,12 +3646,23 @@ static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm,
__ pop(vector);
__ pop(receiver);
__ pop(value);
{
// Put vector and slot beneath return address.
__ push(vector);
__ push(Operand(esp, 1 * kPointerSize)); // push return address
__ mov(Operand(esp, 2 * kPointerSize), slot);
}
// Ensure that the transition handler we are going to call has the same
// number of stack arguments which means that we don't have to adapt them
// before the call.
STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3);
STATIC_ASSERT(StoreTransitionDescriptor::kStackArgumentsCount == 3);
STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount -
StoreWithVectorDescriptor::kValue ==
StoreTransitionDescriptor::kParameterCount -
StoreTransitionDescriptor::kValue);
STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount -
StoreWithVectorDescriptor::kSlot ==
StoreTransitionDescriptor::kParameterCount -
StoreTransitionDescriptor::kSlot);
STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount -
StoreWithVectorDescriptor::kVector ==
StoreTransitionDescriptor::kParameterCount -
StoreTransitionDescriptor::kVector);
__ jmp(Operand::StaticVariable(virtual_register));
__ bind(&prepare_next);
@ -3657,6 +3690,28 @@ void KeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
Register slot = StoreWithVectorDescriptor::SlotRegister(); // edi
Label miss;
if (StoreWithVectorDescriptor::kPassLastArgsOnStack) {
// Current stack layout:
// - esp[8] -- value
// - esp[4] -- slot
// - esp[0] -- return address
STATIC_ASSERT(StoreDescriptor::kStackArgumentsCount == 2);
STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3);
if (in_frame) {
__ RecordComment("[ StoreDescriptor -> StoreWithVectorDescriptor");
// If the vector is not on the stack, then insert the vector beneath
// return address in order to prepare for calling handler with
// StoreWithVector calling convention.
__ push(Operand(esp, 0));
__ mov(Operand(esp, 4), StoreWithVectorDescriptor::VectorRegister());
__ RecordComment("]");
} else {
__ mov(vector, Operand(esp, 1 * kPointerSize));
}
__ mov(slot, Operand(esp, 2 * kPointerSize));
__ mov(value, Operand(esp, 3 * kPointerSize));
}
__ push(value);
Register scratch = value;