Refactoring Store ICs. A first step towards polymorphic store ICs.
Review URL: https://chromiumcodereview.appspot.com/12781004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13934 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
8db737a583
commit
569d9c59b9
@ -4513,7 +4513,7 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
|
|||||||
|
|
||||||
StubCompiler::GenerateLoadArrayLength(masm, receiver, r3, &miss);
|
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()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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") \
|
||||||
|
@ -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(
|
||||||
|
132
src/stub-cache.h
132
src/stub-cache.h
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user