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:
parent
53310ac152
commit
88b8715f95
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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 __
|
||||
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user