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);
__ 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()));
}

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,
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);
}
}

View File

@ -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()));
}

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,
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);
}
}

View File

@ -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") \

View File

@ -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(

View File

@ -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_;
};

View File

@ -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()));
}

View File

@ -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);
}

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,
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);
}
}