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:
verwaest@chromium.org 2013-03-13 14:11:05 +00:00
parent 8db737a583
commit 569d9c59b9
10 changed files with 454 additions and 656 deletions

View File

@ -4513,7 +4513,7 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
StubCompiler::GenerateLoadArrayLength(masm, receiver, r3, &miss); StubCompiler::GenerateLoadArrayLength(masm, receiver, r3, &miss);
__ bind(&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); StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r3, r4, &miss);
__ bind(&miss); __ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, kind()); StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
} }
@ -4573,7 +4573,7 @@ void StringLengthStub::Generate(MacroAssembler* masm) {
support_wrapper_); support_wrapper_);
__ bind(&miss); __ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, kind()); StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
} }
@ -4643,7 +4643,7 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
__ bind(&miss); __ bind(&miss);
StubCompiler::GenerateStoreMiss(masm, kind()); StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
} }

View File

@ -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, void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm,
Register dst, Register dst,
Register src, Register src,
@ -446,9 +433,11 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
Handle<Name> name, Handle<Name> name,
Register receiver_reg, Register receiver_reg,
Register name_reg, Register name_reg,
Register value_reg,
Register scratch1, Register scratch1,
Register scratch2, Register scratch2,
Label* miss_label) { Label* miss_label,
Label* miss_restore_name) {
// r0 : value // r0 : value
Label exit; Label exit;
@ -485,17 +474,8 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
holder = JSObject::cast(holder->GetPrototype()); holder = JSObject::cast(holder->GetPrototype());
} while (holder->GetPrototype()->IsJSObject()); } 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, CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
scratch1, scratch2, name, &miss_pop); scratch1, scratch2, name, miss_restore_name);
__ jmp(&done_check);
__ bind(&miss_pop);
__ pop(name_reg);
__ jmp(miss_label);
__ bind(&done_check);
__ pop(name_reg);
} }
// Stub never generated for non-global objects that require access // Stub never generated for non-global objects that require access
@ -542,14 +522,14 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
if (index < 0) { if (index < 0) {
// Set the property straight into the object. // Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize); 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. // Skip updating write barrier if storing a smi.
__ JumpIfSmi(r0, &exit); __ JumpIfSmi(value_reg, &exit);
// Update the write barrier for the array address. // Update the write barrier for the array address.
// Pass the now unused name_reg as a scratch register. // Pass the now unused name_reg as a scratch register.
__ mov(name_reg, r0); __ mov(name_reg, value_reg);
__ RecordWriteField(receiver_reg, __ RecordWriteField(receiver_reg,
offset, offset,
name_reg, name_reg,
@ -562,14 +542,14 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
// Get the properties array // Get the properties array
__ ldr(scratch1, __ ldr(scratch1,
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
__ str(r0, FieldMemOperand(scratch1, offset)); __ str(value_reg, FieldMemOperand(scratch1, offset));
// Skip updating write barrier if storing a smi. // Skip updating write barrier if storing a smi.
__ JumpIfSmi(r0, &exit); __ JumpIfSmi(value_reg, &exit);
// Update the write barrier for the array address. // Update the write barrier for the array address.
// Ok to clobber receiver_reg and name_reg, since we return. // Ok to clobber receiver_reg and name_reg, since we return.
__ mov(name_reg, r0); __ mov(name_reg, value_reg);
__ RecordWriteField(scratch1, __ RecordWriteField(scratch1,
offset, offset,
name_reg, name_reg,
@ -579,26 +559,19 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
} }
// Return the value (register r0). // Return the value (register r0).
ASSERT(value_reg.is(r0));
__ bind(&exit); __ bind(&exit);
__ Ret(); __ Ret();
} }
void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); Label* label,
Handle<Code> code = (kind == Code::LOAD_IC) Handle<Name> name) {
? masm->isolate()->builtins()->LoadIC_Miss() if (!label->is_unused()) {
: masm->isolate()->builtins()->KeyedLoadIC_Miss(); __ bind(label);
__ Jump(code, RelocInfo::CODE_TARGET); __ 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 __ void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
#define __ ACCESS_MASM(masm())
void StubCompiler::GenerateTailCall(Handle<Code> code) {
__ Jump(code, RelocInfo::CODE_TARGET); __ Jump(code, RelocInfo::CODE_TARGET);
} }
#undef __
#define __ ACCESS_MASM(masm())
Register StubCompiler::CheckPrototypes(Handle<JSObject> object, Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
Register object_reg, Register object_reg,
Handle<JSObject> holder, Handle<JSObject> holder,
@ -1190,7 +1163,7 @@ void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success,
if (!miss->is_unused()) { if (!miss->is_unused()) {
__ b(success); __ b(success);
__ bind(miss); __ 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<Code> StoreStubCompiler::CompileStoreCallback(
Handle<Name> name, Handle<Name> name,
Handle<JSObject> receiver, Handle<JSObject> receiver,
@ -2660,11 +2603,10 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
// Handle store cache miss. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);
Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // 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); GenerateStoreViaSetter(masm(), setter);
__ bind(&miss); __ bind(&miss);
Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // 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. __ 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 __ push(r0); // strict mode
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
@ -2778,11 +2719,10 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
// Handle store cache miss. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);
Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // 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. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);
__ IncrementCounter(counters->named_store_global_inline_miss(), 1, r4, r3); __ IncrementCounter(counters->named_store_global_inline_miss(), 1, r4, r3);
Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // 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, void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
Register name_reg, Register name_reg,
Label* miss) { 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 __ #undef __
#define __ ACCESS_MASM(masm) #define __ ACCESS_MASM(masm)
@ -2968,8 +2929,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
__ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK); __ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK);
} }
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // Return the generated code.
return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
@ -3000,7 +2960,7 @@ Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
} }
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), kind()); TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code. // Return the generated code.
InlineCacheState state = 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<Code> KeyedStoreStubCompiler::CompileStoreElement(
Handle<Map> receiver_map) { Handle<Map> receiver_map) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
@ -3068,11 +2987,10 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
__ DispatchMap(r2, r3, receiver_map, stub, DO_SMI_CHECK); __ DispatchMap(r2, r3, receiver_map, stub, DO_SMI_CHECK);
Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // 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); __ bind(&miss);
Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
// Return the generated code. // 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 // -- r0 : key
// -- r1 : receiver // -- r1 : receiver
// ----------------------------------- // -----------------------------------
Handle<Code> slow_ic = TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
masm->isolate()->builtins()->KeyedLoadIC_Slow();
__ Jump(slow_ic, RelocInfo::CODE_TARGET);
// Miss case, call the runtime. // Miss case, call the runtime.
__ bind(&miss_force_generic); __ bind(&miss_force_generic);
@ -3304,10 +3220,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
// -- r0 : key // -- r0 : key
// -- r1 : receiver // -- r1 : receiver
// ----------------------------------- // -----------------------------------
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric);
Handle<Code> miss_ic =
masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
__ Jump(miss_ic, RelocInfo::CODE_TARGET);
} }
@ -3699,9 +3612,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
// -- r0 : key // -- r0 : key
// -- r1 : receiver // -- r1 : receiver
// ----------------------------------- // -----------------------------------
Handle<Code> slow_ic = TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
masm->isolate()->builtins()->KeyedStoreIC_Slow();
__ Jump(slow_ic, RelocInfo::CODE_TARGET);
// Miss case, call the runtime. // Miss case, call the runtime.
__ bind(&miss_force_generic); __ bind(&miss_force_generic);
@ -3711,10 +3622,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
// -- r0 : key // -- r0 : key
// -- r1 : receiver // -- r1 : receiver
// ----------------------------------- // -----------------------------------
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
Handle<Code> miss_ic =
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ Jump(miss_ic, RelocInfo::CODE_TARGET);
} }
@ -3807,13 +3715,10 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
__ Ret(); __ Ret();
__ bind(&miss_force_generic); __ bind(&miss_force_generic);
Handle<Code> ic = TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ Jump(ic, RelocInfo::CODE_TARGET);
__ bind(&transition_elements_kind); __ bind(&transition_elements_kind);
Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
__ Jump(ic_miss, RelocInfo::CODE_TARGET);
if (is_js_array && IsGrowStoreMode(store_mode)) { if (is_js_array && IsGrowStoreMode(store_mode)) {
// Grow the array by a single element if possible. // Grow the array by a single element if possible.
@ -3878,8 +3783,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
__ jmp(&finish_store); __ jmp(&finish_store);
__ bind(&slow); __ bind(&slow);
Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
__ Jump(ic_slow, RelocInfo::CODE_TARGET);
} }
} }
@ -3953,13 +3857,10 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
// Handle store cache miss, replacing the ic with the generic stub. // Handle store cache miss, replacing the ic with the generic stub.
__ bind(&miss_force_generic); __ bind(&miss_force_generic);
Handle<Code> ic = TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ Jump(ic, RelocInfo::CODE_TARGET);
__ bind(&transition_elements_kind); __ bind(&transition_elements_kind);
Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
__ Jump(ic_miss, RelocInfo::CODE_TARGET);
if (is_js_array && IsGrowStoreMode(store_mode)) { if (is_js_array && IsGrowStoreMode(store_mode)) {
// Grow the array by a single element if possible. // Grow the array by a single element if possible.
@ -4044,8 +3945,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
__ jmp(&finish_store); __ jmp(&finish_store);
__ bind(&slow); __ bind(&slow);
Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
__ Jump(ic_slow, RelocInfo::CODE_TARGET);
} }
} }

View File

@ -3301,7 +3301,7 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
StubCompiler::GenerateLoadArrayLength(masm, edx, eax, &miss); StubCompiler::GenerateLoadArrayLength(masm, edx, eax, &miss);
__ bind(&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); StubCompiler::GenerateLoadFunctionPrototype(masm, edx, eax, ebx, &miss);
__ bind(&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, StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss,
support_wrapper_); support_wrapper_);
__ bind(&miss); __ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, kind()); StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
} }
@ -3404,7 +3404,7 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
__ bind(&miss); __ bind(&miss);
StubCompiler::GenerateStoreMiss(masm, kind()); StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
} }

View File

@ -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, void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm,
Register dst, Register dst,
Register src, Register src,
@ -729,28 +716,13 @@ class CallInterceptorCompiler BASE_EMBEDDED {
}; };
void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); Label* label,
Handle<Code> code = (kind == Code::LOAD_IC) Handle<Name> name) {
? masm->isolate()->builtins()->LoadIC_Miss() if (!label->is_unused()) {
: masm->isolate()->builtins()->KeyedLoadIC_Miss(); __ bind(label);
__ jmp(code, RelocInfo::CODE_TARGET); __ 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, Handle<Name> name,
Register receiver_reg, Register receiver_reg,
Register name_reg, Register name_reg,
Register value_reg,
Register scratch1, Register scratch1,
Register scratch2, Register scratch2,
Label* miss_label) { Label* miss_label,
Label* miss_restore_name) {
LookupResult lookup(masm->isolate()); LookupResult lookup(masm->isolate());
object->Lookup(*name, &lookup); object->Lookup(*name, &lookup);
if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) { if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) {
@ -800,16 +774,8 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
} while (holder->GetPrototype()->IsJSObject()); } while (holder->GetPrototype()->IsJSObject());
} }
// We need an extra register, push // We need an extra register, push
__ push(name_reg);
Label miss_pop, done_check;
CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
scratch1, scratch2, name, &miss_pop); scratch1, scratch2, name, miss_restore_name);
__ jmp(&done_check);
__ bind(&miss_pop);
__ pop(name_reg);
__ jmp(miss_label);
__ bind(&done_check);
__ pop(name_reg);
} }
// Stub never generated for non-global objects that require access // Stub never generated for non-global objects that require access
@ -857,11 +823,11 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
if (index < 0) { if (index < 0) {
// Set the property straight into the object. // Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize); 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. // Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg. // Pass the value being stored in the now unused name_reg.
__ mov(name_reg, eax); __ mov(name_reg, value_reg);
__ RecordWriteField(receiver_reg, __ RecordWriteField(receiver_reg,
offset, offset,
name_reg, name_reg,
@ -876,7 +842,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
// Update the write barrier for the array address. // Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg. // Pass the value being stored in the now unused name_reg.
__ mov(name_reg, eax); __ mov(name_reg, value_reg);
__ RecordWriteField(scratch1, __ RecordWriteField(scratch1,
offset, offset,
name_reg, name_reg,
@ -885,6 +851,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
} }
// Return the value (register eax). // Return the value (register eax).
ASSERT(value_reg.is(eax));
__ ret(0); __ ret(0);
} }
@ -933,15 +900,16 @@ static void GenerateCheckPropertyCells(MacroAssembler* masm,
} }
} }
#undef __
#define __ ACCESS_MASM(masm())
void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
void StubCompiler::GenerateTailCall(Handle<Code> code) {
__ jmp(code, RelocInfo::CODE_TARGET); __ jmp(code, RelocInfo::CODE_TARGET);
} }
#undef __
#define __ ACCESS_MASM(masm())
Register StubCompiler::CheckPrototypes(Handle<JSObject> object, Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
Register object_reg, Register object_reg,
Handle<JSObject> holder, Handle<JSObject> holder,
@ -1062,7 +1030,7 @@ void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success,
if (!miss->is_unused()) { if (!miss->is_unused()) {
__ jmp(success); __ jmp(success);
__ bind(miss); __ 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<Code> StoreStubCompiler::CompileStoreCallback(
Handle<Name> name, Handle<Name> name,
Handle<JSObject> receiver, Handle<JSObject> receiver,
@ -2650,11 +2585,10 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
// Handle store cache miss. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);
__ pop(eax); __ pop(eax);
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ jmp(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // 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); __ bind(&miss);
__ pop(ecx); __ pop(ecx);
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ jmp(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // 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(edx); // receiver
__ push(ecx); // name __ push(ecx); // name
__ push(eax); // value __ push(eax); // value
__ push(Immediate(Smi::FromInt(strict_mode_))); __ push(Immediate(Smi::FromInt(strict_mode())));
__ push(ebx); // restore return address __ push(ebx); // restore return address
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
@ -2773,11 +2706,10 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
// Handle store cache miss. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ jmp(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // 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. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);
__ IncrementCounter(counters->named_store_global_inline_miss(), 1); __ IncrementCounter(counters->named_store_global_inline_miss(), 1);
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ jmp(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // Return the generated code.
return GetCode(Code::NORMAL, name); return GetICCode(kind(), 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);
} }
@ -2887,11 +2777,10 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
__ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ jmp(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // 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); __ bind(&miss);
Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ jmp(miss_ic, RelocInfo::CODE_TARGET);
// Return the generated code. // 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, void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
Register name_reg, Register name_reg,
Label* miss) { 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 __ #undef __
#define __ ACCESS_MASM(masm) #define __ ACCESS_MASM(masm)
@ -3071,7 +2982,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
__ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
} }
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss);
// Return the generated code. // Return the generated code.
return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
@ -3100,7 +3011,7 @@ Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
} }
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), kind()); TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code. // Return the generated code.
InlineCacheState state = InlineCacheState state =
@ -3284,10 +3195,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
// -- edx : receiver // -- edx : receiver
// -- esp[0] : return address // -- esp[0] : return address
// ----------------------------------- // -----------------------------------
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
Handle<Code> slow_ic =
masm->isolate()->builtins()->KeyedLoadIC_Slow();
__ jmp(slow_ic, RelocInfo::CODE_TARGET);
__ bind(&miss_force_generic); __ bind(&miss_force_generic);
// ----------- S t a t e ------------- // ----------- S t a t e -------------
@ -3295,10 +3203,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
// -- edx : receiver // -- edx : receiver
// -- esp[0] : return address // -- esp[0] : return address
// ----------------------------------- // -----------------------------------
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric);
Handle<Code> miss_force_generic_ic =
masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
__ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET);
} }
@ -3516,9 +3421,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
// -- edx : receiver // -- edx : receiver
// -- esp[0] : return address // -- esp[0] : return address
// ----------------------------------- // -----------------------------------
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
__ jmp(ic, RelocInfo::CODE_TARGET);
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : value // -- eax : value
@ -3528,9 +3431,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
// ----------------------------------- // -----------------------------------
__ bind(&miss_force_generic); __ bind(&miss_force_generic);
Handle<Code> miss_ic = TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ jmp(miss_ic, RelocInfo::CODE_TARGET);
} }
@ -3606,14 +3507,11 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
// Handle store cache miss, replacing the ic with the generic stub. // Handle store cache miss, replacing the ic with the generic stub.
__ bind(&miss_force_generic); __ bind(&miss_force_generic);
Handle<Code> ic_force_generic = TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
// Handle transition to other elements kinds without using the generic stub. // Handle transition to other elements kinds without using the generic stub.
__ bind(&transition_elements_kind); __ bind(&transition_elements_kind);
Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
__ jmp(ic_miss, RelocInfo::CODE_TARGET);
if (is_js_array && IsGrowStoreMode(store_mode)) { if (is_js_array && IsGrowStoreMode(store_mode)) {
// Handle transition requiring the array to grow. // Handle transition requiring the array to grow.
@ -3684,8 +3582,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
__ mov(ecx, Immediate(0)); __ mov(ecx, Immediate(0));
__ bind(&slow); __ bind(&slow);
Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
__ jmp(ic_slow, RelocInfo::CODE_TARGET);
} }
} }
@ -3734,14 +3631,11 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
// Handle store cache miss, replacing the ic with the generic stub. // Handle store cache miss, replacing the ic with the generic stub.
__ bind(&miss_force_generic); __ bind(&miss_force_generic);
Handle<Code> ic_force_generic = TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
// Handle transition to other elements kinds without using the generic stub. // Handle transition to other elements kinds without using the generic stub.
__ bind(&transition_elements_kind); __ bind(&transition_elements_kind);
Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
__ jmp(ic_miss, RelocInfo::CODE_TARGET);
if (is_js_array && IsGrowStoreMode(store_mode)) { if (is_js_array && IsGrowStoreMode(store_mode)) {
// Handle transition requiring the array to grow. // Handle transition requiring the array to grow.
@ -3822,8 +3716,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
__ mov(ecx, Immediate(0)); __ mov(ecx, Immediate(0));
__ bind(&slow); __ bind(&slow);
Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
__ jmp(ic_slow, RelocInfo::CODE_TARGET);
} }
} }

View File

@ -139,6 +139,7 @@ class PositionsRecorder;
V(REG_EXP_TAG, "RegExp") \ V(REG_EXP_TAG, "RegExp") \
V(SCRIPT_TAG, "Script") \ V(SCRIPT_TAG, "Script") \
V(STORE_IC_TAG, "StoreIC") \ V(STORE_IC_TAG, "StoreIC") \
V(STORE_POLYMORPHIC_IC_TAG, "StorePolymorphicIC") \
V(STUB_TAG, "Stub") \ V(STUB_TAG, "Stub") \
V(NATIVE_FUNCTION_TAG, "Function") \ V(NATIVE_FUNCTION_TAG, "Function") \
V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile") \ V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile") \

View File

@ -112,9 +112,9 @@ Handle<JSObject> StubCache::StubHolder(Handle<JSObject> receiver,
Handle<Code> StubCache::FindIC(Handle<Name> name, Handle<Code> StubCache::FindIC(Handle<Name> name,
Handle<JSObject> stub_holder, Handle<JSObject> stub_holder,
Code::Kind kind, Code::Kind kind,
Code::StubType type) { Code::StubType type,
Code::Flags flags = Code::ComputeMonomorphicFlags( Code::ExtraICState extra_ic_state) {
kind, Code::kNoExtraICState, type); Code::Flags flags = Code::ComputeMonomorphicFlags(kind, extra_ic_state, type);
Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
isolate_); isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe); 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, Handle<JSObject> stub_holder,
Code::Kind kind, Code::Kind kind,
Code::StubType type) { Code::StubType type,
Code::ExtraICState extra_ic_state) {
ASSERT(type != Code::NORMAL); 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( 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), Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
isolate_); isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe); 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 // Compile the stub that is either shared for all names or
// name specific if there are global objects involved. // name specific if there are global objects involved.
Handle<Code> handler = FindStub( Handle<Code> handler = FindHandler(
cache_name, receiver, Code::LOAD_IC, Code::NONEXISTENT); cache_name, receiver, Code::LOAD_IC, Code::NONEXISTENT);
if (!handler.is_null()) return handler; 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<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindStub( Handle<Code> stub = FindHandler(
name, stub_holder, Code::LOAD_IC, Code::FIELD); name, stub_holder, Code::LOAD_IC, Code::FIELD);
if (!stub.is_null()) return stub; if (!stub.is_null()) return stub;
@ -240,7 +236,7 @@ Handle<Code> StubCache::ComputeLoadCallback(
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
ASSERT(v8::ToCData<Address>(callback->getter()) != 0); ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
Handle<JSObject> stub_holder = StubHolder(receiver, holder); Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindStub( Handle<Code> stub = FindHandler(
name, stub_holder, Code::LOAD_IC, Code::CALLBACKS); name, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
if (!stub.is_null()) return stub; if (!stub.is_null()) return stub;
@ -257,7 +253,7 @@ Handle<Code> StubCache::ComputeLoadViaGetter(Handle<Name> name,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<JSFunction> getter) { Handle<JSFunction> getter) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder); Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindStub( Handle<Code> stub = FindHandler(
name, stub_holder, Code::LOAD_IC, Code::CALLBACKS); name, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
if (!stub.is_null()) return stub; if (!stub.is_null()) return stub;
@ -274,7 +270,7 @@ Handle<Code> StubCache::ComputeLoadConstant(Handle<Name> name,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<JSFunction> value) { Handle<JSFunction> value) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder); Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> handler = FindStub( Handle<Code> handler = FindHandler(
name, stub_holder, Code::LOAD_IC, Code::CONSTANT_FUNCTION); name, stub_holder, Code::LOAD_IC, Code::CONSTANT_FUNCTION);
if (!handler.is_null()) return handler; if (!handler.is_null()) return handler;
@ -290,7 +286,7 @@ Handle<Code> StubCache::ComputeLoadInterceptor(Handle<Name> name,
Handle<JSObject> receiver, Handle<JSObject> receiver,
Handle<JSObject> holder) { Handle<JSObject> holder) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder); Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindStub( Handle<Code> stub = FindHandler(
name, stub_holder, Code::LOAD_IC, Code::INTERCEPTOR); name, stub_holder, Code::LOAD_IC, Code::INTERCEPTOR);
if (!stub.is_null()) return stub; 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<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindStub( Handle<Code> stub = FindHandler(
name, stub_holder, Code::KEYED_LOAD_IC, Code::FIELD); name, stub_holder, Code::KEYED_LOAD_IC, Code::FIELD);
if (!stub.is_null()) return stub; if (!stub.is_null()) return stub;
@ -354,7 +350,7 @@ Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<Name> name,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<JSFunction> value) { Handle<JSFunction> value) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder); 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); name, stub_holder, Code::KEYED_LOAD_IC, Code::CONSTANT_FUNCTION);
if (!handler.is_null()) return handler; if (!handler.is_null()) return handler;
@ -369,7 +365,7 @@ Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<Name> name,
Handle<JSObject> receiver, Handle<JSObject> receiver,
Handle<JSObject> holder) { Handle<JSObject> holder) {
Handle<JSObject> stub_holder = StubHolder(receiver, 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); name, stub_holder, Code::KEYED_LOAD_IC, Code::INTERCEPTOR);
if (!stub.is_null()) return stub; if (!stub.is_null()) return stub;
@ -387,7 +383,7 @@ Handle<Code> StubCache::ComputeKeyedLoadCallback(
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder); Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> stub = FindStub( Handle<Code> stub = FindHandler(
name, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS); name, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS);
if (!stub.is_null()) return stub; if (!stub.is_null()) return stub;
@ -405,12 +401,11 @@ Handle<Code> StubCache::ComputeStoreField(Handle<Name> name,
Handle<Map> transition, Handle<Map> transition,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode) {
Code::StubType type = Code::StubType type =
(transition.is_null()) ? Code::FIELD : Code::MAP_TRANSITION; transition.is_null() ? Code::FIELD : Code::MAP_TRANSITION;
Code::Flags flags = Code::ComputeMonomorphicFlags(
Code::STORE_IC, strict_mode, type); Handle<Code> stub = FindIC(
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), name, receiver, Code::STORE_IC, type, strict_mode);
isolate_); if (!stub.is_null()) return stub;
if (probe->IsCode()) return Handle<Code>::cast(probe);
StoreStubCompiler compiler(isolate_, strict_mode); StoreStubCompiler compiler(isolate_, strict_mode);
Handle<Code> code = Handle<Code> code =
@ -473,11 +468,9 @@ Handle<Code> StubCache::ComputeStoreGlobal(Handle<Name> name,
Handle<GlobalObject> receiver, Handle<GlobalObject> receiver,
Handle<JSGlobalPropertyCell> cell, Handle<JSGlobalPropertyCell> cell,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode) {
Code::Flags flags = Code::ComputeMonomorphicFlags( Handle<Code> stub = FindIC(
Code::STORE_IC, strict_mode); name, receiver, Code::STORE_IC, Code::NORMAL, strict_mode);
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), if (!stub.is_null()) return stub;
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
StoreStubCompiler compiler(isolate_, strict_mode); StoreStubCompiler compiler(isolate_, strict_mode);
Handle<Code> code = compiler.CompileStoreGlobal(receiver, cell, name); Handle<Code> code = compiler.CompileStoreGlobal(receiver, cell, name);
@ -493,11 +486,9 @@ Handle<Code> StubCache::ComputeStoreCallback(
Handle<ExecutableAccessorInfo> callback, Handle<ExecutableAccessorInfo> callback,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode) {
ASSERT(v8::ToCData<Address>(callback->setter()) != 0); ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
Code::Flags flags = Code::ComputeMonomorphicFlags( Handle<Code> stub = FindIC(
Code::STORE_IC, strict_mode, Code::CALLBACKS); name, receiver, Code::STORE_IC, Code::CALLBACKS, strict_mode);
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), if (!stub.is_null()) return stub;
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
StoreStubCompiler compiler(isolate_, strict_mode); StoreStubCompiler compiler(isolate_, strict_mode);
Handle<Code> code = Handle<Code> code =
@ -512,11 +503,9 @@ Handle<Code> StubCache::ComputeStoreViaSetter(Handle<Name> name,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<JSFunction> setter, Handle<JSFunction> setter,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode) {
Code::Flags flags = Code::ComputeMonomorphicFlags( Handle<Code> stub = FindIC(
Code::STORE_IC, strict_mode, Code::CALLBACKS); name, receiver, Code::STORE_IC, Code::CALLBACKS, strict_mode);
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), if (!stub.is_null()) return stub;
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
StoreStubCompiler compiler(isolate_, strict_mode); StoreStubCompiler compiler(isolate_, strict_mode);
Handle<Code> code = Handle<Code> code =
@ -529,11 +518,9 @@ Handle<Code> StubCache::ComputeStoreViaSetter(Handle<Name> name,
Handle<Code> StubCache::ComputeStoreInterceptor(Handle<Name> name, Handle<Code> StubCache::ComputeStoreInterceptor(Handle<Name> name,
Handle<JSObject> receiver, Handle<JSObject> receiver,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode) {
Code::Flags flags = Code::ComputeMonomorphicFlags( Handle<Code> stub = FindIC(
Code::STORE_IC, strict_mode, Code::INTERCEPTOR); name, receiver, Code::STORE_IC, Code::INTERCEPTOR, strict_mode);
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), if (!stub.is_null()) return stub;
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
StoreStubCompiler compiler(isolate_, strict_mode); StoreStubCompiler compiler(isolate_, strict_mode);
Handle<Code> code = compiler.CompileStoreInterceptor(receiver, name); Handle<Code> code = compiler.CompileStoreInterceptor(receiver, name);
@ -548,11 +535,9 @@ Handle<Code> StubCache::ComputeKeyedStoreField(Handle<Name> name,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode) {
Code::StubType type = Code::StubType type =
(transition.is_null()) ? Code::FIELD : Code::MAP_TRANSITION; (transition.is_null()) ? Code::FIELD : Code::MAP_TRANSITION;
Code::Flags flags = Code::ComputeMonomorphicFlags( Handle<Code> stub = FindIC(
Code::KEYED_STORE_IC, strict_mode, type); name, receiver, Code::KEYED_STORE_IC, type, strict_mode);
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), if (!stub.is_null()) return stub;
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
KeyedStoreStubCompiler compiler(isolate(), strict_mode, STANDARD_STORE); KeyedStoreStubCompiler compiler(isolate(), strict_mode, STANDARD_STORE);
Handle<Code> code = Handle<Code> code =
@ -1452,16 +1437,29 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadField(Handle<JSObject> object,
Register reg = HandlerFrontendHeader(object, receiver(), holder, name, &miss); Register reg = HandlerFrontendHeader(object, receiver(), holder, name, &miss);
LoadFieldStub stub(reg, field.is_inobject(holder), field.translate(holder)); LoadFieldStub stub(reg, field.is_inobject(holder), field.translate(holder));
GenerateTailCall(stub.GetCode(isolate())); GenerateTailCall(masm(), stub.GetCode(isolate()));
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), kind()); TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code. // Return the generated code.
return GetCode(kind(), Code::FIELD, name); 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<Code> BaseLoadStubCompiler::CompileLoadConstant(
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSObject> holder, Handle<JSObject> holder,
@ -1527,7 +1525,7 @@ void BaseLoadStubCompiler::GenerateLoadPostInterceptor(
LoadFieldStub stub(interceptor_reg, LoadFieldStub stub(interceptor_reg,
field.is_inobject(holder), field.is_inobject(holder),
field.translate(holder)); field.translate(holder));
GenerateTailCall(stub.GetCode(isolate())); GenerateTailCall(masm(), stub.GetCode(isolate()));
} else { } else {
// We found FIELD property in prototype chain of interceptor's holder. // We found FIELD property in prototype chain of interceptor's holder.
// Retrieve a field from field'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 __ #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) { void LoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *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, Handle<Code> BaseLoadStubCompiler::GetICCode(Code::Kind kind,
Code::StubType type, Code::StubType type,
Handle<Name> name, 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, void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps,
CodeHandleList* handlers) { CodeHandleList* handlers) {
for (int i = 0; i < receiver_maps->length(); ++i) { 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( Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic(
MapHandleList* receiver_maps) { MapHandleList* receiver_maps) {
// Collect MONOMORPHIC stubs for all |receiver_maps|. // Collect MONOMORPHIC stubs for all |receiver_maps|.
@ -1696,7 +1741,7 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic(
elements_kind, elements_kind,
transitioned_map->elements_kind(), transitioned_map->elements_kind(),
is_js_array, is_js_array,
strict_mode_, strict_mode(),
store_mode_).GetCode(isolate()); store_mode_).GetCode(isolate());
} else { } else {
cached_stub = KeyedStoreElementStub( cached_stub = KeyedStoreElementStub(

View File

@ -80,12 +80,15 @@ class StubCache {
Handle<Code> FindIC(Handle<Name> name, Handle<Code> FindIC(Handle<Name> name,
Handle<JSObject> stub_holder, Handle<JSObject> stub_holder,
Code::Kind kind, 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<JSObject> stub_holder, Handle<Name> name,
Code::Kind kind, Handle<JSObject> stub_holder,
Code::StubType type); Code::Kind kind,
Code::StubType type,
Code::ExtraICState extra_state = Code::kNoExtraICState);
Handle<Code> ComputeMonomorphicIC(Handle<JSObject> receiver, Handle<Code> ComputeMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler, Handle<Code> handler,
@ -513,14 +516,23 @@ class StubCompiler BASE_EMBEDDED {
Handle<Name> name, Handle<Name> name,
Register receiver_reg, Register receiver_reg,
Register name_reg, Register name_reg,
Register value_reg,
Register scratch1, Register scratch1,
Register scratch2, Register scratch2,
Label* miss_label); Label* miss_label,
Label* miss_restore_name);
static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind); static Builtins::Name MissBuiltin(Code::Kind kind) {
static void GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind); switch (kind) {
case Code::LOAD_IC: return Builtins::kLoadIC_Miss;
static void GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm); 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 // Generates code that verifies that the property holder has not changed
// (checking maps of objects in the prototype chain for fast and global // (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(); } Heap* heap() { return isolate()->heap(); }
Factory* factory() { return isolate()->factory(); } Factory* factory() { return isolate()->factory(); }
void GenerateTailCall(Handle<Code> code); static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code);
private: private:
Isolate* isolate_; Isolate* isolate_;
@ -739,8 +751,6 @@ class KeyedLoadStubCompiler: public BaseLoadStubCompiler {
void CompileElementHandlers(MapHandleList* receiver_maps, void CompileElementHandlers(MapHandleList* receiver_maps,
CodeHandleList* handlers); CodeHandleList* handlers);
Handle<Code> CompileLoadElementPolymorphic(MapHandleList* receiver_maps);
static void GenerateLoadDictionaryElement(MacroAssembler* masm); static void GenerateLoadDictionaryElement(MacroAssembler* masm);
static Register receiver() { return registers()[0]; } static Register receiver() { return registers()[0]; }
@ -760,17 +770,63 @@ class KeyedLoadStubCompiler: public BaseLoadStubCompiler {
}; };
class StoreStubCompiler: public StubCompiler { class BaseStoreStubCompiler: public StubCompiler {
public: public:
StoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode) BaseStoreStubCompiler(Isolate* isolate,
: StubCompiler(isolate), strict_mode_(strict_mode) { } StrictModeFlag strict_mode,
Register* registers)
: StubCompiler(isolate),
strict_mode_(strict_mode),
registers_(registers) { }
virtual ~BaseStoreStubCompiler() { }
Handle<Code> CompileStoreField(Handle<JSObject> object, Handle<Code> CompileStoreField(Handle<JSObject> object,
int index, int index,
Handle<Map> transition, Handle<Map> transition,
Handle<Name> name); 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<Code> CompileStoreCallback(Handle<Name> name,
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSObject> holder, Handle<JSObject> holder,
@ -792,25 +848,24 @@ class StoreStubCompiler: public StubCompiler {
Handle<Name> name); Handle<Name> name);
private: private:
Handle<Code> GetCode(Code::StubType type, Handle<Name> name); static Register* registers();
virtual Code::Kind kind() { return Code::STORE_IC; }
StrictModeFlag strict_mode_; 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: public:
KeyedStoreStubCompiler(Isolate* isolate, KeyedStoreStubCompiler(Isolate* isolate,
StrictModeFlag strict_mode, StrictModeFlag strict_mode,
KeyedAccessStoreMode store_mode) KeyedAccessStoreMode store_mode)
: StubCompiler(isolate), : BaseStoreStubCompiler(isolate, strict_mode, registers()),
strict_mode_(strict_mode), store_mode_(store_mode) { }
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> CompileStoreElement(Handle<Map> receiver_map);
@ -834,12 +889,23 @@ class KeyedStoreStubCompiler: public StubCompiler {
static void GenerateStoreDictionaryElement(MacroAssembler* masm); static void GenerateStoreDictionaryElement(MacroAssembler* masm);
private: protected:
Handle<Code> GetCode(Code::StubType type, virtual Code::ExtraICState extra_state() {
Handle<Name> name, return Code::ComputeExtraICState(store_mode_, strict_mode());
InlineCacheState state = MONOMORPHIC); }
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_; KeyedAccessStoreMode store_mode_;
}; };

View File

@ -2403,7 +2403,7 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
StubCompiler::GenerateLoadArrayLength(masm, receiver, r8, &miss); StubCompiler::GenerateLoadArrayLength(masm, receiver, r8, &miss);
__ bind(&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); StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r8, r9, &miss);
__ bind(&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, StubCompiler::GenerateLoadStringLength(masm, receiver, r8, r9, &miss,
support_wrapper_); support_wrapper_);
__ bind(&miss); __ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, kind()); StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
} }
@ -2523,7 +2523,7 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
__ bind(&miss); __ bind(&miss);
StubCompiler::GenerateStoreMiss(masm, kind()); StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
} }

View File

@ -1333,8 +1333,7 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
Isolate::Current()->stub_cache()->GenerateProbe( Isolate::Current()->stub_cache()->GenerateProbe(
masm, flags, rax, rcx, rbx, rdx); masm, flags, rax, rcx, rbx, rdx);
// Cache miss: Jump to runtime. GenerateMiss(masm);
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
} }

View File

@ -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, void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm,
Register dst, Register dst,
Register src, Register src,
@ -715,28 +702,13 @@ class CallInterceptorCompiler BASE_EMBEDDED {
}; };
void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); Label* label,
Handle<Code> code = (kind == Code::LOAD_IC) Handle<Name> name) {
? masm->isolate()->builtins()->LoadIC_Miss() if (!label->is_unused()) {
: masm->isolate()->builtins()->KeyedLoadIC_Miss(); __ bind(label);
__ Jump(code, RelocInfo::CODE_TARGET); __ 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, Handle<Name> name,
Register receiver_reg, Register receiver_reg,
Register name_reg, Register name_reg,
Register value_reg,
Register scratch1, Register scratch1,
Register scratch2, Register scratch2,
Label* miss_label) { Label* miss_label,
Label* miss_restore_name) {
LookupResult lookup(masm->isolate()); LookupResult lookup(masm->isolate());
object->Lookup(*name, &lookup); object->Lookup(*name, &lookup);
if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) { if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) {
@ -785,17 +759,8 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
holder = JSObject::cast(holder->GetPrototype()); holder = JSObject::cast(holder->GetPrototype());
} while (holder->GetPrototype()->IsJSObject()); } 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, CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
scratch1, scratch2, name, &miss_pop); scratch1, scratch2, name, miss_restore_name);
__ jmp(&done_check);
__ bind(&miss_pop);
__ pop(name_reg);
__ jmp(miss_label);
__ bind(&done_check);
__ pop(name_reg);
} }
// Stub never generated for non-global objects that require access // Stub never generated for non-global objects that require access
@ -809,7 +774,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
__ pop(scratch1); // Return address. __ pop(scratch1); // Return address.
__ push(receiver_reg); __ push(receiver_reg);
__ Push(transition); __ Push(transition);
__ push(rax); __ push(value_reg);
__ push(scratch1); __ push(scratch1);
__ TailCallExternalReference( __ TailCallExternalReference(
ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
@ -843,11 +808,11 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
if (index < 0) { if (index < 0) {
// Set the property straight into the object. // Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize); 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. // Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg. // Pass the value being stored in the now unused name_reg.
__ movq(name_reg, rax); __ movq(name_reg, value_reg);
__ RecordWriteField( __ RecordWriteField(
receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs); receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs);
} else { } else {
@ -855,16 +820,17 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
int offset = index * kPointerSize + FixedArray::kHeaderSize; int offset = index * kPointerSize + FixedArray::kHeaderSize;
// Get the properties array (optimistically). // Get the properties array (optimistically).
__ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); __ 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. // Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg. // Pass the value being stored in the now unused name_reg.
__ movq(name_reg, rax); __ movq(name_reg, value_reg);
__ RecordWriteField( __ RecordWriteField(
scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs); scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs);
} }
// Return the value (register rax). // Return the value (register rax).
ASSERT(value_reg.is(rax));
__ ret(0); __ ret(0);
} }
@ -908,15 +874,16 @@ static void GenerateCheckPropertyCells(MacroAssembler* masm,
} }
} }
#undef __
#define __ ACCESS_MASM((masm()))
void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
void StubCompiler::GenerateTailCall(Handle<Code> code) {
__ jmp(code, RelocInfo::CODE_TARGET); __ jmp(code, RelocInfo::CODE_TARGET);
} }
#undef __
#define __ ACCESS_MASM((masm()))
Register StubCompiler::CheckPrototypes(Handle<JSObject> object, Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
Register object_reg, Register object_reg,
Handle<JSObject> holder, Handle<JSObject> holder,
@ -1039,7 +1006,7 @@ void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success,
if (!miss->is_unused()) { if (!miss->is_unused()) {
__ jmp(success); __ jmp(success);
__ bind(miss); __ 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<Code> StoreStubCompiler::CompileStoreCallback(
Handle<Name> name, Handle<Name> name,
Handle<JSObject> receiver, Handle<JSObject> receiver,
@ -2474,11 +2408,10 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
// Handle store cache miss. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // 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); GenerateStoreViaSetter(masm(), setter);
__ bind(&miss); __ bind(&miss);
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // 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(rdx); // receiver
__ push(rcx); // name __ push(rcx); // name
__ push(rax); // value __ push(rax); // value
__ Push(Smi::FromInt(strict_mode_)); __ Push(Smi::FromInt(strict_mode()));
__ push(rbx); // restore return address __ push(rbx); // restore return address
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
@ -2594,11 +2526,10 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
// Handle store cache miss. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // 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. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);
__ IncrementCounter(counters->named_store_global_inline_miss(), 1); __ IncrementCounter(counters->named_store_global_inline_miss(), 1);
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // Return the generated code.
return GetCode(Code::NORMAL, name); return GetICCode(kind(), 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);
} }
@ -2709,11 +2598,10 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
__ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ jmp(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // 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); __ bind(&miss);
Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
__ jmp(ic, RelocInfo::CODE_TARGET); TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code. // 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, void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
Register name_reg, Register name_reg,
Label* miss) { 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 __ #undef __
#define __ ACCESS_MASM(masm) #define __ ACCESS_MASM(masm)
@ -2895,7 +2806,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
__ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
} }
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss);
// Return the generated code. // Return the generated code.
return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
@ -2925,7 +2836,7 @@ Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
} }
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), kind()); TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code. // Return the generated code.
InlineCacheState state = InlineCacheState state =
@ -3101,9 +3012,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
// -- rdx : receiver // -- rdx : receiver
// -- rsp[0] : return address // -- rsp[0] : return address
// ----------------------------------- // -----------------------------------
Handle<Code> slow_ic = TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
masm->isolate()->builtins()->KeyedLoadIC_Slow();
__ jmp(slow_ic, RelocInfo::CODE_TARGET);
__ bind(&miss_force_generic); __ bind(&miss_force_generic);
// ----------- S t a t e ------------- // ----------- S t a t e -------------
@ -3111,9 +3020,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
// -- rdx : receiver // -- rdx : receiver
// -- rsp[0] : return address // -- rsp[0] : return address
// ----------------------------------- // -----------------------------------
Handle<Code> miss_ic = TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric);
masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
__ jmp(miss_ic, RelocInfo::CODE_TARGET);
} }
@ -3311,9 +3218,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
// -- rdx : receiver // -- rdx : receiver
// -- rsp[0] : return address // -- rsp[0] : return address
// ----------------------------------- // -----------------------------------
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
__ jmp(ic, RelocInfo::CODE_TARGET);
// Miss case: call runtime. // Miss case: call runtime.
__ bind(&miss_force_generic); __ bind(&miss_force_generic);
@ -3324,10 +3229,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
// -- rdx : receiver // -- rdx : receiver
// -- rsp[0] : return address // -- rsp[0] : return address
// ----------------------------------- // -----------------------------------
TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
Handle<Code> miss_ic =
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ jmp(miss_ic, RelocInfo::CODE_TARGET);
} }
@ -3396,13 +3298,10 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
// Handle store cache miss. // Handle store cache miss.
__ bind(&miss_force_generic); __ bind(&miss_force_generic);
Handle<Code> ic_force_generic = TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
__ bind(&transition_elements_kind); __ bind(&transition_elements_kind);
Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
__ jmp(ic_miss, RelocInfo::CODE_TARGET);
if (is_js_array && IsGrowStoreMode(store_mode)) { if (is_js_array && IsGrowStoreMode(store_mode)) {
// Grow the array by a single element if possible. // Grow the array by a single element if possible.
@ -3468,8 +3367,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
__ jmp(&finish_store); __ jmp(&finish_store);
__ bind(&slow); __ bind(&slow);
Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
__ jmp(ic_slow, RelocInfo::CODE_TARGET);
} }
} }
@ -3519,16 +3417,13 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
// Handle store cache miss, replacing the ic with the generic stub. // Handle store cache miss, replacing the ic with the generic stub.
__ bind(&miss_force_generic); __ bind(&miss_force_generic);
Handle<Code> ic_force_generic = TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
__ bind(&restore_key_transition_elements_kind); __ bind(&restore_key_transition_elements_kind);
// Restore smi-tagging of rcx. // Restore smi-tagging of rcx.
__ Integer32ToSmi(rcx, rcx); __ Integer32ToSmi(rcx, rcx);
__ bind(&transition_elements_kind); __ bind(&transition_elements_kind);
Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
__ jmp(ic_miss, RelocInfo::CODE_TARGET);
if (is_js_array && IsGrowStoreMode(store_mode)) { if (is_js_array && IsGrowStoreMode(store_mode)) {
// Grow the array by a single element if possible. // Grow the array by a single element if possible.
@ -3602,8 +3497,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
__ jmp(&finish_store); __ jmp(&finish_store);
__ bind(&slow); __ bind(&slow);
Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
__ jmp(ic_slow, RelocInfo::CODE_TARGET);
} }
} }