Load/Store stub compilation refactoring.

Review URL: https://chromiumcodereview.appspot.com/12426008

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13954 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
verwaest@chromium.org 2013-03-15 12:07:35 +00:00
parent 53310ac152
commit 88b8715f95
9 changed files with 165 additions and 396 deletions

View File

@ -2574,26 +2574,21 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : receiver
// -- r2 : name
// -- lr : return address
// -----------------------------------
Label miss;
// Check that the maps haven't changed.
__ JumpIfSmi(r1, &miss);
CheckPrototypes(receiver, r1, holder, r3, r4, r5, name, &miss);
__ JumpIfSmi(receiver(), &miss);
CheckPrototypes(object, receiver(), holder,
scratch1(), scratch2(), scratch3(), name, &miss);
// Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
__ push(r1); // receiver
__ push(receiver()); // receiver
__ mov(ip, Operand(callback)); // callback info
__ Push(ip, r2, r0);
__ Push(ip, this->name(), value());
// Do tail-call to the runtime system.
ExternalReference store_callback_property =
@ -2655,61 +2650,28 @@ void StoreStubCompiler::GenerateStoreViaSetter(
#define __ ACCESS_MASM(masm())
Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<JSFunction> setter) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : receiver
// -- r2 : name
// -- lr : return address
// -----------------------------------
Label miss;
// Check that the maps haven't changed.
__ JumpIfSmi(r1, &miss);
CheckPrototypes(receiver, r1, holder, r3, r4, r5, name, &miss);
GenerateStoreViaSetter(masm(), setter);
__ bind(&miss);
TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
return GetICCode(kind(), Code::CALLBACKS, name);
}
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> receiver,
Handle<JSObject> object,
Handle<Name> name) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : receiver
// -- r2 : name
// -- lr : return address
// -----------------------------------
Label miss;
// Check that the map of the object hasn't changed.
__ CheckMap(r1, r3, Handle<Map>(receiver->map()), &miss,
__ CheckMap(receiver(), scratch1(), Handle<Map>(object->map()), &miss,
DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed.
if (receiver->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(r1, r3, &miss);
if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(receiver(), scratch1(), &miss);
}
// Stub is never generated for non-global objects that require access
// checks.
ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
__ Push(r1, r2, r0); // Receiver, name, value.
__ Push(receiver(), this->name(), value());
__ mov(r0, Operand(Smi::FromInt(strict_mode())));
__ push(r0); // strict mode
__ mov(scratch1(), Operand(Smi::FromInt(strict_mode())));
__ push(scratch1()); // strict mode
// Do tail-call to the runtime system.
ExternalReference store_ic_property =
@ -2730,40 +2692,38 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> cell,
Handle<Name> name) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : receiver
// -- r2 : name
// -- lr : return address
// -----------------------------------
Label miss;
// Check that the map of the global has not changed.
__ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
__ cmp(r3, Operand(Handle<Map>(object->map())));
__ ldr(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
__ cmp(scratch1(), Operand(Handle<Map>(object->map())));
__ b(ne, &miss);
// Check that the value in the cell is not the hole. If it is, this
// cell could have been deleted and reintroducing the global needs
// to update the property details in the property dictionary of the
// global object. We bail out to the runtime system to do that.
__ mov(r4, Operand(cell));
__ LoadRoot(r5, Heap::kTheHoleValueRootIndex);
__ ldr(r6, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset));
__ cmp(r5, r6);
__ mov(scratch1(), Operand(cell));
__ LoadRoot(scratch2(), Heap::kTheHoleValueRootIndex);
__ ldr(scratch3(),
FieldMemOperand(scratch1(), JSGlobalPropertyCell::kValueOffset));
__ cmp(scratch3(), scratch2());
__ b(eq, &miss);
// Store the value in the cell.
__ str(r0, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset));
__ str(value(),
FieldMemOperand(scratch1(), JSGlobalPropertyCell::kValueOffset));
// Cells are always rescanned, so no write barrier here.
Counters* counters = masm()->isolate()->counters();
__ IncrementCounter(counters->named_store_global_inline(), 1, r4, r3);
__ IncrementCounter(
counters->named_store_global_inline(), 1, scratch1(), scratch2());
__ Ret();
// Handle store cache miss.
__ bind(&miss);
__ IncrementCounter(counters->named_store_global_inline_miss(), 1, r4, r3);
__ IncrementCounter(
counters->named_store_global_inline_miss(), 1, scratch1(), scratch2());
TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
@ -2909,33 +2869,6 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
}
Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
Handle<Map> receiver_map) {
// ----------- S t a t e -------------
// -- lr : return address
// -- r0 : key
// -- r1 : receiver
// -----------------------------------
ElementsKind elements_kind = receiver_map->elements_kind();
if (receiver_map->has_fast_elements() ||
receiver_map->has_external_array_elements()) {
Handle<Code> stub = KeyedLoadFastElementStub(
receiver_map->instance_type() == JS_ARRAY_TYPE,
elements_kind).GetCode(isolate());
__ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK);
} else {
Handle<Code> stub =
KeyedLoadDictionaryElementStub().GetCode(isolate());
__ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK);
}
TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
}
Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
MapHandleList* receiver_maps,
CodeHandleList* handlers,
@ -2969,56 +2902,24 @@ Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
}
Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
Handle<Map> receiver_map) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : key
// -- r2 : receiver
// -- lr : return address
// -- r3 : scratch
// -----------------------------------
ElementsKind elements_kind = receiver_map->elements_kind();
bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
Handle<Code> stub =
KeyedStoreElementStub(is_js_array,
elements_kind,
store_mode_).GetCode(isolate());
__ DispatchMap(r2, r3, receiver_map, stub, DO_SMI_CHECK);
TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
}
Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
MapHandleList* receiver_maps,
CodeHandleList* handler_stubs,
MapHandleList* transitioned_maps) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : key
// -- r2 : receiver
// -- lr : return address
// -- r3 : scratch
// -----------------------------------
Label miss;
__ JumpIfSmi(r2, &miss);
__ JumpIfSmi(receiver(), &miss);
int receiver_count = receiver_maps->length();
__ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
__ ldr(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
for (int i = 0; i < receiver_count; ++i) {
__ mov(ip, Operand(receiver_maps->at(i)));
__ cmp(r3, ip);
__ cmp(scratch1(), ip);
if (transitioned_maps->at(i).is_null()) {
__ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq);
} else {
Label next_map;
__ b(ne, &next_map);
__ mov(r3, Operand(transitioned_maps->at(i)));
__ mov(transition_map(), Operand(transitioned_maps->at(i)));
__ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, al);
__ bind(&next_map);
}

View File

@ -618,6 +618,7 @@ void MacroAssembler::CheckMap(Register obj,
void MacroAssembler::DispatchMap(Register obj,
Register unused,
Handle<Map> map,
Handle<Code> success,
SmiCheckType smi_check_type) {

View File

@ -410,6 +410,7 @@ class MacroAssembler: public Assembler {
// specified target if equal. Skip the smi check if not required (object is
// known to be a heap object)
void DispatchMap(Register obj,
Register unused,
Handle<Map> map,
Handle<Code> success,
SmiCheckType smi_check_type);

View File

@ -2551,31 +2551,25 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : name
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss;
Label miss, miss_restore_name;
// Check that the maps haven't changed, preserving the value register.
__ push(eax);
__ JumpIfSmi(edx, &miss);
CheckPrototypes(receiver, edx, holder, ebx, eax, edi, name, &miss);
__ pop(eax); // restore value
__ JumpIfSmi(receiver(), &miss);
CheckPrototypes(object, receiver(), holder,
scratch1(), this->name(), scratch2(),
name, &miss_restore_name);
// Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
__ pop(ebx); // remove the return address
__ push(edx); // receiver
__ push(Immediate(callback)); // callback info
__ push(ecx); // name
__ push(eax); // value
__ push(ebx); // restore return address
__ pop(scratch1()); // remove the return address
__ push(receiver());
__ Push(callback);
__ Push(name);
__ push(value());
__ push(scratch1()); // restore return address
// Do tail-call to the runtime system.
ExternalReference store_callback_property =
@ -2583,8 +2577,8 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
__ TailCallExternalReference(store_callback_property, 4, 1);
// Handle store cache miss.
GenerateRestoreName(masm(), &miss_restore_name, name);
__ bind(&miss);
__ pop(eax);
TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
@ -2638,66 +2632,30 @@ void StoreStubCompiler::GenerateStoreViaSetter(
#define __ ACCESS_MASM(masm())
Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<JSFunction> setter) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : name
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss;
// Check that the maps haven't changed, preserving the name register.
__ push(ecx);
__ JumpIfSmi(edx, &miss);
CheckPrototypes(receiver, edx, holder, ebx, ecx, edi, name, &miss);
__ pop(ecx);
GenerateStoreViaSetter(masm(), setter);
__ bind(&miss);
__ pop(ecx);
TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
return GetICCode(kind(), Code::CALLBACKS, name);
}
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> receiver,
Handle<JSObject> object,
Handle<Name> name) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : name
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss;
// Check that the map of the object hasn't changed.
__ CheckMap(edx, Handle<Map>(receiver->map()),
__ CheckMap(receiver(), Handle<Map>(object->map()),
&miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed.
if (receiver->IsJSGlobalProxy()) {
if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(edx, ebx, &miss);
}
// Stub never generated for non-global objects that require access
// checks.
ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
__ pop(ebx); // remove the return address
__ push(edx); // receiver
__ push(ecx); // name
__ push(eax); // value
__ pop(scratch1()); // remove the return address
__ push(receiver());
__ push(this->name());
__ push(value());
__ push(Immediate(Smi::FromInt(strict_mode())));
__ push(ebx); // restore return address
__ push(scratch1()); // restore return address
// Do tail-call to the runtime system.
ExternalReference store_ic_property =
@ -2717,22 +2675,17 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> cell,
Handle<Name> name) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : name
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss;
// Check that the map of the global has not changed.
__ cmp(FieldOperand(edx, HeapObject::kMapOffset),
__ cmp(FieldOperand(receiver(), HeapObject::kMapOffset),
Immediate(Handle<Map>(object->map())));
__ j(not_equal, &miss);
// Compute the cell operand to use.
__ mov(ebx, Immediate(cell));
Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset);
__ mov(scratch1(), Immediate(cell));
Operand cell_operand =
FieldOperand(scratch1(), JSGlobalPropertyCell::kValueOffset);
// Check that the value in the cell is not the hole. If it is, this
// cell could have been deleted and reintroducing the global needs
@ -2742,7 +2695,7 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
__ j(equal, &miss);
// Store the value in the cell.
__ mov(cell_operand, eax);
__ mov(cell_operand, value());
// No write barrier here, because cells are always rescanned.
// Return the value (register eax).
@ -2760,52 +2713,21 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
}
Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
Handle<Map> receiver_map) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : key
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
ElementsKind elements_kind = receiver_map->elements_kind();
bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
Handle<Code> stub =
KeyedStoreElementStub(is_jsarray,
elements_kind,
store_mode_).GetCode(isolate());
__ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
}
Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
MapHandleList* receiver_maps,
CodeHandleList* handler_stubs,
MapHandleList* transitioned_maps) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : key
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss;
__ JumpIfSmi(edx, &miss, Label::kNear);
__ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
// ebx: receiver->map().
__ JumpIfSmi(receiver(), &miss, Label::kNear);
__ mov(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset));
for (int i = 0; i < receiver_maps->length(); ++i) {
__ cmp(edi, receiver_maps->at(i));
__ cmp(scratch1(), receiver_maps->at(i));
if (transitioned_maps->at(i).is_null()) {
__ j(equal, handler_stubs->at(i));
} else {
Label next_map;
__ j(not_equal, &next_map, Label::kNear);
__ mov(ebx, Immediate(transitioned_maps->at(i)));
__ mov(transition_map(), Immediate(transitioned_maps->at(i)));
__ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
__ bind(&next_map);
}
@ -2961,34 +2883,6 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
}
Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
Handle<Map> receiver_map) {
// ----------- S t a t e -------------
// -- ecx : key
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
ElementsKind elements_kind = receiver_map->elements_kind();
if (receiver_map->has_fast_elements() ||
receiver_map->has_external_array_elements()) {
Handle<Code> stub = KeyedLoadFastElementStub(
receiver_map->instance_type() == JS_ARRAY_TYPE,
elements_kind).GetCode(isolate());
__ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
} else {
Handle<Code> stub =
KeyedLoadDictionaryElementStub().GetCode(isolate());
__ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
}
TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss);
// Return the generated code.
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
}
Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
MapHandleList* receiver_maps,
CodeHandleList* handlers,

View File

@ -1609,6 +1609,71 @@ Handle<Code> BaseStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
}
Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<JSFunction> setter) {
Label miss, miss_restore_name;
// Check that the maps haven't changed, preserving the name register.
__ JumpIfSmi(receiver(), &miss);
CheckPrototypes(object, receiver(), holder,
this->name(), scratch1(), scratch2(),
name, &miss_restore_name);
GenerateStoreViaSetter(masm(), setter);
GenerateRestoreName(masm(), &miss_restore_name, name);
__ bind(&miss);
TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
return GetICCode(kind(), Code::CALLBACKS, name);
}
Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
Handle<Map> receiver_map) {
ElementsKind elements_kind = receiver_map->elements_kind();
if (receiver_map->has_fast_elements() ||
receiver_map->has_external_array_elements()) {
Handle<Code> stub = KeyedLoadFastElementStub(
receiver_map->instance_type() == JS_ARRAY_TYPE,
elements_kind).GetCode(isolate());
__ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
} else {
Handle<Code> stub =
KeyedLoadDictionaryElementStub().GetCode(isolate());
__ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
}
TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss);
// Return the generated code.
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
}
Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
Handle<Map> receiver_map) {
ElementsKind elements_kind = receiver_map->elements_kind();
bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
Handle<Code> stub =
KeyedStoreElementStub(is_jsarray,
elements_kind,
store_mode_).GetCode(isolate());
__ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss);
// Return the generated code.
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
}
#undef __

View File

@ -895,6 +895,10 @@ class KeyedStoreStubCompiler: public BaseStoreStubCompiler {
}
private:
Register transition_map() {
return registers()[3];
}
static Register* registers();
virtual Code::Kind kind() { return Code::KEYED_STORE_IC; }
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {

View File

@ -2944,6 +2944,7 @@ void MacroAssembler::EnumLength(Register dst, Register map) {
void MacroAssembler::DispatchMap(Register obj,
Register unused,
Handle<Map> map,
Handle<Code> success,
SmiCheckType smi_check_type) {

View File

@ -909,6 +909,7 @@ class MacroAssembler: public Assembler {
// specified target if equal. Skip the smi check if not required (object is
// known to be a heap object)
void DispatchMap(Register obj,
Register unused,
Handle<Map> map,
Handle<Code> success,
SmiCheckType smi_check_type);

View File

@ -2377,29 +2377,24 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss;
// Check that the maps haven't changed.
__ JumpIfSmi(rdx, &miss);
CheckPrototypes(receiver, rdx, holder, rbx, r8, rdi, name, &miss);
__ JumpIfSmi(receiver(), &miss);
CheckPrototypes(object, receiver(), holder,
scratch1(), scratch2(), scratch3(), name, &miss);
// Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
__ pop(rbx); // remove the return address
__ push(rdx); // receiver
__ pop(scratch1()); // remove the return address
__ push(receiver());
__ Push(callback); // callback info
__ push(rcx); // name
__ push(rax); // value
__ push(rbx); // restore return address
__ push(this->name());
__ push(value());
__ push(scratch1()); // restore return address
// Do tail-call to the runtime system.
ExternalReference store_callback_property =
@ -2461,63 +2456,30 @@ void StoreStubCompiler::GenerateStoreViaSetter(
#define __ ACCESS_MASM(masm())
Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<JSFunction> setter) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss;
// Check that the maps haven't changed.
__ JumpIfSmi(rdx, &miss);
CheckPrototypes(receiver, rdx, holder, rbx, r8, rdi, name, &miss);
GenerateStoreViaSetter(masm(), setter);
__ bind(&miss);
TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
return GetICCode(kind(), Code::CALLBACKS, name);
}
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> receiver,
Handle<JSObject> object,
Handle<Name> name) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss;
// Check that the map of the object hasn't changed.
__ CheckMap(rdx, Handle<Map>(receiver->map()), &miss,
__ CheckMap(receiver(), Handle<Map>(object->map()), &miss,
DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed.
if (receiver->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(rdx, rbx, &miss);
if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(receiver(), scratch1(), &miss);
}
// Stub never generated for non-global objects that require access
// checks.
ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
__ pop(rbx); // remove the return address
__ push(rdx); // receiver
__ push(rcx); // name
__ push(rax); // value
__ pop(scratch1()); // remove the return address
__ push(receiver());
__ push(this->name());
__ push(value());
__ Push(Smi::FromInt(strict_mode()));
__ push(rbx); // restore return address
__ push(scratch1()); // restore return address
// Do tail-call to the runtime system.
ExternalReference store_ic_property =
@ -2537,22 +2499,17 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> cell,
Handle<Name> name) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss;
// Check that the map of the global has not changed.
__ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
__ Cmp(FieldOperand(receiver(), HeapObject::kMapOffset),
Handle<Map>(object->map()));
__ j(not_equal, &miss);
// Compute the cell operand to use.
__ Move(rbx, cell);
Operand cell_operand = FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset);
__ Move(scratch1(), cell);
Operand cell_operand =
FieldOperand(scratch1(), JSGlobalPropertyCell::kValueOffset);
// Check that the value in the cell is not the hole. If it is, this
// cell could have been deleted and reintroducing the global needs
@ -2562,7 +2519,7 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
__ j(equal, &miss);
// Store the value in the cell.
__ movq(cell_operand, rax);
__ movq(cell_operand, value());
// Cells are always rescanned, so no write barrier here.
// Return the value (register rax).
@ -2580,55 +2537,26 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
}
Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
Handle<Map> receiver_map) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
ElementsKind elements_kind = receiver_map->elements_kind();
bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
Handle<Code> stub =
KeyedStoreElementStub(is_js_array,
elements_kind,
store_mode_).GetCode(isolate());
__ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
}
Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
MapHandleList* receiver_maps,
CodeHandleList* handler_stubs,
MapHandleList* transitioned_maps) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss;
__ JumpIfSmi(rdx, &miss, Label::kNear);
__ JumpIfSmi(receiver(), &miss, Label::kNear);
__ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset));
__ movq(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset));
int receiver_count = receiver_maps->length();
for (int i = 0; i < receiver_count; ++i) {
// Check map and tail call if there's a match
__ Cmp(rdi, receiver_maps->at(i));
__ Cmp(scratch1(), receiver_maps->at(i));
if (transitioned_maps->at(i).is_null()) {
__ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET);
} else {
Label next_map;
__ j(not_equal, &next_map, Label::kNear);
__ movq(rbx, transitioned_maps->at(i), RelocInfo::EMBEDDED_OBJECT);
__ movq(transition_map(),
transitioned_maps->at(i),
RelocInfo::EMBEDDED_OBJECT);
__ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
__ bind(&next_map);
}
@ -2786,33 +2714,6 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
}
Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
Handle<Map> receiver_map) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
ElementsKind elements_kind = receiver_map->elements_kind();
if (receiver_map->has_fast_elements() ||
receiver_map->has_external_array_elements()) {
Handle<Code> stub = KeyedLoadFastElementStub(
receiver_map->instance_type() == JS_ARRAY_TYPE,
elements_kind).GetCode(isolate());
__ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
} else {
Handle<Code> stub =
KeyedLoadDictionaryElementStub().GetCode(isolate());
__ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
}
TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss);
// Return the generated code.
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
}
Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
MapHandleList* receiver_maps,
CodeHandleList* handlers,