Refactoring Store ICs. A first step towards polymorphic store ICs.
Review URL: https://chromiumcodereview.appspot.com/12781004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13934 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
8db737a583
commit
569d9c59b9
@ -4513,7 +4513,7 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
StubCompiler::GenerateLoadArrayLength(masm, receiver, r3, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
|
||||
}
|
||||
|
||||
|
||||
@ -4542,7 +4542,7 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r3, r4, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
|
||||
}
|
||||
|
||||
|
||||
@ -4573,7 +4573,7 @@ void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||
support_wrapper_);
|
||||
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
|
||||
}
|
||||
|
||||
|
||||
@ -4643,7 +4643,7 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
__ bind(&miss);
|
||||
|
||||
StubCompiler::GenerateStoreMiss(masm, kind());
|
||||
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -320,19 +320,6 @@ void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
|
||||
}
|
||||
|
||||
|
||||
// Load a fast property out of a holder object (src). In-object properties
|
||||
// are loaded directly otherwise the property is loaded from the properties
|
||||
// fixed array.
|
||||
void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
|
||||
Register dst,
|
||||
Register src,
|
||||
Handle<JSObject> holder,
|
||||
PropertyIndex index) {
|
||||
DoGenerateFastPropertyLoad(
|
||||
masm, dst, src, index.is_inobject(holder), index.translate(holder));
|
||||
}
|
||||
|
||||
|
||||
void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm,
|
||||
Register dst,
|
||||
Register src,
|
||||
@ -446,9 +433,11 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
Handle<Name> name,
|
||||
Register receiver_reg,
|
||||
Register name_reg,
|
||||
Register value_reg,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
Label* miss_label) {
|
||||
Label* miss_label,
|
||||
Label* miss_restore_name) {
|
||||
// r0 : value
|
||||
Label exit;
|
||||
|
||||
@ -485,17 +474,8 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
holder = JSObject::cast(holder->GetPrototype());
|
||||
} while (holder->GetPrototype()->IsJSObject());
|
||||
}
|
||||
// We need an extra register, push
|
||||
__ push(name_reg);
|
||||
Label miss_pop, done_check;
|
||||
CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
|
||||
scratch1, scratch2, name, &miss_pop);
|
||||
__ jmp(&done_check);
|
||||
__ bind(&miss_pop);
|
||||
__ pop(name_reg);
|
||||
__ jmp(miss_label);
|
||||
__ bind(&done_check);
|
||||
__ pop(name_reg);
|
||||
scratch1, scratch2, name, miss_restore_name);
|
||||
}
|
||||
|
||||
// Stub never generated for non-global objects that require access
|
||||
@ -542,14 +522,14 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
if (index < 0) {
|
||||
// Set the property straight into the object.
|
||||
int offset = object->map()->instance_size() + (index * kPointerSize);
|
||||
__ str(r0, FieldMemOperand(receiver_reg, offset));
|
||||
__ str(value_reg, FieldMemOperand(receiver_reg, offset));
|
||||
|
||||
// Skip updating write barrier if storing a smi.
|
||||
__ JumpIfSmi(r0, &exit);
|
||||
__ JumpIfSmi(value_reg, &exit);
|
||||
|
||||
// Update the write barrier for the array address.
|
||||
// Pass the now unused name_reg as a scratch register.
|
||||
__ mov(name_reg, r0);
|
||||
__ mov(name_reg, value_reg);
|
||||
__ RecordWriteField(receiver_reg,
|
||||
offset,
|
||||
name_reg,
|
||||
@ -562,14 +542,14 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
// Get the properties array
|
||||
__ ldr(scratch1,
|
||||
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
|
||||
__ str(r0, FieldMemOperand(scratch1, offset));
|
||||
__ str(value_reg, FieldMemOperand(scratch1, offset));
|
||||
|
||||
// Skip updating write barrier if storing a smi.
|
||||
__ JumpIfSmi(r0, &exit);
|
||||
__ JumpIfSmi(value_reg, &exit);
|
||||
|
||||
// Update the write barrier for the array address.
|
||||
// Ok to clobber receiver_reg and name_reg, since we return.
|
||||
__ mov(name_reg, r0);
|
||||
__ mov(name_reg, value_reg);
|
||||
__ RecordWriteField(scratch1,
|
||||
offset,
|
||||
name_reg,
|
||||
@ -579,26 +559,19 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
// Return the value (register r0).
|
||||
ASSERT(value_reg.is(r0));
|
||||
__ bind(&exit);
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
|
||||
void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
|
||||
ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
|
||||
Handle<Code> code = (kind == Code::LOAD_IC)
|
||||
? masm->isolate()->builtins()->LoadIC_Miss()
|
||||
: masm->isolate()->builtins()->KeyedLoadIC_Miss();
|
||||
__ Jump(code, RelocInfo::CODE_TARGET);
|
||||
void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
|
||||
Label* label,
|
||||
Handle<Name> name) {
|
||||
if (!label->is_unused()) {
|
||||
__ bind(label);
|
||||
__ mov(this->name(), Operand(name));
|
||||
}
|
||||
|
||||
|
||||
void StubCompiler::GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind) {
|
||||
ASSERT(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC);
|
||||
Handle<Code> code = (kind == Code::STORE_IC)
|
||||
? masm->isolate()->builtins()->StoreIC_Miss()
|
||||
: masm->isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ Jump(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
@ -1063,15 +1036,15 @@ static void StoreIntAsFloat(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
#define __ ACCESS_MASM(masm())
|
||||
|
||||
|
||||
void StubCompiler::GenerateTailCall(Handle<Code> code) {
|
||||
void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
|
||||
__ Jump(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
#define __ ACCESS_MASM(masm())
|
||||
|
||||
|
||||
Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
|
||||
Register object_reg,
|
||||
Handle<JSObject> holder,
|
||||
@ -1190,7 +1163,7 @@ void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success,
|
||||
if (!miss->is_unused()) {
|
||||
__ b(success);
|
||||
__ bind(miss);
|
||||
GenerateLoadMiss(masm(), kind());
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2599,36 +2572,6 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
|
||||
int index,
|
||||
Handle<Map> transition,
|
||||
Handle<Name> name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r0 : value
|
||||
// -- r1 : receiver
|
||||
// -- r2 : name
|
||||
// -- lr : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
GenerateStoreField(masm(),
|
||||
object,
|
||||
index,
|
||||
transition,
|
||||
name,
|
||||
r1, r2, r3, r4,
|
||||
&miss);
|
||||
__ bind(&miss);
|
||||
Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(transition.is_null()
|
||||
? Code::FIELD
|
||||
: Code::MAP_TRANSITION, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StoreStubCompiler::CompileStoreCallback(
|
||||
Handle<Name> name,
|
||||
Handle<JSObject> receiver,
|
||||
@ -2660,11 +2603,10 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
|
||||
|
||||
// Handle store cache miss.
|
||||
__ bind(&miss);
|
||||
Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::CALLBACKS, name);
|
||||
return GetICCode(kind(), Code::CALLBACKS, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2733,11 +2675,10 @@ Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
|
||||
GenerateStoreViaSetter(masm(), setter);
|
||||
|
||||
__ bind(&miss);
|
||||
Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::CALLBACKS, name);
|
||||
return GetICCode(kind(), Code::CALLBACKS, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2767,7 +2708,7 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
|
||||
|
||||
__ Push(r1, r2, r0); // Receiver, name, value.
|
||||
|
||||
__ mov(r0, Operand(Smi::FromInt(strict_mode_)));
|
||||
__ mov(r0, Operand(Smi::FromInt(strict_mode())));
|
||||
__ push(r0); // strict mode
|
||||
|
||||
// Do tail-call to the runtime system.
|
||||
@ -2778,11 +2719,10 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
|
||||
|
||||
// Handle store cache miss.
|
||||
__ bind(&miss);
|
||||
Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::INTERCEPTOR, name);
|
||||
return GetICCode(kind(), Code::INTERCEPTOR, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2824,11 +2764,10 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
|
||||
// Handle store cache miss.
|
||||
__ bind(&miss);
|
||||
__ IncrementCounter(counters->named_store_global_inline_miss(), 1, r4, r3);
|
||||
Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::NORMAL, name);
|
||||
return GetICCode(kind(), Code::NORMAL, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2866,6 +2805,20 @@ Register* KeyedLoadStubCompiler::registers() {
|
||||
}
|
||||
|
||||
|
||||
Register* StoreStubCompiler::registers() {
|
||||
// receiver, name, value, scratch1, scratch2, scratch3.
|
||||
static Register registers[] = { r1, r2, r0, r3, r4, r5 };
|
||||
return registers;
|
||||
}
|
||||
|
||||
|
||||
Register* KeyedStoreStubCompiler::registers() {
|
||||
// receiver, name, value, scratch1, scratch2, scratch3.
|
||||
static Register registers[] = { r2, r1, r0, r3, r4, r5 };
|
||||
return registers;
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
|
||||
Register name_reg,
|
||||
Label* miss) {
|
||||
@ -2874,6 +2827,14 @@ void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
|
||||
}
|
||||
|
||||
|
||||
void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
|
||||
Register name_reg,
|
||||
Label* miss) {
|
||||
__ cmp(name_reg, Operand(name));
|
||||
__ b(ne, miss);
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
@ -2968,8 +2929,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
|
||||
__ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK);
|
||||
}
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
|
||||
@ -3000,7 +2960,7 @@ Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
|
||||
}
|
||||
|
||||
__ bind(&miss);
|
||||
GenerateLoadMiss(masm(), kind());
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
InlineCacheState state =
|
||||
@ -3009,47 +2969,6 @@ Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
|
||||
int index,
|
||||
Handle<Map> transition,
|
||||
Handle<Name> name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r0 : value
|
||||
// -- r1 : name
|
||||
// -- r2 : receiver
|
||||
// -- lr : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
Counters* counters = masm()->isolate()->counters();
|
||||
__ IncrementCounter(counters->keyed_store_field(), 1, r3, r4);
|
||||
|
||||
// Check that the name has not changed.
|
||||
__ cmp(r1, Operand(name));
|
||||
__ b(ne, &miss);
|
||||
|
||||
// r3 is used as scratch register. r1 and r2 keep their values if a jump to
|
||||
// the miss label is generated.
|
||||
GenerateStoreField(masm(),
|
||||
object,
|
||||
index,
|
||||
transition,
|
||||
name,
|
||||
r2, r1, r3, r4,
|
||||
&miss);
|
||||
__ bind(&miss);
|
||||
|
||||
__ DecrementCounter(counters->keyed_store_field(), 1, r3, r4);
|
||||
Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(transition.is_null()
|
||||
? Code::FIELD
|
||||
: Code::MAP_TRANSITION, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
|
||||
Handle<Map> receiver_map) {
|
||||
// ----------- S t a t e -------------
|
||||
@ -3068,11 +2987,10 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
|
||||
|
||||
__ DispatchMap(r2, r3, receiver_map, stub, DO_SMI_CHECK);
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::NORMAL, factory()->empty_string());
|
||||
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
|
||||
}
|
||||
|
||||
|
||||
@ -3107,11 +3025,11 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
|
||||
}
|
||||
|
||||
__ bind(&miss);
|
||||
Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
|
||||
return GetICCode(
|
||||
kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
|
||||
}
|
||||
|
||||
|
||||
@ -3292,9 +3210,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
Handle<Code> slow_ic =
|
||||
masm->isolate()->builtins()->KeyedLoadIC_Slow();
|
||||
__ Jump(slow_ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
|
||||
|
||||
// Miss case, call the runtime.
|
||||
__ bind(&miss_force_generic);
|
||||
@ -3304,10 +3220,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
|
||||
Handle<Code> miss_ic =
|
||||
masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
|
||||
__ Jump(miss_ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric);
|
||||
}
|
||||
|
||||
|
||||
@ -3699,9 +3612,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
Handle<Code> slow_ic =
|
||||
masm->isolate()->builtins()->KeyedStoreIC_Slow();
|
||||
__ Jump(slow_ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
|
||||
|
||||
// Miss case, call the runtime.
|
||||
__ bind(&miss_force_generic);
|
||||
@ -3711,10 +3622,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
|
||||
Handle<Code> miss_ic =
|
||||
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
|
||||
__ Jump(miss_ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
|
||||
}
|
||||
|
||||
|
||||
@ -3807,13 +3715,10 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
|
||||
__ Ret();
|
||||
|
||||
__ bind(&miss_force_generic);
|
||||
Handle<Code> ic =
|
||||
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
|
||||
|
||||
__ bind(&transition_elements_kind);
|
||||
Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ Jump(ic_miss, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
|
||||
|
||||
if (is_js_array && IsGrowStoreMode(store_mode)) {
|
||||
// Grow the array by a single element if possible.
|
||||
@ -3878,8 +3783,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
|
||||
__ jmp(&finish_store);
|
||||
|
||||
__ bind(&slow);
|
||||
Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
|
||||
__ Jump(ic_slow, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3953,13 +3857,10 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
|
||||
|
||||
// Handle store cache miss, replacing the ic with the generic stub.
|
||||
__ bind(&miss_force_generic);
|
||||
Handle<Code> ic =
|
||||
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
|
||||
|
||||
__ bind(&transition_elements_kind);
|
||||
Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ Jump(ic_miss, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
|
||||
|
||||
if (is_js_array && IsGrowStoreMode(store_mode)) {
|
||||
// Grow the array by a single element if possible.
|
||||
@ -4044,8 +3945,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
|
||||
__ jmp(&finish_store);
|
||||
|
||||
__ bind(&slow);
|
||||
Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
|
||||
__ Jump(ic_slow, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3301,7 +3301,7 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
StubCompiler::GenerateLoadArrayLength(masm, edx, eax, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
|
||||
}
|
||||
|
||||
|
||||
@ -3320,7 +3320,7 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
StubCompiler::GenerateLoadFunctionPrototype(masm, edx, eax, ebx, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
|
||||
}
|
||||
|
||||
|
||||
@ -3340,7 +3340,7 @@ void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||
StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss,
|
||||
support_wrapper_);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
|
||||
}
|
||||
|
||||
|
||||
@ -3404,7 +3404,7 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
__ bind(&miss);
|
||||
|
||||
StubCompiler::GenerateStoreMiss(masm, kind());
|
||||
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -369,19 +369,6 @@ void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
// Load a fast property out of a holder object (src). In-object properties
|
||||
// are loaded directly otherwise the property is loaded from the properties
|
||||
// fixed array.
|
||||
void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
|
||||
Register dst,
|
||||
Register src,
|
||||
Handle<JSObject> holder,
|
||||
PropertyIndex index) {
|
||||
DoGenerateFastPropertyLoad(
|
||||
masm, dst, src, index.is_inobject(holder), index.translate(holder));
|
||||
}
|
||||
|
||||
|
||||
void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm,
|
||||
Register dst,
|
||||
Register src,
|
||||
@ -729,28 +716,13 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
};
|
||||
|
||||
|
||||
void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
|
||||
ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
|
||||
Handle<Code> code = (kind == Code::LOAD_IC)
|
||||
? masm->isolate()->builtins()->LoadIC_Miss()
|
||||
: masm->isolate()->builtins()->KeyedLoadIC_Miss();
|
||||
__ jmp(code, RelocInfo::CODE_TARGET);
|
||||
void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
|
||||
Label* label,
|
||||
Handle<Name> name) {
|
||||
if (!label->is_unused()) {
|
||||
__ bind(label);
|
||||
__ mov(this->name(), Immediate(name));
|
||||
}
|
||||
|
||||
|
||||
void StubCompiler::GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind) {
|
||||
ASSERT(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC);
|
||||
Handle<Code> code = (kind == Code::STORE_IC)
|
||||
? masm->isolate()->builtins()->StoreIC_Miss()
|
||||
: masm->isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ jmp(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
|
||||
Handle<Code> code =
|
||||
masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
|
||||
__ jmp(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
@ -763,9 +735,11 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
Handle<Name> name,
|
||||
Register receiver_reg,
|
||||
Register name_reg,
|
||||
Register value_reg,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
Label* miss_label) {
|
||||
Label* miss_label,
|
||||
Label* miss_restore_name) {
|
||||
LookupResult lookup(masm->isolate());
|
||||
object->Lookup(*name, &lookup);
|
||||
if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) {
|
||||
@ -800,16 +774,8 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
} while (holder->GetPrototype()->IsJSObject());
|
||||
}
|
||||
// We need an extra register, push
|
||||
__ push(name_reg);
|
||||
Label miss_pop, done_check;
|
||||
CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
|
||||
scratch1, scratch2, name, &miss_pop);
|
||||
__ jmp(&done_check);
|
||||
__ bind(&miss_pop);
|
||||
__ pop(name_reg);
|
||||
__ jmp(miss_label);
|
||||
__ bind(&done_check);
|
||||
__ pop(name_reg);
|
||||
scratch1, scratch2, name, miss_restore_name);
|
||||
}
|
||||
|
||||
// Stub never generated for non-global objects that require access
|
||||
@ -857,11 +823,11 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
if (index < 0) {
|
||||
// Set the property straight into the object.
|
||||
int offset = object->map()->instance_size() + (index * kPointerSize);
|
||||
__ mov(FieldOperand(receiver_reg, offset), eax);
|
||||
__ mov(FieldOperand(receiver_reg, offset), value_reg);
|
||||
|
||||
// Update the write barrier for the array address.
|
||||
// Pass the value being stored in the now unused name_reg.
|
||||
__ mov(name_reg, eax);
|
||||
__ mov(name_reg, value_reg);
|
||||
__ RecordWriteField(receiver_reg,
|
||||
offset,
|
||||
name_reg,
|
||||
@ -876,7 +842,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
|
||||
// Update the write barrier for the array address.
|
||||
// Pass the value being stored in the now unused name_reg.
|
||||
__ mov(name_reg, eax);
|
||||
__ mov(name_reg, value_reg);
|
||||
__ RecordWriteField(scratch1,
|
||||
offset,
|
||||
name_reg,
|
||||
@ -885,6 +851,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
// Return the value (register eax).
|
||||
ASSERT(value_reg.is(eax));
|
||||
__ ret(0);
|
||||
}
|
||||
|
||||
@ -933,15 +900,16 @@ static void GenerateCheckPropertyCells(MacroAssembler* masm,
|
||||
}
|
||||
}
|
||||
|
||||
#undef __
|
||||
#define __ ACCESS_MASM(masm())
|
||||
|
||||
|
||||
void StubCompiler::GenerateTailCall(Handle<Code> code) {
|
||||
void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
|
||||
__ jmp(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
#define __ ACCESS_MASM(masm())
|
||||
|
||||
|
||||
Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
|
||||
Register object_reg,
|
||||
Handle<JSObject> holder,
|
||||
@ -1062,7 +1030,7 @@ void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success,
|
||||
if (!miss->is_unused()) {
|
||||
__ jmp(success);
|
||||
__ bind(miss);
|
||||
GenerateLoadMiss(masm(), kind());
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2581,39 +2549,6 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
|
||||
int index,
|
||||
Handle<Map> transition,
|
||||
Handle<Name> name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : value
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
// Generate store field code. Trashes the name register.
|
||||
GenerateStoreField(masm(),
|
||||
object,
|
||||
index,
|
||||
transition,
|
||||
name,
|
||||
edx, ecx, ebx, edi,
|
||||
&miss);
|
||||
// Handle store cache miss.
|
||||
__ bind(&miss);
|
||||
__ mov(ecx, Immediate(name)); // restore name
|
||||
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(transition.is_null()
|
||||
? Code::FIELD
|
||||
: Code::MAP_TRANSITION, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StoreStubCompiler::CompileStoreCallback(
|
||||
Handle<Name> name,
|
||||
Handle<JSObject> receiver,
|
||||
@ -2650,11 +2585,10 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
|
||||
// Handle store cache miss.
|
||||
__ bind(&miss);
|
||||
__ pop(eax);
|
||||
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::CALLBACKS, name);
|
||||
return GetICCode(kind(), Code::CALLBACKS, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2727,11 +2661,10 @@ Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
|
||||
|
||||
__ bind(&miss);
|
||||
__ pop(ecx);
|
||||
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::CALLBACKS, name);
|
||||
return GetICCode(kind(), Code::CALLBACKS, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2763,7 +2696,7 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
|
||||
__ push(edx); // receiver
|
||||
__ push(ecx); // name
|
||||
__ push(eax); // value
|
||||
__ push(Immediate(Smi::FromInt(strict_mode_)));
|
||||
__ push(Immediate(Smi::FromInt(strict_mode())));
|
||||
__ push(ebx); // restore return address
|
||||
|
||||
// Do tail-call to the runtime system.
|
||||
@ -2773,11 +2706,10 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
|
||||
|
||||
// Handle store cache miss.
|
||||
__ bind(&miss);
|
||||
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::INTERCEPTOR, name);
|
||||
return GetICCode(kind(), Code::INTERCEPTOR, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2821,52 +2753,10 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
|
||||
// Handle store cache miss.
|
||||
__ bind(&miss);
|
||||
__ IncrementCounter(counters->named_store_global_inline_miss(), 1);
|
||||
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::NORMAL, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
|
||||
int index,
|
||||
Handle<Map> transition,
|
||||
Handle<Name> name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : value
|
||||
// -- ecx : key
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
Counters* counters = isolate()->counters();
|
||||
__ IncrementCounter(counters->keyed_store_field(), 1);
|
||||
|
||||
// Check that the name has not changed.
|
||||
__ cmp(ecx, Immediate(name));
|
||||
__ j(not_equal, &miss);
|
||||
|
||||
// Generate store field code. Trashes the name register.
|
||||
GenerateStoreField(masm(),
|
||||
object,
|
||||
index,
|
||||
transition,
|
||||
name,
|
||||
edx, ecx, ebx, edi,
|
||||
&miss);
|
||||
|
||||
// Handle store cache miss.
|
||||
__ bind(&miss);
|
||||
__ DecrementCounter(counters->keyed_store_field(), 1);
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(transition.is_null()
|
||||
? Code::FIELD
|
||||
: Code::MAP_TRANSITION, name);
|
||||
return GetICCode(kind(), Code::NORMAL, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2887,11 +2777,10 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
|
||||
|
||||
__ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::NORMAL, factory()->empty_string());
|
||||
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
|
||||
}
|
||||
|
||||
|
||||
@ -2922,11 +2811,11 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
|
||||
}
|
||||
}
|
||||
__ bind(&miss);
|
||||
Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ jmp(miss_ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
|
||||
return GetICCode(
|
||||
kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
|
||||
}
|
||||
|
||||
|
||||
@ -2964,6 +2853,20 @@ Register* KeyedLoadStubCompiler::registers() {
|
||||
}
|
||||
|
||||
|
||||
Register* StoreStubCompiler::registers() {
|
||||
// receiver, name, value, scratch1, scratch2, scratch3.
|
||||
static Register registers[] = { edx, ecx, eax, ebx, edi, no_reg };
|
||||
return registers;
|
||||
}
|
||||
|
||||
|
||||
Register* KeyedStoreStubCompiler::registers() {
|
||||
// receiver, name, value, scratch1, scratch2, scratch3.
|
||||
static Register registers[] = { edx, ecx, eax, ebx, edi, no_reg };
|
||||
return registers;
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
|
||||
Register name_reg,
|
||||
Label* miss) {
|
||||
@ -2972,6 +2875,14 @@ void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
|
||||
}
|
||||
|
||||
|
||||
void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
|
||||
Register name_reg,
|
||||
Label* miss) {
|
||||
__ cmp(name_reg, Immediate(name));
|
||||
__ j(not_equal, miss);
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
@ -3071,7 +2982,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
|
||||
__ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
|
||||
}
|
||||
|
||||
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
||||
TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss);
|
||||
|
||||
// Return the generated code.
|
||||
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
|
||||
@ -3100,7 +3011,7 @@ Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
|
||||
}
|
||||
|
||||
__ bind(&miss);
|
||||
GenerateLoadMiss(masm(), kind());
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
InlineCacheState state =
|
||||
@ -3284,10 +3195,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
|
||||
Handle<Code> slow_ic =
|
||||
masm->isolate()->builtins()->KeyedLoadIC_Slow();
|
||||
__ jmp(slow_ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
|
||||
|
||||
__ bind(&miss_force_generic);
|
||||
// ----------- S t a t e -------------
|
||||
@ -3295,10 +3203,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
|
||||
Handle<Code> miss_force_generic_ic =
|
||||
masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
|
||||
__ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric);
|
||||
}
|
||||
|
||||
|
||||
@ -3516,9 +3421,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
|
||||
Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
|
||||
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : value
|
||||
@ -3528,9 +3431,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
// -----------------------------------
|
||||
|
||||
__ bind(&miss_force_generic);
|
||||
Handle<Code> miss_ic =
|
||||
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
|
||||
__ jmp(miss_ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
|
||||
}
|
||||
|
||||
|
||||
@ -3606,14 +3507,11 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
|
||||
|
||||
// Handle store cache miss, replacing the ic with the generic stub.
|
||||
__ bind(&miss_force_generic);
|
||||
Handle<Code> ic_force_generic =
|
||||
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
|
||||
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
|
||||
|
||||
// Handle transition to other elements kinds without using the generic stub.
|
||||
__ bind(&transition_elements_kind);
|
||||
Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ jmp(ic_miss, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
|
||||
|
||||
if (is_js_array && IsGrowStoreMode(store_mode)) {
|
||||
// Handle transition requiring the array to grow.
|
||||
@ -3684,8 +3582,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
|
||||
__ mov(ecx, Immediate(0));
|
||||
|
||||
__ bind(&slow);
|
||||
Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
|
||||
__ jmp(ic_slow, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3734,14 +3631,11 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
|
||||
|
||||
// Handle store cache miss, replacing the ic with the generic stub.
|
||||
__ bind(&miss_force_generic);
|
||||
Handle<Code> ic_force_generic =
|
||||
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
|
||||
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
|
||||
|
||||
// Handle transition to other elements kinds without using the generic stub.
|
||||
__ bind(&transition_elements_kind);
|
||||
Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ jmp(ic_miss, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
|
||||
|
||||
if (is_js_array && IsGrowStoreMode(store_mode)) {
|
||||
// Handle transition requiring the array to grow.
|
||||
@ -3822,8 +3716,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
|
||||
__ mov(ecx, Immediate(0));
|
||||
|
||||
__ bind(&slow);
|
||||
Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
|
||||
__ jmp(ic_slow, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,6 +139,7 @@ class PositionsRecorder;
|
||||
V(REG_EXP_TAG, "RegExp") \
|
||||
V(SCRIPT_TAG, "Script") \
|
||||
V(STORE_IC_TAG, "StoreIC") \
|
||||
V(STORE_POLYMORPHIC_IC_TAG, "StorePolymorphicIC") \
|
||||
V(STUB_TAG, "Stub") \
|
||||
V(NATIVE_FUNCTION_TAG, "Function") \
|
||||
V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile") \
|
||||
|
@ -112,9 +112,9 @@ Handle<JSObject> StubCache::StubHolder(Handle<JSObject> receiver,
|
||||
Handle<Code> StubCache::FindIC(Handle<Name> name,
|
||||
Handle<JSObject> stub_holder,
|
||||
Code::Kind kind,
|
||||
Code::StubType type) {
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(
|
||||
kind, Code::kNoExtraICState, type);
|
||||
Code::StubType type,
|
||||
Code::ExtraICState extra_ic_state) {
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(kind, extra_ic_state, type);
|
||||
Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
@ -122,18 +122,14 @@ Handle<Code> StubCache::FindIC(Handle<Name> name,
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCache::FindStub(Handle<Name> name,
|
||||
Handle<Code> StubCache::FindHandler(Handle<Name> name,
|
||||
Handle<JSObject> stub_holder,
|
||||
Code::Kind kind,
|
||||
Code::StubType type) {
|
||||
Code::StubType type,
|
||||
Code::ExtraICState extra_ic_state) {
|
||||
ASSERT(type != Code::NORMAL);
|
||||
int extra_flags = -1;
|
||||
if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC) {
|
||||
extra_flags = kind;
|
||||
kind = Code::STUB;
|
||||
}
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(
|
||||
kind, Code::kNoExtraICState, type, extra_flags);
|
||||
Code::STUB, extra_ic_state, type, kind);
|
||||
Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
@ -197,7 +193,7 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
|
||||
|
||||
// Compile the stub that is either shared for all names or
|
||||
// name specific if there are global objects involved.
|
||||
Handle<Code> handler = FindStub(
|
||||
Handle<Code> handler = FindHandler(
|
||||
cache_name, receiver, Code::LOAD_IC, Code::NONEXISTENT);
|
||||
if (!handler.is_null()) return handler;
|
||||
|
||||
@ -221,7 +217,7 @@ Handle<Code> StubCache::ComputeLoadField(Handle<Name> name,
|
||||
}
|
||||
|
||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||
Handle<Code> stub = FindStub(
|
||||
Handle<Code> stub = FindHandler(
|
||||
name, stub_holder, Code::LOAD_IC, Code::FIELD);
|
||||
if (!stub.is_null()) return stub;
|
||||
|
||||
@ -240,7 +236,7 @@ Handle<Code> StubCache::ComputeLoadCallback(
|
||||
Handle<ExecutableAccessorInfo> callback) {
|
||||
ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
|
||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||
Handle<Code> stub = FindStub(
|
||||
Handle<Code> stub = FindHandler(
|
||||
name, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
|
||||
if (!stub.is_null()) return stub;
|
||||
|
||||
@ -257,7 +253,7 @@ Handle<Code> StubCache::ComputeLoadViaGetter(Handle<Name> name,
|
||||
Handle<JSObject> holder,
|
||||
Handle<JSFunction> getter) {
|
||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||
Handle<Code> stub = FindStub(
|
||||
Handle<Code> stub = FindHandler(
|
||||
name, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
|
||||
if (!stub.is_null()) return stub;
|
||||
|
||||
@ -274,7 +270,7 @@ Handle<Code> StubCache::ComputeLoadConstant(Handle<Name> name,
|
||||
Handle<JSObject> holder,
|
||||
Handle<JSFunction> value) {
|
||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||
Handle<Code> handler = FindStub(
|
||||
Handle<Code> handler = FindHandler(
|
||||
name, stub_holder, Code::LOAD_IC, Code::CONSTANT_FUNCTION);
|
||||
if (!handler.is_null()) return handler;
|
||||
|
||||
@ -290,7 +286,7 @@ Handle<Code> StubCache::ComputeLoadInterceptor(Handle<Name> name,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<JSObject> holder) {
|
||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||
Handle<Code> stub = FindStub(
|
||||
Handle<Code> stub = FindHandler(
|
||||
name, stub_holder, Code::LOAD_IC, Code::INTERCEPTOR);
|
||||
if (!stub.is_null()) return stub;
|
||||
|
||||
@ -337,7 +333,7 @@ Handle<Code> StubCache::ComputeKeyedLoadField(Handle<Name> name,
|
||||
}
|
||||
|
||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||
Handle<Code> stub = FindStub(
|
||||
Handle<Code> stub = FindHandler(
|
||||
name, stub_holder, Code::KEYED_LOAD_IC, Code::FIELD);
|
||||
if (!stub.is_null()) return stub;
|
||||
|
||||
@ -354,7 +350,7 @@ Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<Name> name,
|
||||
Handle<JSObject> holder,
|
||||
Handle<JSFunction> value) {
|
||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||
Handle<Code> handler = FindStub(
|
||||
Handle<Code> handler = FindHandler(
|
||||
name, stub_holder, Code::KEYED_LOAD_IC, Code::CONSTANT_FUNCTION);
|
||||
if (!handler.is_null()) return handler;
|
||||
|
||||
@ -369,7 +365,7 @@ Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<Name> name,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<JSObject> holder) {
|
||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||
Handle<Code> stub = FindStub(
|
||||
Handle<Code> stub = FindHandler(
|
||||
name, stub_holder, Code::KEYED_LOAD_IC, Code::INTERCEPTOR);
|
||||
if (!stub.is_null()) return stub;
|
||||
|
||||
@ -387,7 +383,7 @@ Handle<Code> StubCache::ComputeKeyedLoadCallback(
|
||||
Handle<JSObject> holder,
|
||||
Handle<ExecutableAccessorInfo> callback) {
|
||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||
Handle<Code> stub = FindStub(
|
||||
Handle<Code> stub = FindHandler(
|
||||
name, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS);
|
||||
if (!stub.is_null()) return stub;
|
||||
|
||||
@ -405,12 +401,11 @@ Handle<Code> StubCache::ComputeStoreField(Handle<Name> name,
|
||||
Handle<Map> transition,
|
||||
StrictModeFlag strict_mode) {
|
||||
Code::StubType type =
|
||||
(transition.is_null()) ? Code::FIELD : Code::MAP_TRANSITION;
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(
|
||||
Code::STORE_IC, strict_mode, type);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
transition.is_null() ? Code::FIELD : Code::MAP_TRANSITION;
|
||||
|
||||
Handle<Code> stub = FindIC(
|
||||
name, receiver, Code::STORE_IC, type, strict_mode);
|
||||
if (!stub.is_null()) return stub;
|
||||
|
||||
StoreStubCompiler compiler(isolate_, strict_mode);
|
||||
Handle<Code> code =
|
||||
@ -473,11 +468,9 @@ Handle<Code> StubCache::ComputeStoreGlobal(Handle<Name> name,
|
||||
Handle<GlobalObject> receiver,
|
||||
Handle<JSGlobalPropertyCell> cell,
|
||||
StrictModeFlag strict_mode) {
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(
|
||||
Code::STORE_IC, strict_mode);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
Handle<Code> stub = FindIC(
|
||||
name, receiver, Code::STORE_IC, Code::NORMAL, strict_mode);
|
||||
if (!stub.is_null()) return stub;
|
||||
|
||||
StoreStubCompiler compiler(isolate_, strict_mode);
|
||||
Handle<Code> code = compiler.CompileStoreGlobal(receiver, cell, name);
|
||||
@ -493,11 +486,9 @@ Handle<Code> StubCache::ComputeStoreCallback(
|
||||
Handle<ExecutableAccessorInfo> callback,
|
||||
StrictModeFlag strict_mode) {
|
||||
ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(
|
||||
Code::STORE_IC, strict_mode, Code::CALLBACKS);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
Handle<Code> stub = FindIC(
|
||||
name, receiver, Code::STORE_IC, Code::CALLBACKS, strict_mode);
|
||||
if (!stub.is_null()) return stub;
|
||||
|
||||
StoreStubCompiler compiler(isolate_, strict_mode);
|
||||
Handle<Code> code =
|
||||
@ -512,11 +503,9 @@ Handle<Code> StubCache::ComputeStoreViaSetter(Handle<Name> name,
|
||||
Handle<JSObject> holder,
|
||||
Handle<JSFunction> setter,
|
||||
StrictModeFlag strict_mode) {
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(
|
||||
Code::STORE_IC, strict_mode, Code::CALLBACKS);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
Handle<Code> stub = FindIC(
|
||||
name, receiver, Code::STORE_IC, Code::CALLBACKS, strict_mode);
|
||||
if (!stub.is_null()) return stub;
|
||||
|
||||
StoreStubCompiler compiler(isolate_, strict_mode);
|
||||
Handle<Code> code =
|
||||
@ -529,11 +518,9 @@ Handle<Code> StubCache::ComputeStoreViaSetter(Handle<Name> name,
|
||||
Handle<Code> StubCache::ComputeStoreInterceptor(Handle<Name> name,
|
||||
Handle<JSObject> receiver,
|
||||
StrictModeFlag strict_mode) {
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(
|
||||
Code::STORE_IC, strict_mode, Code::INTERCEPTOR);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
Handle<Code> stub = FindIC(
|
||||
name, receiver, Code::STORE_IC, Code::INTERCEPTOR, strict_mode);
|
||||
if (!stub.is_null()) return stub;
|
||||
|
||||
StoreStubCompiler compiler(isolate_, strict_mode);
|
||||
Handle<Code> code = compiler.CompileStoreInterceptor(receiver, name);
|
||||
@ -548,11 +535,9 @@ Handle<Code> StubCache::ComputeKeyedStoreField(Handle<Name> name,
|
||||
StrictModeFlag strict_mode) {
|
||||
Code::StubType type =
|
||||
(transition.is_null()) ? Code::FIELD : Code::MAP_TRANSITION;
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(
|
||||
Code::KEYED_STORE_IC, strict_mode, type);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
Handle<Code> stub = FindIC(
|
||||
name, receiver, Code::KEYED_STORE_IC, type, strict_mode);
|
||||
if (!stub.is_null()) return stub;
|
||||
|
||||
KeyedStoreStubCompiler compiler(isolate(), strict_mode, STANDARD_STORE);
|
||||
Handle<Code> code =
|
||||
@ -1452,16 +1437,29 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadField(Handle<JSObject> object,
|
||||
Register reg = HandlerFrontendHeader(object, receiver(), holder, name, &miss);
|
||||
|
||||
LoadFieldStub stub(reg, field.is_inobject(holder), field.translate(holder));
|
||||
GenerateTailCall(stub.GetCode(isolate()));
|
||||
GenerateTailCall(masm(), stub.GetCode(isolate()));
|
||||
|
||||
__ bind(&miss);
|
||||
GenerateLoadMiss(masm(), kind());
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(kind(), Code::FIELD, name);
|
||||
}
|
||||
|
||||
|
||||
// Load a fast property out of a holder object (src). In-object properties
|
||||
// are loaded directly otherwise the property is loaded from the properties
|
||||
// fixed array.
|
||||
void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
|
||||
Register dst,
|
||||
Register src,
|
||||
Handle<JSObject> holder,
|
||||
PropertyIndex index) {
|
||||
DoGenerateFastPropertyLoad(
|
||||
masm, dst, src, index.is_inobject(holder), index.translate(holder));
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> BaseLoadStubCompiler::CompileLoadConstant(
|
||||
Handle<JSObject> object,
|
||||
Handle<JSObject> holder,
|
||||
@ -1527,7 +1525,7 @@ void BaseLoadStubCompiler::GenerateLoadPostInterceptor(
|
||||
LoadFieldStub stub(interceptor_reg,
|
||||
field.is_inobject(holder),
|
||||
field.translate(holder));
|
||||
GenerateTailCall(stub.GetCode(isolate()));
|
||||
GenerateTailCall(masm(), stub.GetCode(isolate()));
|
||||
} else {
|
||||
// We found FIELD property in prototype chain of interceptor's holder.
|
||||
// Retrieve a field from field's holder.
|
||||
@ -1581,9 +1579,45 @@ Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> BaseStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
|
||||
int index,
|
||||
Handle<Map> transition,
|
||||
Handle<Name> name) {
|
||||
Label miss, miss_restore_name;
|
||||
|
||||
GenerateNameCheck(name, this->name(), &miss);
|
||||
|
||||
// Generate store field code.
|
||||
GenerateStoreField(masm(),
|
||||
object,
|
||||
index,
|
||||
transition,
|
||||
name,
|
||||
receiver(), this->name(), value(), scratch1(), scratch2(),
|
||||
&miss,
|
||||
&miss_restore_name);
|
||||
|
||||
// Handle store cache miss.
|
||||
GenerateRestoreName(masm(), &miss_restore_name, name);
|
||||
__ bind(&miss);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetICCode(kind(),
|
||||
transition.is_null() ? Code::FIELD : Code::MAP_TRANSITION,
|
||||
name);
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
|
||||
|
||||
void StubCompiler::TailCallBuiltin(MacroAssembler* masm, Builtins::Name name) {
|
||||
Handle<Code> code(masm->isolate()->builtins()->builtin(name));
|
||||
GenerateTailCall(masm, code);
|
||||
}
|
||||
|
||||
|
||||
void LoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
|
||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
|
||||
}
|
||||
@ -1594,6 +1628,16 @@ void KeyedLoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
|
||||
}
|
||||
|
||||
|
||||
void StoreStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
|
||||
GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
|
||||
}
|
||||
|
||||
|
||||
void KeyedStoreStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
|
||||
GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> BaseLoadStubCompiler::GetICCode(Code::Kind kind,
|
||||
Code::StubType type,
|
||||
Handle<Name> name,
|
||||
@ -1620,6 +1664,32 @@ Handle<Code> BaseLoadStubCompiler::GetCode(Code::Kind kind,
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> BaseStoreStubCompiler::GetICCode(Code::Kind kind,
|
||||
Code::StubType type,
|
||||
Handle<Name> name,
|
||||
InlineCacheState state) {
|
||||
Code::Flags flags = Code::ComputeFlags(
|
||||
kind, state, extra_state(), type);
|
||||
Handle<Code> code = GetCodeWithFlags(flags, name);
|
||||
PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
|
||||
JitEvent(name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> BaseStoreStubCompiler::GetCode(Code::Kind kind,
|
||||
Code::StubType type,
|
||||
Handle<Name> name) {
|
||||
ASSERT(type != Code::NORMAL);
|
||||
Code::Flags flags = Code::ComputeFlags(
|
||||
Code::STUB, MONOMORPHIC, extra_state(), type, kind);
|
||||
Handle<Code> code = GetCodeWithFlags(flags, name);
|
||||
PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
|
||||
JitEvent(name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps,
|
||||
CodeHandleList* handlers) {
|
||||
for (int i = 0; i < receiver_maps->length(); ++i) {
|
||||
@ -1648,31 +1718,6 @@ void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps,
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StoreStubCompiler::GetCode(Code::StubType type,
|
||||
Handle<Name> name) {
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(
|
||||
Code::STORE_IC, strict_mode_, type);
|
||||
Handle<Code> code = GetCodeWithFlags(flags, name);
|
||||
PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
|
||||
GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedStoreStubCompiler::GetCode(Code::StubType type,
|
||||
Handle<Name> name,
|
||||
InlineCacheState state) {
|
||||
Code::ExtraICState extra_state =
|
||||
Code::ComputeExtraICState(store_mode_, strict_mode_);
|
||||
Code::Flags flags =
|
||||
Code::ComputeFlags(Code::KEYED_STORE_IC, state, extra_state, type);
|
||||
Handle<Code> code = GetCodeWithFlags(flags, name);
|
||||
PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name));
|
||||
GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic(
|
||||
MapHandleList* receiver_maps) {
|
||||
// Collect MONOMORPHIC stubs for all |receiver_maps|.
|
||||
@ -1696,7 +1741,7 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic(
|
||||
elements_kind,
|
||||
transitioned_map->elements_kind(),
|
||||
is_js_array,
|
||||
strict_mode_,
|
||||
strict_mode(),
|
||||
store_mode_).GetCode(isolate());
|
||||
} else {
|
||||
cached_stub = KeyedStoreElementStub(
|
||||
|
126
src/stub-cache.h
126
src/stub-cache.h
@ -80,12 +80,15 @@ class StubCache {
|
||||
Handle<Code> FindIC(Handle<Name> name,
|
||||
Handle<JSObject> stub_holder,
|
||||
Code::Kind kind,
|
||||
Code::StubType type);
|
||||
Code::StubType type,
|
||||
Code::ExtraICState extra_state = Code::kNoExtraICState);
|
||||
|
||||
Handle<Code> FindStub(Handle<Name> name,
|
||||
Handle<Code> FindHandler(
|
||||
Handle<Name> name,
|
||||
Handle<JSObject> stub_holder,
|
||||
Code::Kind kind,
|
||||
Code::StubType type);
|
||||
Code::StubType type,
|
||||
Code::ExtraICState extra_state = Code::kNoExtraICState);
|
||||
|
||||
Handle<Code> ComputeMonomorphicIC(Handle<JSObject> receiver,
|
||||
Handle<Code> handler,
|
||||
@ -513,14 +516,23 @@ class StubCompiler BASE_EMBEDDED {
|
||||
Handle<Name> name,
|
||||
Register receiver_reg,
|
||||
Register name_reg,
|
||||
Register value_reg,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
Label* miss_label);
|
||||
Label* miss_label,
|
||||
Label* miss_restore_name);
|
||||
|
||||
static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
|
||||
static void GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind);
|
||||
|
||||
static void GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm);
|
||||
static Builtins::Name MissBuiltin(Code::Kind kind) {
|
||||
switch (kind) {
|
||||
case Code::LOAD_IC: return Builtins::kLoadIC_Miss;
|
||||
case Code::STORE_IC: return Builtins::kStoreIC_Miss;
|
||||
case Code::KEYED_LOAD_IC: return Builtins::kKeyedLoadIC_Miss;
|
||||
case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Miss;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
return Builtins::kLoadIC_Miss;
|
||||
}
|
||||
static void TailCallBuiltin(MacroAssembler* masm, Builtins::Name name);
|
||||
|
||||
// Generates code that verifies that the property holder has not changed
|
||||
// (checking maps of objects in the prototype chain for fast and global
|
||||
@ -577,7 +589,7 @@ class StubCompiler BASE_EMBEDDED {
|
||||
Heap* heap() { return isolate()->heap(); }
|
||||
Factory* factory() { return isolate()->factory(); }
|
||||
|
||||
void GenerateTailCall(Handle<Code> code);
|
||||
static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code);
|
||||
|
||||
private:
|
||||
Isolate* isolate_;
|
||||
@ -739,8 +751,6 @@ class KeyedLoadStubCompiler: public BaseLoadStubCompiler {
|
||||
void CompileElementHandlers(MapHandleList* receiver_maps,
|
||||
CodeHandleList* handlers);
|
||||
|
||||
Handle<Code> CompileLoadElementPolymorphic(MapHandleList* receiver_maps);
|
||||
|
||||
static void GenerateLoadDictionaryElement(MacroAssembler* masm);
|
||||
|
||||
static Register receiver() { return registers()[0]; }
|
||||
@ -760,17 +770,63 @@ class KeyedLoadStubCompiler: public BaseLoadStubCompiler {
|
||||
};
|
||||
|
||||
|
||||
class StoreStubCompiler: public StubCompiler {
|
||||
class BaseStoreStubCompiler: public StubCompiler {
|
||||
public:
|
||||
StoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode)
|
||||
: StubCompiler(isolate), strict_mode_(strict_mode) { }
|
||||
BaseStoreStubCompiler(Isolate* isolate,
|
||||
StrictModeFlag strict_mode,
|
||||
Register* registers)
|
||||
: StubCompiler(isolate),
|
||||
strict_mode_(strict_mode),
|
||||
registers_(registers) { }
|
||||
|
||||
virtual ~BaseStoreStubCompiler() { }
|
||||
|
||||
Handle<Code> CompileStoreField(Handle<JSObject> object,
|
||||
int index,
|
||||
Handle<Map> transition,
|
||||
Handle<Name> name);
|
||||
|
||||
protected:
|
||||
Handle<Code> GetICCode(Code::Kind kind,
|
||||
Code::StubType type,
|
||||
Handle<Name> name,
|
||||
InlineCacheState state = MONOMORPHIC);
|
||||
|
||||
Handle<Code> GetCode(Code::Kind kind,
|
||||
Code::StubType type,
|
||||
Handle<Name> name);
|
||||
|
||||
void GenerateRestoreName(MacroAssembler* masm,
|
||||
Label* label,
|
||||
Handle<Name> name);
|
||||
|
||||
Register receiver() { return registers_[0]; }
|
||||
Register name() { return registers_[1]; }
|
||||
Register value() { return registers_[2]; }
|
||||
Register scratch1() { return registers_[3]; }
|
||||
Register scratch2() { return registers_[4]; }
|
||||
Register scratch3() { return registers_[5]; }
|
||||
StrictModeFlag strict_mode() { return strict_mode_; }
|
||||
virtual Code::ExtraICState extra_state() { return strict_mode_; }
|
||||
|
||||
private:
|
||||
virtual Code::Kind kind() = 0;
|
||||
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) = 0;
|
||||
virtual void JitEvent(Handle<Name> name, Handle<Code> code) = 0;
|
||||
virtual void GenerateNameCheck(Handle<Name> name,
|
||||
Register name_reg,
|
||||
Label* miss) { }
|
||||
StrictModeFlag strict_mode_;
|
||||
Register* registers_;
|
||||
};
|
||||
|
||||
|
||||
class StoreStubCompiler: public BaseStoreStubCompiler {
|
||||
public:
|
||||
StoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode)
|
||||
: BaseStoreStubCompiler(isolate, strict_mode, registers()) { }
|
||||
|
||||
|
||||
Handle<Code> CompileStoreCallback(Handle<Name> name,
|
||||
Handle<JSObject> object,
|
||||
Handle<JSObject> holder,
|
||||
@ -792,26 +848,25 @@ class StoreStubCompiler: public StubCompiler {
|
||||
Handle<Name> name);
|
||||
|
||||
private:
|
||||
Handle<Code> GetCode(Code::StubType type, Handle<Name> name);
|
||||
|
||||
StrictModeFlag strict_mode_;
|
||||
static Register* registers();
|
||||
virtual Code::Kind kind() { return Code::STORE_IC; }
|
||||
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
|
||||
if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
|
||||
return code->ic_state() == MONOMORPHIC
|
||||
? Logger::STORE_IC_TAG : Logger::STORE_POLYMORPHIC_IC_TAG;
|
||||
}
|
||||
virtual void JitEvent(Handle<Name> name, Handle<Code> code);
|
||||
};
|
||||
|
||||
|
||||
class KeyedStoreStubCompiler: public StubCompiler {
|
||||
class KeyedStoreStubCompiler: public BaseStoreStubCompiler {
|
||||
public:
|
||||
KeyedStoreStubCompiler(Isolate* isolate,
|
||||
StrictModeFlag strict_mode,
|
||||
KeyedAccessStoreMode store_mode)
|
||||
: StubCompiler(isolate),
|
||||
strict_mode_(strict_mode),
|
||||
: BaseStoreStubCompiler(isolate, strict_mode, registers()),
|
||||
store_mode_(store_mode) { }
|
||||
|
||||
Handle<Code> CompileStoreField(Handle<JSObject> object,
|
||||
int index,
|
||||
Handle<Map> transition,
|
||||
Handle<Name> name);
|
||||
|
||||
Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
|
||||
|
||||
Handle<Code> CompileStorePolymorphic(MapHandleList* receiver_maps,
|
||||
@ -834,12 +889,23 @@ class KeyedStoreStubCompiler: public StubCompiler {
|
||||
|
||||
static void GenerateStoreDictionaryElement(MacroAssembler* masm);
|
||||
|
||||
private:
|
||||
Handle<Code> GetCode(Code::StubType type,
|
||||
Handle<Name> name,
|
||||
InlineCacheState state = MONOMORPHIC);
|
||||
protected:
|
||||
virtual Code::ExtraICState extra_state() {
|
||||
return Code::ComputeExtraICState(store_mode_, strict_mode());
|
||||
}
|
||||
|
||||
StrictModeFlag strict_mode_;
|
||||
private:
|
||||
static Register* registers();
|
||||
virtual Code::Kind kind() { return Code::KEYED_STORE_IC; }
|
||||
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
|
||||
if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
|
||||
return code->ic_state() == MONOMORPHIC
|
||||
? Logger::KEYED_STORE_IC_TAG : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG;
|
||||
}
|
||||
virtual void JitEvent(Handle<Name> name, Handle<Code> code);
|
||||
virtual void GenerateNameCheck(Handle<Name> name,
|
||||
Register name_reg,
|
||||
Label* miss);
|
||||
KeyedAccessStoreMode store_mode_;
|
||||
};
|
||||
|
||||
|
@ -2403,7 +2403,7 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
StubCompiler::GenerateLoadArrayLength(masm, receiver, r8, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
|
||||
}
|
||||
|
||||
|
||||
@ -2431,7 +2431,7 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r8, r9, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
|
||||
}
|
||||
|
||||
|
||||
@ -2460,7 +2460,7 @@ void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||
StubCompiler::GenerateLoadStringLength(masm, receiver, r8, r9, &miss,
|
||||
support_wrapper_);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
|
||||
}
|
||||
|
||||
|
||||
@ -2523,7 +2523,7 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
__ bind(&miss);
|
||||
|
||||
StubCompiler::GenerateStoreMiss(masm, kind());
|
||||
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1333,8 +1333,7 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
Isolate::Current()->stub_cache()->GenerateProbe(
|
||||
masm, flags, rax, rcx, rbx, rdx);
|
||||
|
||||
// Cache miss: Jump to runtime.
|
||||
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
|
||||
GenerateMiss(masm);
|
||||
}
|
||||
|
||||
|
||||
|
@ -343,19 +343,6 @@ void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
// Load a fast property out of a holder object (src). In-object properties
|
||||
// are loaded directly otherwise the property is loaded from the properties
|
||||
// fixed array.
|
||||
void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
|
||||
Register dst,
|
||||
Register src,
|
||||
Handle<JSObject> holder,
|
||||
PropertyIndex index) {
|
||||
DoGenerateFastPropertyLoad(
|
||||
masm, dst, src, index.is_inobject(holder), index.translate(holder));
|
||||
}
|
||||
|
||||
|
||||
void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm,
|
||||
Register dst,
|
||||
Register src,
|
||||
@ -715,28 +702,13 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
};
|
||||
|
||||
|
||||
void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
|
||||
ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
|
||||
Handle<Code> code = (kind == Code::LOAD_IC)
|
||||
? masm->isolate()->builtins()->LoadIC_Miss()
|
||||
: masm->isolate()->builtins()->KeyedLoadIC_Miss();
|
||||
__ Jump(code, RelocInfo::CODE_TARGET);
|
||||
void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
|
||||
Label* label,
|
||||
Handle<Name> name) {
|
||||
if (!label->is_unused()) {
|
||||
__ bind(label);
|
||||
__ Move(this->name(), name);
|
||||
}
|
||||
|
||||
|
||||
void StubCompiler::GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind) {
|
||||
ASSERT(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC);
|
||||
Handle<Code> code = (kind == Code::STORE_IC)
|
||||
? masm->isolate()->builtins()->StoreIC_Miss()
|
||||
: masm->isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ Jump(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
|
||||
Handle<Code> code =
|
||||
masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
|
||||
__ Jump(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
@ -749,9 +721,11 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
Handle<Name> name,
|
||||
Register receiver_reg,
|
||||
Register name_reg,
|
||||
Register value_reg,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
Label* miss_label) {
|
||||
Label* miss_label,
|
||||
Label* miss_restore_name) {
|
||||
LookupResult lookup(masm->isolate());
|
||||
object->Lookup(*name, &lookup);
|
||||
if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) {
|
||||
@ -785,17 +759,8 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
holder = JSObject::cast(holder->GetPrototype());
|
||||
} while (holder->GetPrototype()->IsJSObject());
|
||||
}
|
||||
// We need an extra register, push
|
||||
__ push(name_reg);
|
||||
Label miss_pop, done_check;
|
||||
CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
|
||||
scratch1, scratch2, name, &miss_pop);
|
||||
__ jmp(&done_check);
|
||||
__ bind(&miss_pop);
|
||||
__ pop(name_reg);
|
||||
__ jmp(miss_label);
|
||||
__ bind(&done_check);
|
||||
__ pop(name_reg);
|
||||
scratch1, scratch2, name, miss_restore_name);
|
||||
}
|
||||
|
||||
// Stub never generated for non-global objects that require access
|
||||
@ -809,7 +774,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
__ pop(scratch1); // Return address.
|
||||
__ push(receiver_reg);
|
||||
__ Push(transition);
|
||||
__ push(rax);
|
||||
__ push(value_reg);
|
||||
__ push(scratch1);
|
||||
__ TailCallExternalReference(
|
||||
ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
|
||||
@ -843,11 +808,11 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
if (index < 0) {
|
||||
// Set the property straight into the object.
|
||||
int offset = object->map()->instance_size() + (index * kPointerSize);
|
||||
__ movq(FieldOperand(receiver_reg, offset), rax);
|
||||
__ movq(FieldOperand(receiver_reg, offset), value_reg);
|
||||
|
||||
// Update the write barrier for the array address.
|
||||
// Pass the value being stored in the now unused name_reg.
|
||||
__ movq(name_reg, rax);
|
||||
__ movq(name_reg, value_reg);
|
||||
__ RecordWriteField(
|
||||
receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs);
|
||||
} else {
|
||||
@ -855,16 +820,17 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
||||
int offset = index * kPointerSize + FixedArray::kHeaderSize;
|
||||
// Get the properties array (optimistically).
|
||||
__ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
|
||||
__ movq(FieldOperand(scratch1, offset), rax);
|
||||
__ movq(FieldOperand(scratch1, offset), value_reg);
|
||||
|
||||
// Update the write barrier for the array address.
|
||||
// Pass the value being stored in the now unused name_reg.
|
||||
__ movq(name_reg, rax);
|
||||
__ movq(name_reg, value_reg);
|
||||
__ RecordWriteField(
|
||||
scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs);
|
||||
}
|
||||
|
||||
// Return the value (register rax).
|
||||
ASSERT(value_reg.is(rax));
|
||||
__ ret(0);
|
||||
}
|
||||
|
||||
@ -908,15 +874,16 @@ static void GenerateCheckPropertyCells(MacroAssembler* masm,
|
||||
}
|
||||
}
|
||||
|
||||
#undef __
|
||||
#define __ ACCESS_MASM((masm()))
|
||||
|
||||
|
||||
void StubCompiler::GenerateTailCall(Handle<Code> code) {
|
||||
void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
|
||||
__ jmp(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
#define __ ACCESS_MASM((masm()))
|
||||
|
||||
|
||||
Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
|
||||
Register object_reg,
|
||||
Handle<JSObject> holder,
|
||||
@ -1039,7 +1006,7 @@ void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success,
|
||||
if (!miss->is_unused()) {
|
||||
__ jmp(success);
|
||||
__ bind(miss);
|
||||
GenerateLoadMiss(masm(), kind());
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2408,39 +2375,6 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
|
||||
int index,
|
||||
Handle<Map> transition,
|
||||
Handle<Name> name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : value
|
||||
// -- rcx : name
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
// Generate store field code. Preserves receiver and name on jump to miss.
|
||||
GenerateStoreField(masm(),
|
||||
object,
|
||||
index,
|
||||
transition,
|
||||
name,
|
||||
rdx, rcx, rbx, rdi,
|
||||
&miss);
|
||||
|
||||
// Handle store cache miss.
|
||||
__ bind(&miss);
|
||||
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(transition.is_null()
|
||||
? Code::FIELD
|
||||
: Code::MAP_TRANSITION, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StoreStubCompiler::CompileStoreCallback(
|
||||
Handle<Name> name,
|
||||
Handle<JSObject> receiver,
|
||||
@ -2474,11 +2408,10 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
|
||||
|
||||
// Handle store cache miss.
|
||||
__ bind(&miss);
|
||||
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::CALLBACKS, name);
|
||||
return GetICCode(kind(), Code::CALLBACKS, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2548,11 +2481,10 @@ Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
|
||||
GenerateStoreViaSetter(masm(), setter);
|
||||
|
||||
__ bind(&miss);
|
||||
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::CALLBACKS, name);
|
||||
return GetICCode(kind(), Code::CALLBACKS, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2584,7 +2516,7 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
|
||||
__ push(rdx); // receiver
|
||||
__ push(rcx); // name
|
||||
__ push(rax); // value
|
||||
__ Push(Smi::FromInt(strict_mode_));
|
||||
__ Push(Smi::FromInt(strict_mode()));
|
||||
__ push(rbx); // restore return address
|
||||
|
||||
// Do tail-call to the runtime system.
|
||||
@ -2594,11 +2526,10 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
|
||||
|
||||
// Handle store cache miss.
|
||||
__ bind(&miss);
|
||||
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::INTERCEPTOR, name);
|
||||
return GetICCode(kind(), Code::INTERCEPTOR, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2642,52 +2573,10 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
|
||||
// Handle store cache miss.
|
||||
__ bind(&miss);
|
||||
__ IncrementCounter(counters->named_store_global_inline_miss(), 1);
|
||||
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::NORMAL, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
|
||||
int index,
|
||||
Handle<Map> transition,
|
||||
Handle<Name> name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : value
|
||||
// -- rcx : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
Counters* counters = isolate()->counters();
|
||||
__ IncrementCounter(counters->keyed_store_field(), 1);
|
||||
|
||||
// Check that the name has not changed.
|
||||
__ Cmp(rcx, name);
|
||||
__ j(not_equal, &miss);
|
||||
|
||||
// Generate store field code. Preserves receiver and name on jump to miss.
|
||||
GenerateStoreField(masm(),
|
||||
object,
|
||||
index,
|
||||
transition,
|
||||
name,
|
||||
rdx, rcx, rbx, rdi,
|
||||
&miss);
|
||||
|
||||
// Handle store cache miss.
|
||||
__ bind(&miss);
|
||||
__ DecrementCounter(counters->keyed_store_field(), 1);
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(transition.is_null()
|
||||
? Code::FIELD
|
||||
: Code::MAP_TRANSITION, name);
|
||||
return GetICCode(kind(), Code::NORMAL, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2709,11 +2598,10 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
|
||||
|
||||
__ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::NORMAL, factory()->empty_string());
|
||||
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
|
||||
}
|
||||
|
||||
|
||||
@ -2747,11 +2635,12 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
|
||||
}
|
||||
|
||||
__ bind(&miss);
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
|
||||
return GetICCode(
|
||||
kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
|
||||
}
|
||||
|
||||
|
||||
@ -2789,6 +2678,20 @@ Register* KeyedLoadStubCompiler::registers() {
|
||||
}
|
||||
|
||||
|
||||
Register* StoreStubCompiler::registers() {
|
||||
// receiver, name, value, scratch1, scratch2, scratch3.
|
||||
static Register registers[] = { rdx, rcx, rax, rbx, rdi, r8 };
|
||||
return registers;
|
||||
}
|
||||
|
||||
|
||||
Register* KeyedStoreStubCompiler::registers() {
|
||||
// receiver, name, value, scratch1, scratch2, scratch3.
|
||||
static Register registers[] = { rdx, rcx, rax, rbx, rdi, r8 };
|
||||
return registers;
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
|
||||
Register name_reg,
|
||||
Label* miss) {
|
||||
@ -2797,6 +2700,14 @@ void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
|
||||
}
|
||||
|
||||
|
||||
void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
|
||||
Register name_reg,
|
||||
Label* miss) {
|
||||
__ Cmp(name_reg, name);
|
||||
__ j(not_equal, miss);
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
@ -2895,7 +2806,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
|
||||
__ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
|
||||
}
|
||||
|
||||
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
||||
TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss);
|
||||
|
||||
// Return the generated code.
|
||||
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
|
||||
@ -2925,7 +2836,7 @@ Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
|
||||
}
|
||||
|
||||
__ bind(&miss);
|
||||
GenerateLoadMiss(masm(), kind());
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
// Return the generated code.
|
||||
InlineCacheState state =
|
||||
@ -3101,9 +3012,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
Handle<Code> slow_ic =
|
||||
masm->isolate()->builtins()->KeyedLoadIC_Slow();
|
||||
__ jmp(slow_ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
|
||||
|
||||
__ bind(&miss_force_generic);
|
||||
// ----------- S t a t e -------------
|
||||
@ -3111,9 +3020,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
Handle<Code> miss_ic =
|
||||
masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
|
||||
__ jmp(miss_ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric);
|
||||
}
|
||||
|
||||
|
||||
@ -3311,9 +3218,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
|
||||
Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
|
||||
__ jmp(ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
|
||||
|
||||
// Miss case: call runtime.
|
||||
__ bind(&miss_force_generic);
|
||||
@ -3324,10 +3229,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
|
||||
Handle<Code> miss_ic =
|
||||
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
|
||||
__ jmp(miss_ic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
|
||||
}
|
||||
|
||||
|
||||
@ -3396,13 +3298,10 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
|
||||
|
||||
// Handle store cache miss.
|
||||
__ bind(&miss_force_generic);
|
||||
Handle<Code> ic_force_generic =
|
||||
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
|
||||
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
|
||||
|
||||
__ bind(&transition_elements_kind);
|
||||
Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ jmp(ic_miss, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
|
||||
|
||||
if (is_js_array && IsGrowStoreMode(store_mode)) {
|
||||
// Grow the array by a single element if possible.
|
||||
@ -3468,8 +3367,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
|
||||
__ jmp(&finish_store);
|
||||
|
||||
__ bind(&slow);
|
||||
Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
|
||||
__ jmp(ic_slow, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3519,16 +3417,13 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
|
||||
|
||||
// Handle store cache miss, replacing the ic with the generic stub.
|
||||
__ bind(&miss_force_generic);
|
||||
Handle<Code> ic_force_generic =
|
||||
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
|
||||
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
|
||||
|
||||
__ bind(&restore_key_transition_elements_kind);
|
||||
// Restore smi-tagging of rcx.
|
||||
__ Integer32ToSmi(rcx, rcx);
|
||||
__ bind(&transition_elements_kind);
|
||||
Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
|
||||
__ jmp(ic_miss, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
|
||||
|
||||
if (is_js_array && IsGrowStoreMode(store_mode)) {
|
||||
// Grow the array by a single element if possible.
|
||||
@ -3602,8 +3497,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
|
||||
__ jmp(&finish_store);
|
||||
|
||||
__ bind(&slow);
|
||||
Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
|
||||
__ jmp(ic_slow, RelocInfo::CODE_TARGET);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user