Commit 88b8715f authored by verwaest@chromium.org's avatar verwaest@chromium.org

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
parent 53310ac1
...@@ -2574,26 +2574,21 @@ Handle<Code> CallStubCompiler::CompileCallGlobal( ...@@ -2574,26 +2574,21 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
Handle<Code> StoreStubCompiler::CompileStoreCallback( Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<Name> name, Handle<Name> name,
Handle<JSObject> receiver, Handle<JSObject> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : receiver
// -- r2 : name
// -- lr : return address
// -----------------------------------
Label miss; Label miss;
// Check that the maps haven't changed. // Check that the maps haven't changed.
__ JumpIfSmi(r1, &miss); __ JumpIfSmi(receiver(), &miss);
CheckPrototypes(receiver, r1, holder, r3, r4, r5, name, &miss); CheckPrototypes(object, receiver(), holder,
scratch1(), scratch2(), scratch3(), name, &miss);
// Stub never generated for non-global objects that require access checks. // Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
__ push(r1); // receiver __ push(receiver()); // receiver
__ mov(ip, Operand(callback)); // callback info __ mov(ip, Operand(callback)); // callback info
__ Push(ip, r2, r0); __ Push(ip, this->name(), value());
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference store_callback_property = ExternalReference store_callback_property =
...@@ -2655,61 +2650,28 @@ void StoreStubCompiler::GenerateStoreViaSetter( ...@@ -2655,61 +2650,28 @@ void StoreStubCompiler::GenerateStoreViaSetter(
#define __ ACCESS_MASM(masm()) #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<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> receiver, Handle<JSObject> object,
Handle<Name> name) { Handle<Name> name) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : receiver
// -- r2 : name
// -- lr : return address
// -----------------------------------
Label miss; Label miss;
// Check that the map of the object hasn't changed. // 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); DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed. // Perform global security token check if needed.
if (receiver->IsJSGlobalProxy()) { if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(r1, r3, &miss); __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss);
} }
// Stub is never generated for non-global objects that require access // Stub is never generated for non-global objects that require access
// checks. // 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()))); __ mov(scratch1(), Operand(Smi::FromInt(strict_mode())));
__ push(r0); // strict mode __ push(scratch1()); // strict mode
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference store_ic_property = ExternalReference store_ic_property =
...@@ -2730,40 +2692,38 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal( ...@@ -2730,40 +2692,38 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
Handle<GlobalObject> object, Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> cell, Handle<JSGlobalPropertyCell> cell,
Handle<Name> name) { Handle<Name> name) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : receiver
// -- r2 : name
// -- lr : return address
// -----------------------------------
Label miss; Label miss;
// Check that the map of the global has not changed. // Check that the map of the global has not changed.
__ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); __ ldr(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
__ cmp(r3, Operand(Handle<Map>(object->map()))); __ cmp(scratch1(), Operand(Handle<Map>(object->map())));
__ b(ne, &miss); __ b(ne, &miss);
// Check that the value in the cell is not the hole. If it is, this // 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 // cell could have been deleted and reintroducing the global needs
// to update the property details in the property dictionary of the // to update the property details in the property dictionary of the
// global object. We bail out to the runtime system to do that. // global object. We bail out to the runtime system to do that.
__ mov(r4, Operand(cell)); __ mov(scratch1(), Operand(cell));
__ LoadRoot(r5, Heap::kTheHoleValueRootIndex); __ LoadRoot(scratch2(), Heap::kTheHoleValueRootIndex);
__ ldr(r6, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset)); __ ldr(scratch3(),
__ cmp(r5, r6); FieldMemOperand(scratch1(), JSGlobalPropertyCell::kValueOffset));
__ cmp(scratch3(), scratch2());
__ b(eq, &miss); __ b(eq, &miss);
// Store the value in the cell. // 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. // Cells are always rescanned, so no write barrier here.
Counters* counters = masm()->isolate()->counters(); Counters* counters = masm()->isolate()->counters();
__ IncrementCounter(counters->named_store_global_inline(), 1, r4, r3); __ IncrementCounter(
counters->named_store_global_inline(), 1, scratch1(), scratch2());
__ Ret(); __ Ret();
// Handle store cache miss. // Handle store cache miss.
__ bind(&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())); TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code. // Return the generated code.
...@@ -2909,33 +2869,6 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal( ...@@ -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( Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
MapHandleList* receiver_maps, MapHandleList* receiver_maps,
CodeHandleList* handlers, CodeHandleList* handlers,
...@@ -2969,56 +2902,24 @@ Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( ...@@ -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( Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
MapHandleList* receiver_maps, MapHandleList* receiver_maps,
CodeHandleList* handler_stubs, CodeHandleList* handler_stubs,
MapHandleList* transitioned_maps) { MapHandleList* transitioned_maps) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : key
// -- r2 : receiver
// -- lr : return address
// -- r3 : scratch
// -----------------------------------
Label miss; Label miss;
__ JumpIfSmi(r2, &miss); __ JumpIfSmi(receiver(), &miss);
int receiver_count = receiver_maps->length(); 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) { for (int i = 0; i < receiver_count; ++i) {
__ mov(ip, Operand(receiver_maps->at(i))); __ mov(ip, Operand(receiver_maps->at(i)));
__ cmp(r3, ip); __ cmp(scratch1(), ip);
if (transitioned_maps->at(i).is_null()) { if (transitioned_maps->at(i).is_null()) {
__ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq); __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq);
} else { } else {
Label next_map; Label next_map;
__ b(ne, &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); __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, al);
__ bind(&next_map); __ bind(&next_map);
} }
......
...@@ -618,6 +618,7 @@ void MacroAssembler::CheckMap(Register obj, ...@@ -618,6 +618,7 @@ void MacroAssembler::CheckMap(Register obj,
void MacroAssembler::DispatchMap(Register obj, void MacroAssembler::DispatchMap(Register obj,
Register unused,
Handle<Map> map, Handle<Map> map,
Handle<Code> success, Handle<Code> success,
SmiCheckType smi_check_type) { SmiCheckType smi_check_type) {
......
...@@ -410,6 +410,7 @@ class MacroAssembler: public Assembler { ...@@ -410,6 +410,7 @@ class MacroAssembler: public Assembler {
// specified target if equal. Skip the smi check if not required (object is // specified target if equal. Skip the smi check if not required (object is
// known to be a heap object) // known to be a heap object)
void DispatchMap(Register obj, void DispatchMap(Register obj,
Register unused,
Handle<Map> map, Handle<Map> map,
Handle<Code> success, Handle<Code> success,
SmiCheckType smi_check_type); SmiCheckType smi_check_type);
......
...@@ -2551,31 +2551,25 @@ Handle<Code> CallStubCompiler::CompileCallGlobal( ...@@ -2551,31 +2551,25 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
Handle<Code> StoreStubCompiler::CompileStoreCallback( Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<Name> name, Handle<Name> name,
Handle<JSObject> receiver, Handle<JSObject> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
// ----------- S t a t e ------------- Label miss, miss_restore_name;
// -- eax : value
// -- ecx : name
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss;
// Check that the maps haven't changed, preserving the value register. // Check that the maps haven't changed, preserving the value register.
__ push(eax); __ JumpIfSmi(receiver(), &miss);
__ JumpIfSmi(edx, &miss); CheckPrototypes(object, receiver(), holder,
CheckPrototypes(receiver, edx, holder, ebx, eax, edi, name, &miss); scratch1(), this->name(), scratch2(),
__ pop(eax); // restore value name, &miss_restore_name);
// Stub never generated for non-global objects that require access checks. // Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
__ pop(ebx); // remove the return address __ pop(scratch1()); // remove the return address
__ push(edx); // receiver __ push(receiver());
__ push(Immediate(callback)); // callback info __ Push(callback);
__ push(ecx); // name __ Push(name);
__ push(eax); // value __ push(value());
__ push(ebx); // restore return address __ push(scratch1()); // restore return address
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference store_callback_property = ExternalReference store_callback_property =
...@@ -2583,8 +2577,8 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( ...@@ -2583,8 +2577,8 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
__ TailCallExternalReference(store_callback_property, 4, 1); __ TailCallExternalReference(store_callback_property, 4, 1);
// Handle store cache miss. // Handle store cache miss.
GenerateRestoreName(masm(), &miss_restore_name, name);
__ bind(&miss); __ bind(&miss);
__ pop(eax);
TailCallBuiltin(masm(), MissBuiltin(kind())); TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code. // Return the generated code.
...@@ -2638,66 +2632,30 @@ void StoreStubCompiler::GenerateStoreViaSetter( ...@@ -2638,66 +2632,30 @@ void StoreStubCompiler::GenerateStoreViaSetter(
#define __ ACCESS_MASM(masm()) #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<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> receiver, Handle<JSObject> object,
Handle<Name> name) { Handle<Name> name) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : name
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss; Label miss;
// Check that the map of the object hasn't changed. // 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); &miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed. // Perform global security token check if needed.
if (receiver->IsJSGlobalProxy()) { if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(edx, ebx, &miss); __ CheckAccessGlobalProxy(edx, ebx, &miss);
} }
// Stub never generated for non-global objects that require access // Stub never generated for non-global objects that require access
// checks. // checks.
ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
__ pop(ebx); // remove the return address __ pop(scratch1()); // remove the return address
__ push(edx); // receiver __ push(receiver());
__ push(ecx); // name __ push(this->name());
__ push(eax); // value __ push(value());
__ push(Immediate(Smi::FromInt(strict_mode()))); __ push(Immediate(Smi::FromInt(strict_mode())));
__ push(ebx); // restore return address __ push(scratch1()); // restore return address
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference store_ic_property = ExternalReference store_ic_property =
...@@ -2717,22 +2675,17 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal( ...@@ -2717,22 +2675,17 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
Handle<GlobalObject> object, Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> cell, Handle<JSGlobalPropertyCell> cell,
Handle<Name> name) { Handle<Name> name) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : name
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss; Label miss;
// Check that the map of the global has not changed. // 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()))); Immediate(Handle<Map>(object->map())));
__ j(not_equal, &miss); __ j(not_equal, &miss);
// Compute the cell operand to use. // Compute the cell operand to use.
__ mov(ebx, Immediate(cell)); __ mov(scratch1(), Immediate(cell));
Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); Operand cell_operand =
FieldOperand(scratch1(), JSGlobalPropertyCell::kValueOffset);
// Check that the value in the cell is not the hole. If it is, this // 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 // cell could have been deleted and reintroducing the global needs
...@@ -2742,7 +2695,7 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal( ...@@ -2742,7 +2695,7 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
__ j(equal, &miss); __ j(equal, &miss);
// Store the value in the cell. // Store the value in the cell.
__ mov(cell_operand, eax); __ mov(cell_operand, value());
// No write barrier here, because cells are always rescanned. // No write barrier here, because cells are always rescanned.
// Return the value (register eax). // Return the value (register eax).
...@@ -2760,52 +2713,21 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal( ...@@ -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( Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
MapHandleList* receiver_maps, MapHandleList* receiver_maps,
CodeHandleList* handler_stubs, CodeHandleList* handler_stubs,
MapHandleList* transitioned_maps) { MapHandleList* transitioned_maps) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : key
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss; Label miss;
__ JumpIfSmi(edx, &miss, Label::kNear); __ JumpIfSmi(receiver(), &miss, Label::kNear);
__ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); __ mov(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset));
// ebx: receiver->map().
for (int i = 0; i < receiver_maps->length(); ++i) { 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()) { if (transitioned_maps->at(i).is_null()) {
__ j(equal, handler_stubs->at(i)); __ j(equal, handler_stubs->at(i));
} else { } else {
Label next_map; Label next_map;
__ j(not_equal, &next_map, Label::kNear); __ 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); __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
__ bind(&next_map); __ bind(&next_map);
} }
...@@ -2961,34 +2883,6 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal( ...@@ -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( Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
MapHandleList* receiver_maps, MapHandleList* receiver_maps,
CodeHandleList* handlers, CodeHandleList* handlers,
......
...@@ -1609,6 +1609,71 @@ Handle<Code> BaseStoreStubCompiler::CompileStoreField(Handle<JSObject> object, ...@@ -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 __ #undef __
......
...@@ -895,6 +895,10 @@ class KeyedStoreStubCompiler: public BaseStoreStubCompiler { ...@@ -895,6 +895,10 @@ class KeyedStoreStubCompiler: public BaseStoreStubCompiler {
} }
private: private:
Register transition_map() {
return registers()[3];
}
static Register* registers(); static Register* registers();
virtual Code::Kind kind() { return Code::KEYED_STORE_IC; } virtual Code::Kind kind() { return Code::KEYED_STORE_IC; }
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) { virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
......
...@@ -2944,6 +2944,7 @@ void MacroAssembler::EnumLength(Register dst, Register map) { ...@@ -2944,6 +2944,7 @@ void MacroAssembler::EnumLength(Register dst, Register map) {
void MacroAssembler::DispatchMap(Register obj, void MacroAssembler::DispatchMap(Register obj,
Register unused,
Handle<Map> map, Handle<Map> map,
Handle<Code> success, Handle<Code> success,
SmiCheckType smi_check_type) { SmiCheckType smi_check_type) {
......
...@@ -909,6 +909,7 @@ class MacroAssembler: public Assembler { ...@@ -909,6 +909,7 @@ class MacroAssembler: public Assembler {
// specified target if equal. Skip the smi check if not required (object is // specified target if equal. Skip the smi check if not required (object is
// known to be a heap object) // known to be a heap object)
void DispatchMap(Register obj, void DispatchMap(Register obj,
Register unused,
Handle<Map> map, Handle<Map> map,
Handle<Code> success, Handle<Code> success,
SmiCheckType smi_check_type); SmiCheckType smi_check_type);
......
...@@ -2377,29 +2377,24 @@ Handle<Code> CallStubCompiler::CompileCallGlobal( ...@@ -2377,29 +2377,24 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
Handle<Code> StoreStubCompiler::CompileStoreCallback( Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<Name> name, Handle<Name> name,
Handle<JSObject> receiver, Handle<JSObject> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss; Label miss;
// Check that the maps haven't changed. // Check that the maps haven't changed.
__ JumpIfSmi(rdx, &miss); __ JumpIfSmi(receiver(), &miss);
CheckPrototypes(receiver, rdx, holder, rbx, r8, rdi, name, &miss); CheckPrototypes(object, receiver(), holder,
scratch1(), scratch2(), scratch3(), name, &miss);
// Stub never generated for non-global objects that require access checks. // Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
__ pop(rbx); // remove the return address __ pop(scratch1()); // remove the return address
__ push(rdx); // receiver __ push(receiver());
__ Push(callback); // callback info __ Push(callback); // callback info
__ push(rcx); // name __ push(this->name());
__ push(rax); // value __ push(value());
__ push(rbx); // restore return address __ push(scratch1()); // restore return address
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference store_callback_property = ExternalReference store_callback_property =
...@@ -2461,63 +2456,30 @@ void StoreStubCompiler::GenerateStoreViaSetter( ...@@ -2461,63 +2456,30 @@ void StoreStubCompiler::GenerateStoreViaSetter(
#define __ ACCESS_MASM(masm()) #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<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> receiver, Handle<JSObject> object,
Handle<Name> name) { Handle<Name> name) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss; Label miss;
// Check that the map of the object hasn't changed. // 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); DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed. // Perform global security token check if needed.
if (receiver->IsJSGlobalProxy()) { if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(rdx, rbx, &miss); __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss);
} }
// Stub never generated for non-global objects that require access // Stub never generated for non-global objects that require access
// checks. // checks.
ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
__ pop(rbx); // remove the return address __ pop(scratch1()); // remove the return address
__ push(rdx); // receiver __ push(receiver());
__ push(rcx); // name __ push(this->name());
__ push(rax); // value __ push(value());
__ Push(Smi::FromInt(strict_mode())); __ Push(Smi::FromInt(strict_mode()));
__ push(rbx); // restore return address __ push(scratch1()); // restore return address
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference store_ic_property = ExternalReference store_ic_property =
...@@ -2537,22 +2499,17 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal( ...@@ -2537,22 +2499,17 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
Handle<GlobalObject> object, Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> cell, Handle<JSGlobalPropertyCell> cell,
Handle<Name> name) { Handle<Name> name) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss; Label miss;
// Check that the map of the global has not changed. // Check that the map of the global has not changed.
__ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), __ Cmp(FieldOperand(receiver(), HeapObject::kMapOffset),
Handle<Map>(object->map())); Handle<Map>(object->map()));
__ j(not_equal, &miss); __ j(not_equal, &miss);
// Compute the cell operand to use. // Compute the cell operand to use.
__ Move(rbx, cell); __ Move(scratch1(), cell);
Operand cell_operand = FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset); Operand cell_operand =
FieldOperand(scratch1(), JSGlobalPropertyCell::kValueOffset);
// Check that the value in the cell is not the hole. If it is, this // 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 // cell could have been deleted and reintroducing the global needs
...@@ -2562,7 +2519,7 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal( ...@@ -2562,7 +2519,7 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
__ j(equal, &miss); __ j(equal, &miss);
// Store the value in the cell. // Store the value in the cell.
__ movq(cell_operand, rax); __ movq(cell_operand, value());
// Cells are always rescanned, so no write barrier here. // Cells are always rescanned, so no write barrier here.
// Return the value (register rax). // Return the value (register rax).
...@@ -2580,55 +2537,26 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal( ...@@ -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( Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
MapHandleList* receiver_maps, MapHandleList* receiver_maps,
CodeHandleList* handler_stubs, CodeHandleList* handler_stubs,
MapHandleList* transitioned_maps) { MapHandleList* transitioned_maps) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss; 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(); int receiver_count = receiver_maps->length();
for (int i = 0; i < receiver_count; ++i) { for (int i = 0; i < receiver_count; ++i) {
// Check map and tail call if there's a match // 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()) { if (transitioned_maps->at(i).is_null()) {
__ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET); __ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET);
} else { } else {
Label next_map; Label next_map;
__ j(not_equal, &next_map, Label::kNear); __ 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); __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
__ bind(&next_map); __ bind(&next_map);
} }
...@@ -2786,33 +2714,6 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal( ...@@ -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( Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
MapHandleList* receiver_maps, MapHandleList* receiver_maps,
CodeHandleList* handlers, CodeHandleList* handlers,
......
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