Commit 6b69d536 authored by chunyang.dai's avatar chunyang.dai Committed by Commit bot

X87: Reland Vector ICs: platform support for vector-based stores.

port 40fbed06 (r30581)

original commit message:

    The last changes for vector store functionality, they are in 3 areas:

    1) The new vector [keyed] store code stubs - implementation.
    2) IC and handler compiler adjustments
    3) Odds and ends. A change in ast.cc, a test update, a small Oracle fix.

BUG=

Review URL: https://codereview.chromium.org/1311413007

Cr-Commit-Position: refs/heads/master@{#30612}
parent 0fce748d
......@@ -30,7 +30,8 @@ Register* PropertyAccessCompiler::store_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3.
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
DCHECK(ebx.is(StoreTransitionDescriptor::MapRegister()));
DCHECK(FLAG_vector_stores ||
ebx.is(StoreTransitionDescriptor::MapRegister()));
static Register registers[] = {receiver, name, ebx, edi, no_reg};
return registers;
}
......
......@@ -304,13 +304,24 @@ static void StoreIC_PushArgs(MacroAssembler* masm) {
Register name = StoreDescriptor::NameRegister();
Register value = StoreDescriptor::ValueRegister();
DCHECK(!ebx.is(receiver) && !ebx.is(name) && !ebx.is(value));
__ pop(ebx);
__ push(receiver);
__ push(name);
__ push(value);
__ push(ebx);
if (FLAG_vector_stores) {
Register slot = VectorStoreICDescriptor::SlotRegister();
Register vector = VectorStoreICDescriptor::VectorRegister();
__ xchg(receiver, Operand(esp, 0));
__ push(name);
__ push(value);
__ push(slot);
__ push(vector);
__ push(receiver); // which contains the return address.
} else {
DCHECK(!ebx.is(receiver) && !ebx.is(name) && !ebx.is(value));
__ pop(ebx);
__ push(receiver);
__ push(name);
__ push(value);
__ push(ebx);
}
}
......@@ -319,7 +330,7 @@ void NamedStoreHandlerCompiler::GenerateSlow(MacroAssembler* masm) {
StoreIC_PushArgs(masm);
// Do tail-call to runtime routine.
__ TailCallRuntime(Runtime::kStoreIC_Slow, 3, 1);
__ TailCallRuntime(Runtime::kStoreIC_Slow, FLAG_vector_stores ? 5 : 3, 1);
}
......@@ -328,7 +339,8 @@ void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) {
StoreIC_PushArgs(masm);
// Do tail-call to runtime routine.
__ TailCallRuntime(Runtime::kKeyedStoreIC_Slow, 3, 1);
__ TailCallRuntime(Runtime::kKeyedStoreIC_Slow, FLAG_vector_stores ? 5 : 3,
1);
}
......@@ -352,10 +364,16 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
void NamedStoreHandlerCompiler::GeneratePushMap(Register map_reg,
Register scratch) {
// Get the return address, push the argument and then continue.
__ pop(scratch);
// current after GeneratePushMap
// -------------------------------------------------
// ret addr slot
// vector vector
// sp -> slot map
// sp -> ret addr
//
__ xchg(map_reg, Operand(esp, 0));
__ xchg(map_reg, Operand(esp, 2 * kPointerSize));
__ push(map_reg);
__ push(scratch);
}
......@@ -575,6 +593,7 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
Label success;
__ jmp(&success);
GenerateRestoreName(miss, name);
if (IC::ICUseVector(kind())) PopVectorAndSlot();
TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
}
......
......@@ -112,7 +112,10 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
Label next_map;
__ j(not_equal, &next_map, Label::kNear);
Handle<WeakCell> cell = Map::WeakCellForMap(transitioned_maps->at(i));
__ LoadWeakValue(transition_map(), cell, &miss);
Register transition_map = scratch1();
DCHECK(!FLAG_vector_stores &&
transition_map.is(StoreTransitionDescriptor::MapRegister()));
__ LoadWeakValue(transition_map, cell, &miss);
__ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
__ bind(&next_map);
}
......
......@@ -577,7 +577,7 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm,
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
Code::ComputeHandlerFlags(Code::STORE_IC));
masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
receiver, key, ebx, no_reg);
receiver, key, edi, no_reg);
if (FLAG_vector_stores) {
__ pop(VectorStoreICDescriptor::VectorRegister());
......@@ -734,6 +734,12 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm,
void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
if (FLAG_vector_stores) {
// This shouldn't be called.
__ int3();
return;
}
// Return address is on the stack.
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
Code::ComputeHandlerFlags(Code::STORE_IC));
......@@ -787,22 +793,32 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) {
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
Register value = StoreDescriptor::ValueRegister();
Register dictionary = ebx;
__ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset));
Register vector = VectorStoreICDescriptor::VectorRegister();
Register slot = VectorStoreICDescriptor::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.
__ push(receiver);
if (FLAG_vector_stores) {
__ push(vector);
__ push(slot);
}
Register dictionary = ebx;
__ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset));
GenerateDictionaryStore(masm, &restore_miss, dictionary, name, value,
receiver, edi);
__ Drop(1);
__ Drop(FLAG_vector_stores ? 3 : 1);
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->store_normal_hit(), 1);
__ ret(0);
__ bind(&restore_miss);
if (FLAG_vector_stores) {
__ pop(slot);
__ pop(vector);
}
__ pop(receiver);
__ IncrementCounter(counters->store_normal_miss(), 1);
GenerateMiss(masm);
......
......@@ -25,6 +25,9 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
ExternalReference map_offset(isolate->stub_cache()->map_reference(table));
Label miss;
bool is_vector_store =
IC::ICUseVector(ic_kind) &&
(ic_kind == Code::STORE_IC || ic_kind == Code::KEYED_STORE_IC);
// Multiply by 3 because there are 3 fields per entry (name, code, map).
__ lea(offset, Operand(offset, offset, times_2, 0));
......@@ -56,19 +59,28 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
}
#endif
if (IC::ICUseVector(ic_kind)) {
// The vector and slot were pushed onto the stack before starting the
// probe, and need to be dropped before calling the handler.
// 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 = VectorStoreICDescriptor::VectorRegister();
DCHECK(extra.is(VectorStoreICDescriptor::SlotRegister()));
__ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ pop(vector);
__ xchg(extra, Operand(esp, 0));
// Jump to the first instruction in the code stub.
__ ret(0);
} else {
__ pop(LoadWithVectorDescriptor::VectorRegister());
__ pop(LoadDescriptor::SlotRegister());
__ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ jmp(extra);
}
// Jump to the first instruction in the code stub.
__ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ jmp(extra);
__ bind(&miss);
} else {
DCHECK(ic_kind == Code::STORE_IC || ic_kind == Code::KEYED_STORE_IC);
// Save the offset on the stack.
__ push(offset);
......@@ -105,21 +117,21 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
__ pop(offset);
__ mov(offset, Operand::StaticArray(offset, times_1, value_offset));
if (IC::ICUseVector(ic_kind)) {
// 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 = LoadWithVectorDescriptor::VectorRegister();
Register slot = LoadDescriptor::SlotRegister();
DCHECK(!offset.is(vector) && !offset.is(slot));
Register vector = VectorStoreICDescriptor::VectorRegister();
DCHECK(offset.is(VectorStoreICDescriptor::SlotRegister()));
__ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ pop(vector);
__ pop(slot);
__ xchg(offset, Operand(esp, 0));
__ ret(0);
} else {
__ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ jmp(offset);
}
// Jump to the first instruction in the code stub.
__ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ jmp(offset);
// Pop at miss.
__ bind(&miss);
__ pop(offset);
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment