Migrate ArrayLength (Keyed|Named)LoadIC to CodeStub
Review URL: https://chromiumcodereview.appspot.com/11938013 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13458 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
77f3556504
commit
f80379f3fb
@ -4503,6 +4503,35 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
Label miss;
|
||||
Register receiver;
|
||||
if (kind() == Code::KEYED_LOAD_IC) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
__ cmp(r0, Operand(masm->isolate()->factory()->length_symbol()));
|
||||
__ b(ne, &miss);
|
||||
receiver = r1;
|
||||
} else {
|
||||
ASSERT(kind() == Code::LOAD_IC);
|
||||
// ----------- S t a t e -------------
|
||||
// -- r2 : name
|
||||
// -- lr : return address
|
||||
// -- r0 : receiver
|
||||
// -- sp[0] : receiver
|
||||
// -----------------------------------
|
||||
receiver = r0;
|
||||
}
|
||||
|
||||
StubCompiler::GenerateLoadArrayLength(masm, receiver, r3, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
}
|
||||
|
||||
|
||||
void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||
Label miss;
|
||||
Register receiver;
|
||||
|
@ -213,21 +213,6 @@ static void GenerateDictionaryStore(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r2 : name
|
||||
// -- lr : return address
|
||||
// -- r0 : receiver
|
||||
// -- sp[0] : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
StubCompiler::GenerateLoadArrayLength(masm, r0, r3, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r2 : name
|
||||
|
@ -3207,27 +3207,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
|
||||
Handle<String> name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
// Check the key is the cached one.
|
||||
__ cmp(r0, Operand(name));
|
||||
__ b(ne, &miss);
|
||||
|
||||
GenerateLoadArrayLength(masm(), r1, r2, &miss);
|
||||
__ bind(&miss);
|
||||
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
||||
|
||||
return GetCode(Code::CALLBACKS, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
|
||||
Handle<String> name) {
|
||||
// ----------- S t a t e -------------
|
||||
|
@ -413,8 +413,9 @@ void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle,
|
||||
is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
|
||||
receiver_types_.Clear();
|
||||
if (key()->IsPropertyName()) {
|
||||
ArrayLengthStub array_stub(Code::LOAD_IC);
|
||||
StringLengthStub string_stub(Code::LOAD_IC, false);
|
||||
if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_ArrayLength)) {
|
||||
if (oracle->LoadIsStub(this, &array_stub)) {
|
||||
is_array_length_ = true;
|
||||
} else if (oracle->LoadIsStub(this, &string_stub)) {
|
||||
is_string_length_ = true;
|
||||
|
@ -1453,11 +1453,6 @@ BUILTIN(HandleApiCallAsConstructor) {
|
||||
}
|
||||
|
||||
|
||||
static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) {
|
||||
LoadIC::GenerateArrayLength(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_LoadIC_FunctionPrototype(MacroAssembler* masm) {
|
||||
LoadIC::GenerateFunctionPrototype(masm);
|
||||
}
|
||||
|
@ -134,8 +134,6 @@ enum BuiltinExtraArguments {
|
||||
Code::kNoExtraICState) \
|
||||
V(LoadIC_Normal, LOAD_IC, MONOMORPHIC, \
|
||||
Code::kNoExtraICState) \
|
||||
V(LoadIC_ArrayLength, LOAD_IC, MONOMORPHIC, \
|
||||
Code::kNoExtraICState) \
|
||||
V(LoadIC_FunctionPrototype, LOAD_IC, MONOMORPHIC, \
|
||||
Code::kNoExtraICState) \
|
||||
V(LoadIC_Megamorphic, LOAD_IC, MEGAMORPHIC, \
|
||||
|
@ -47,6 +47,7 @@ namespace internal {
|
||||
V(Compare) \
|
||||
V(CompareIC) \
|
||||
V(MathPow) \
|
||||
V(ArrayLength) \
|
||||
V(StringLength) \
|
||||
V(RecordWrite) \
|
||||
V(StoreBufferOverflow) \
|
||||
@ -557,11 +558,25 @@ class ICStub: public PlatformCodeStub {
|
||||
}
|
||||
Code::Kind kind() { return kind_; }
|
||||
|
||||
virtual int MinorKey() {
|
||||
return KindBits::encode(kind_);
|
||||
}
|
||||
|
||||
private:
|
||||
Code::Kind kind_;
|
||||
};
|
||||
|
||||
|
||||
class ArrayLengthStub: public ICStub {
|
||||
public:
|
||||
explicit ArrayLengthStub(Code::Kind kind) : ICStub(kind) { }
|
||||
virtual void Generate(MacroAssembler* masm);
|
||||
|
||||
private:
|
||||
virtual CodeStub::Major MajorKey() { return ArrayLength; }
|
||||
};
|
||||
|
||||
|
||||
class StringLengthStub: public ICStub {
|
||||
public:
|
||||
StringLengthStub(Code::Kind kind, bool support_wrapper)
|
||||
|
@ -3259,6 +3259,25 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
if (kind() == Code::KEYED_LOAD_IC) {
|
||||
__ cmp(ecx, Immediate(masm->isolate()->factory()->length_symbol()));
|
||||
__ j(not_equal, &miss);
|
||||
}
|
||||
|
||||
StubCompiler::GenerateLoadArrayLength(masm, edx, eax, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
}
|
||||
|
||||
|
||||
void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : name
|
||||
|
@ -216,20 +216,6 @@ static void GenerateDictionaryStore(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
StubCompiler::GenerateLoadArrayLength(masm, edx, eax, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : name
|
||||
|
@ -3315,32 +3315,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
|
||||
Handle<String> name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : key
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
Counters* counters = isolate()->counters();
|
||||
__ IncrementCounter(counters->keyed_load_array_length(), 1);
|
||||
|
||||
// Check that the name has not changed.
|
||||
__ cmp(ecx, Immediate(name));
|
||||
__ j(not_equal, &miss);
|
||||
|
||||
GenerateLoadArrayLength(masm(), edx, eax, &miss);
|
||||
__ bind(&miss);
|
||||
__ DecrementCounter(counters->keyed_load_array_length(), 1);
|
||||
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::CALLBACKS, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
|
||||
Handle<String> name) {
|
||||
// ----------- S t a t e -------------
|
||||
|
56
src/ic.cc
56
src/ic.cc
@ -868,6 +868,29 @@ bool IC::HandleLoad(State state,
|
||||
*result = Smi::FromInt(String::cast(*string)->length());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Use specialized code for getting the length of arrays.
|
||||
if (object->IsJSArray() && name->Equals(isolate()->heap()->length_symbol())) {
|
||||
Handle<Code> stub;
|
||||
if (state == UNINITIALIZED) {
|
||||
stub = pre_monomorphic_stub();
|
||||
} else if (state == PREMONOMORPHIC) {
|
||||
ArrayLengthStub array_length_stub(kind());
|
||||
stub = array_length_stub.GetCode();
|
||||
} else if (state != MEGAMORPHIC) {
|
||||
ASSERT(state != GENERIC);
|
||||
stub = megamorphic_stub();
|
||||
}
|
||||
if (!stub.is_null()) {
|
||||
set_target(*stub);
|
||||
#ifdef DEBUG
|
||||
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
|
||||
#endif
|
||||
}
|
||||
*result = JSArray::cast(*object)->length();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -887,27 +910,6 @@ MaybeObject* LoadIC::Load(State state,
|
||||
return result;
|
||||
}
|
||||
|
||||
// Use specialized code for getting the length of arrays.
|
||||
if (object->IsJSArray() &&
|
||||
name->Equals(isolate()->heap()->length_symbol())) {
|
||||
Handle<Code> stub;
|
||||
if (state == UNINITIALIZED) {
|
||||
stub = pre_monomorphic_stub();
|
||||
} else if (state == PREMONOMORPHIC) {
|
||||
stub = isolate()->builtins()->LoadIC_ArrayLength();
|
||||
} else if (state != MEGAMORPHIC) {
|
||||
ASSERT(state != GENERIC);
|
||||
stub = megamorphic_stub();
|
||||
}
|
||||
if (!stub.is_null()) {
|
||||
set_target(*stub);
|
||||
#ifdef DEBUG
|
||||
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
|
||||
#endif
|
||||
}
|
||||
return JSArray::cast(*object)->length();
|
||||
}
|
||||
|
||||
// Use specialized code for getting prototype of functions.
|
||||
if (object->IsJSFunction() &&
|
||||
name->Equals(isolate()->heap()->prototype_symbol()) &&
|
||||
@ -1175,18 +1177,6 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
||||
}
|
||||
|
||||
// TODO(1073): don't ignore the current stub state.
|
||||
// Use specialized code for getting the length of arrays.
|
||||
if (object->IsJSArray() &&
|
||||
name->Equals(isolate()->heap()->length_symbol())) {
|
||||
Handle<JSArray> array = Handle<JSArray>::cast(object);
|
||||
Handle<Code> code =
|
||||
isolate()->stub_cache()->ComputeKeyedLoadArrayLength(name, array);
|
||||
ASSERT(!code.is_null());
|
||||
set_target(*code);
|
||||
TRACE_IC("KeyedLoadIC", name, state, target());
|
||||
return array->length();
|
||||
}
|
||||
|
||||
// Use specialized code for getting prototype of functions.
|
||||
if (object->IsJSFunction() &&
|
||||
name->Equals(isolate()->heap()->prototype_symbol()) &&
|
||||
|
@ -348,23 +348,6 @@ Handle<Code> StubCache::ComputeKeyedLoadCallback(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCache::ComputeKeyedLoadArrayLength(Handle<String> name,
|
||||
Handle<JSArray> receiver) {
|
||||
Code::Flags flags =
|
||||
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::CALLBACKS);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
||||
KeyedLoadStubCompiler compiler(isolate_);
|
||||
Handle<Code> code = compiler.CompileLoadArrayLength(name);
|
||||
PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
|
||||
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
|
||||
JSObject::UpdateMapCodeCache(receiver, name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCache::ComputeKeyedLoadFunctionPrototype(
|
||||
Handle<String> name,
|
||||
Handle<JSFunction> receiver) {
|
||||
|
@ -133,9 +133,6 @@ class StubCache {
|
||||
Handle<JSObject> receiver,
|
||||
Handle<JSObject> holder);
|
||||
|
||||
Handle<Code> ComputeKeyedLoadArrayLength(Handle<String> name,
|
||||
Handle<JSArray> receiver);
|
||||
|
||||
Handle<Code> ComputeKeyedLoadFunctionPrototype(Handle<String> name,
|
||||
Handle<JSFunction> receiver);
|
||||
|
||||
@ -667,8 +664,6 @@ class KeyedLoadStubCompiler: public StubCompiler {
|
||||
Handle<JSObject> holder,
|
||||
Handle<String> name);
|
||||
|
||||
Handle<Code> CompileLoadArrayLength(Handle<String> name);
|
||||
|
||||
Handle<Code> CompileLoadFunctionPrototype(Handle<String> name);
|
||||
|
||||
Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
|
||||
|
@ -2360,6 +2360,33 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
Label miss;
|
||||
Register receiver;
|
||||
if (kind() == Code::KEYED_LOAD_IC) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
__ Cmp(rax, masm->isolate()->factory()->length_symbol());
|
||||
receiver = rdx;
|
||||
} else {
|
||||
ASSERT(kind() == Code::LOAD_IC);
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : receiver
|
||||
// -- rcx : name
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
receiver = rax;
|
||||
}
|
||||
|
||||
StubCompiler::GenerateLoadArrayLength(masm, receiver, r8, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
}
|
||||
|
||||
|
||||
void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||
Label miss;
|
||||
Register receiver;
|
||||
|
@ -224,20 +224,6 @@ static void GenerateDictionaryStore(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : receiver
|
||||
// -- rcx : name
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : receiver
|
||||
|
@ -3128,32 +3128,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
|
||||
Handle<String> name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
Counters* counters = isolate()->counters();
|
||||
__ IncrementCounter(counters->keyed_load_array_length(), 1);
|
||||
|
||||
// Check that the name has not changed.
|
||||
__ Cmp(rax, name);
|
||||
__ j(not_equal, &miss);
|
||||
|
||||
GenerateLoadArrayLength(masm(), rdx, rcx, &miss);
|
||||
__ bind(&miss);
|
||||
__ DecrementCounter(counters->keyed_load_array_length(), 1);
|
||||
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::CALLBACKS, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
|
||||
Handle<String> name) {
|
||||
// ----------- S t a t e -------------
|
||||
|
Loading…
Reference in New Issue
Block a user