X87: Reland Vector ICs: platform support for vector-based stores.
port 40fbed0609
(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}
This commit is contained in:
parent
0fce748dc6
commit
6b69d5365d
@ -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));
|
||||
if (FLAG_vector_stores) {
|
||||
Register slot = VectorStoreICDescriptor::SlotRegister();
|
||||
Register vector = VectorStoreICDescriptor::VectorRegister();
|
||||
|
||||
__ pop(ebx);
|
||||
__ push(receiver);
|
||||
__ push(name);
|
||||
__ push(value);
|
||||
__ push(ebx);
|
||||
__ 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);
|
||||
|
@ -4269,11 +4269,173 @@ void VectorStoreICStub::GenerateForTrampoline(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
// value is on the stack already.
|
||||
static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver,
|
||||
Register key, Register vector,
|
||||
Register slot, Register feedback,
|
||||
Label* miss) {
|
||||
// feedback initially contains the feedback array
|
||||
Label next, next_loop, prepare_next;
|
||||
Label load_smi_map, compare_map;
|
||||
Label start_polymorphic;
|
||||
|
||||
__ push(receiver);
|
||||
__ push(vector);
|
||||
|
||||
Register receiver_map = receiver;
|
||||
Register cached_map = vector;
|
||||
|
||||
// Receiver might not be a heap object.
|
||||
__ JumpIfSmi(receiver, &load_smi_map);
|
||||
__ mov(receiver_map, FieldOperand(receiver, 0));
|
||||
__ bind(&compare_map);
|
||||
__ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0)));
|
||||
|
||||
// A named keyed store might have a 2 element array, all other cases can count
|
||||
// on an array with at least 2 {map, handler} pairs, so they can go right
|
||||
// into polymorphic array handling.
|
||||
__ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset));
|
||||
__ j(not_equal, &start_polymorphic);
|
||||
|
||||
// found, now call handler.
|
||||
Register handler = feedback;
|
||||
DCHECK(handler.is(VectorStoreICDescriptor::ValueRegister()));
|
||||
__ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1)));
|
||||
__ pop(vector);
|
||||
__ pop(receiver);
|
||||
__ lea(handler, FieldOperand(handler, Code::kHeaderSize));
|
||||
__ xchg(handler, Operand(esp, 0));
|
||||
__ ret(0);
|
||||
|
||||
// Polymorphic, we have to loop from 2 to N
|
||||
|
||||
// TODO(mvstanton): I think there is a bug here, we are assuming the
|
||||
// array has more than one map/handler pair, but we call this function in the
|
||||
// keyed store with a string key case, where it might be just an array of two
|
||||
// elements.
|
||||
|
||||
__ bind(&start_polymorphic);
|
||||
__ push(key);
|
||||
Register counter = key;
|
||||
__ mov(counter, Immediate(Smi::FromInt(2)));
|
||||
__ bind(&next_loop);
|
||||
__ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size,
|
||||
FixedArray::kHeaderSize));
|
||||
__ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset));
|
||||
__ j(not_equal, &prepare_next);
|
||||
__ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size,
|
||||
FixedArray::kHeaderSize + kPointerSize));
|
||||
__ pop(key);
|
||||
__ pop(vector);
|
||||
__ pop(receiver);
|
||||
__ lea(handler, FieldOperand(handler, Code::kHeaderSize));
|
||||
__ xchg(handler, Operand(esp, 0));
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&prepare_next);
|
||||
__ add(counter, Immediate(Smi::FromInt(2)));
|
||||
__ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset));
|
||||
__ j(less, &next_loop);
|
||||
|
||||
// We exhausted our array of map handler pairs.
|
||||
__ pop(key);
|
||||
__ pop(vector);
|
||||
__ pop(receiver);
|
||||
__ jmp(miss);
|
||||
|
||||
__ bind(&load_smi_map);
|
||||
__ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex);
|
||||
__ jmp(&compare_map);
|
||||
}
|
||||
|
||||
|
||||
static void HandleMonomorphicStoreCase(MacroAssembler* masm, Register receiver,
|
||||
Register key, Register vector,
|
||||
Register slot, Register weak_cell,
|
||||
Label* miss) {
|
||||
// The store ic value is on the stack.
|
||||
DCHECK(weak_cell.is(VectorStoreICDescriptor::ValueRegister()));
|
||||
|
||||
// feedback initially contains the feedback array
|
||||
Label compare_smi_map;
|
||||
|
||||
// Move the weak map into the weak_cell register.
|
||||
Register ic_map = weak_cell;
|
||||
__ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset));
|
||||
|
||||
// Receiver might not be a heap object.
|
||||
__ JumpIfSmi(receiver, &compare_smi_map);
|
||||
__ cmp(ic_map, FieldOperand(receiver, 0));
|
||||
__ j(not_equal, miss);
|
||||
__ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size,
|
||||
FixedArray::kHeaderSize + kPointerSize));
|
||||
__ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize));
|
||||
// Put the store ic value back in it's register.
|
||||
__ xchg(weak_cell, Operand(esp, 0));
|
||||
// "return" to the handler.
|
||||
__ ret(0);
|
||||
|
||||
// In microbenchmarks, it made sense to unroll this code so that the call to
|
||||
// the handler is duplicated for a HeapObject receiver and a Smi receiver.
|
||||
__ bind(&compare_smi_map);
|
||||
__ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex);
|
||||
__ j(not_equal, miss);
|
||||
__ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size,
|
||||
FixedArray::kHeaderSize + kPointerSize));
|
||||
__ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize));
|
||||
// Put the store ic value back in it's register.
|
||||
__ xchg(weak_cell, Operand(esp, 0));
|
||||
// "return" to the handler.
|
||||
__ ret(0);
|
||||
}
|
||||
|
||||
|
||||
void VectorStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
|
||||
Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // edx
|
||||
Register key = VectorStoreICDescriptor::NameRegister(); // ecx
|
||||
Register value = VectorStoreICDescriptor::ValueRegister(); // eax
|
||||
Register vector = VectorStoreICDescriptor::VectorRegister(); // ebx
|
||||
Register slot = VectorStoreICDescriptor::SlotRegister(); // edi
|
||||
Label miss;
|
||||
|
||||
// TODO(mvstanton): Implement.
|
||||
__ push(value);
|
||||
|
||||
Register scratch = value;
|
||||
__ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size,
|
||||
FixedArray::kHeaderSize));
|
||||
|
||||
// Is it a weak cell?
|
||||
Label try_array;
|
||||
Label not_array, smi_key, key_okay;
|
||||
__ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex);
|
||||
__ j(not_equal, &try_array);
|
||||
HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss);
|
||||
|
||||
// Is it a fixed array?
|
||||
__ bind(&try_array);
|
||||
__ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex);
|
||||
__ j(not_equal, ¬_array);
|
||||
HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss);
|
||||
|
||||
__ bind(¬_array);
|
||||
__ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex);
|
||||
__ j(not_equal, &miss);
|
||||
|
||||
__ pop(value);
|
||||
__ push(slot);
|
||||
__ push(vector);
|
||||
Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
|
||||
Code::ComputeHandlerFlags(Code::STORE_IC));
|
||||
masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, code_flags,
|
||||
receiver, key, slot, no_reg);
|
||||
__ pop(vector);
|
||||
__ pop(slot);
|
||||
Label no_pop_miss;
|
||||
__ jmp(&no_pop_miss);
|
||||
|
||||
__ bind(&miss);
|
||||
__ pop(value);
|
||||
__ bind(&no_pop_miss);
|
||||
StoreIC::GenerateMiss(masm);
|
||||
}
|
||||
|
||||
@ -4288,11 +4450,147 @@ void VectorKeyedStoreICStub::GenerateForTrampoline(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm,
|
||||
Register receiver, Register key,
|
||||
Register vector, Register slot,
|
||||
Register feedback, Label* miss) {
|
||||
// feedback initially contains the feedback array
|
||||
Label next, next_loop, prepare_next;
|
||||
Label load_smi_map, compare_map;
|
||||
Label transition_call;
|
||||
Label pop_and_miss;
|
||||
|
||||
__ push(receiver);
|
||||
__ push(vector);
|
||||
|
||||
Register receiver_map = receiver;
|
||||
Register cached_map = vector;
|
||||
|
||||
// Receiver might not be a heap object.
|
||||
__ JumpIfSmi(receiver, &load_smi_map);
|
||||
__ mov(receiver_map, FieldOperand(receiver, 0));
|
||||
__ bind(&compare_map);
|
||||
|
||||
// Polymorphic, we have to loop from 0 to N - 1
|
||||
__ push(key);
|
||||
// On the stack we have:
|
||||
// key (esp)
|
||||
// vector
|
||||
// receiver
|
||||
// value
|
||||
Register counter = key;
|
||||
__ mov(counter, Immediate(Smi::FromInt(0)));
|
||||
__ bind(&next_loop);
|
||||
__ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size,
|
||||
FixedArray::kHeaderSize));
|
||||
__ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset));
|
||||
__ j(not_equal, &prepare_next);
|
||||
__ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size,
|
||||
FixedArray::kHeaderSize + kPointerSize));
|
||||
__ CompareRoot(cached_map, Heap::kUndefinedValueRootIndex);
|
||||
__ j(not_equal, &transition_call);
|
||||
__ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size,
|
||||
FixedArray::kHeaderSize + 2 * kPointerSize));
|
||||
__ pop(key);
|
||||
__ pop(vector);
|
||||
__ pop(receiver);
|
||||
__ lea(feedback, FieldOperand(feedback, Code::kHeaderSize));
|
||||
__ xchg(feedback, Operand(esp, 0));
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&transition_call);
|
||||
// Oh holy hell this will be tough.
|
||||
// The map goes in vector register.
|
||||
__ mov(receiver, FieldOperand(cached_map, WeakCell::kValueOffset));
|
||||
// The weak cell may have been cleared.
|
||||
__ JumpIfSmi(receiver, &pop_and_miss);
|
||||
// slot goes on the stack, and holds return address.
|
||||
__ xchg(slot, Operand(esp, 4 * kPointerSize));
|
||||
// Get the handler in value.
|
||||
__ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size,
|
||||
FixedArray::kHeaderSize + 2 * kPointerSize));
|
||||
__ lea(feedback, FieldOperand(feedback, Code::kHeaderSize));
|
||||
// Pop key into place.
|
||||
__ pop(key);
|
||||
// Put the return address on top of stack, vector goes in slot.
|
||||
__ xchg(slot, Operand(esp, 0));
|
||||
// put the map on the stack, receiver holds receiver.
|
||||
__ xchg(receiver, Operand(esp, 1 * kPointerSize));
|
||||
// put the vector on the stack, slot holds value.
|
||||
__ xchg(slot, Operand(esp, 2 * kPointerSize));
|
||||
// feedback (value) = value, slot = handler.
|
||||
__ xchg(feedback, slot);
|
||||
__ jmp(slot);
|
||||
|
||||
__ bind(&prepare_next);
|
||||
__ add(counter, Immediate(Smi::FromInt(3)));
|
||||
__ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset));
|
||||
__ j(less, &next_loop);
|
||||
|
||||
// We exhausted our array of map handler pairs.
|
||||
__ bind(&pop_and_miss);
|
||||
__ pop(key);
|
||||
__ pop(vector);
|
||||
__ pop(receiver);
|
||||
__ jmp(miss);
|
||||
|
||||
__ bind(&load_smi_map);
|
||||
__ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex);
|
||||
__ jmp(&compare_map);
|
||||
}
|
||||
|
||||
|
||||
void VectorKeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
|
||||
Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // edx
|
||||
Register key = VectorStoreICDescriptor::NameRegister(); // ecx
|
||||
Register value = VectorStoreICDescriptor::ValueRegister(); // eax
|
||||
Register vector = VectorStoreICDescriptor::VectorRegister(); // ebx
|
||||
Register slot = VectorStoreICDescriptor::SlotRegister(); // edi
|
||||
Label miss;
|
||||
|
||||
// TODO(mvstanton): Implement.
|
||||
__ push(value);
|
||||
|
||||
Register scratch = value;
|
||||
__ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size,
|
||||
FixedArray::kHeaderSize));
|
||||
|
||||
// Is it a weak cell?
|
||||
Label try_array;
|
||||
Label not_array, smi_key, key_okay;
|
||||
__ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex);
|
||||
__ j(not_equal, &try_array);
|
||||
HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss);
|
||||
|
||||
// Is it a fixed array?
|
||||
__ bind(&try_array);
|
||||
__ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex);
|
||||
__ j(not_equal, ¬_array);
|
||||
HandlePolymorphicKeyedStoreCase(masm, receiver, key, vector, slot, scratch,
|
||||
&miss);
|
||||
|
||||
__ bind(¬_array);
|
||||
Label try_poly_name;
|
||||
__ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex);
|
||||
__ j(not_equal, &try_poly_name);
|
||||
|
||||
__ pop(value);
|
||||
|
||||
Handle<Code> megamorphic_stub =
|
||||
KeyedStoreIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState());
|
||||
__ jmp(megamorphic_stub, RelocInfo::CODE_TARGET);
|
||||
|
||||
__ bind(&try_poly_name);
|
||||
// We might have a name in feedback, and a fixed array in the next slot.
|
||||
__ cmp(key, scratch);
|
||||
__ j(not_equal, &miss);
|
||||
// If the name comparison succeeded, we know we have a fixed array with
|
||||
// at least one map/handler pair.
|
||||
__ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size,
|
||||
FixedArray::kHeaderSize + kPointerSize));
|
||||
HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss);
|
||||
|
||||
__ bind(&miss);
|
||||
__ pop(value);
|
||||
KeyedStoreIC::GenerateMiss(masm);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user