Migrate FunctionPrototype (Keyed|Named)LoadIC to CodeStub
Review URL: https://chromiumcodereview.appspot.com/11941016 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13459 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
f80379f3fb
commit
b79a927e74
@ -4532,6 +4532,35 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FunctionPrototypeStub::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()->prototype_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::GenerateLoadFunctionPrototype(masm, receiver, r3, r4, &miss);
|
||||||
|
__ bind(&miss);
|
||||||
|
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void StringLengthStub::Generate(MacroAssembler* masm) {
|
void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||||
Label miss;
|
Label miss;
|
||||||
Register receiver;
|
Register receiver;
|
||||||
|
@ -213,21 +213,6 @@ static void GenerateDictionaryStore(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
|
|
||||||
// ----------- S t a t e -------------
|
|
||||||
// -- r2 : name
|
|
||||||
// -- lr : return address
|
|
||||||
// -- r0 : receiver
|
|
||||||
// -- sp[0] : receiver
|
|
||||||
// -----------------------------------
|
|
||||||
Label miss;
|
|
||||||
|
|
||||||
StubCompiler::GenerateLoadFunctionPrototype(masm, r0, r1, r3, &miss);
|
|
||||||
__ bind(&miss);
|
|
||||||
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Checks the receiver for special cases (value type, slow case bits).
|
// Checks the receiver for special cases (value type, slow case bits).
|
||||||
// Falls through for regular JS object.
|
// Falls through for regular JS object.
|
||||||
static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
|
static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
|
||||||
|
@ -3207,31 +3207,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
|
|
||||||
Handle<String> name) {
|
|
||||||
// ----------- S t a t e -------------
|
|
||||||
// -- lr : return address
|
|
||||||
// -- r0 : key
|
|
||||||
// -- r1 : receiver
|
|
||||||
// -----------------------------------
|
|
||||||
Label miss;
|
|
||||||
|
|
||||||
Counters* counters = masm()->isolate()->counters();
|
|
||||||
__ IncrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3);
|
|
||||||
|
|
||||||
// Check the name hasn't changed.
|
|
||||||
__ cmp(r0, Operand(name));
|
|
||||||
__ b(ne, &miss);
|
|
||||||
|
|
||||||
GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss);
|
|
||||||
__ bind(&miss);
|
|
||||||
__ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3);
|
|
||||||
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
|
||||||
|
|
||||||
return GetCode(Code::CALLBACKS, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
|
Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
|
||||||
Handle<Map> receiver_map) {
|
Handle<Map> receiver_map) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
|
@ -414,13 +414,13 @@ void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle,
|
|||||||
receiver_types_.Clear();
|
receiver_types_.Clear();
|
||||||
if (key()->IsPropertyName()) {
|
if (key()->IsPropertyName()) {
|
||||||
ArrayLengthStub array_stub(Code::LOAD_IC);
|
ArrayLengthStub array_stub(Code::LOAD_IC);
|
||||||
|
FunctionPrototypeStub proto_stub(Code::LOAD_IC);
|
||||||
StringLengthStub string_stub(Code::LOAD_IC, false);
|
StringLengthStub string_stub(Code::LOAD_IC, false);
|
||||||
if (oracle->LoadIsStub(this, &array_stub)) {
|
if (oracle->LoadIsStub(this, &array_stub)) {
|
||||||
is_array_length_ = true;
|
is_array_length_ = true;
|
||||||
} else if (oracle->LoadIsStub(this, &string_stub)) {
|
} else if (oracle->LoadIsStub(this, &string_stub)) {
|
||||||
is_string_length_ = true;
|
is_string_length_ = true;
|
||||||
} else if (oracle->LoadIsBuiltin(this,
|
} else if (oracle->LoadIsStub(this, &proto_stub)) {
|
||||||
Builtins::kLoadIC_FunctionPrototype)) {
|
|
||||||
is_function_prototype_ = true;
|
is_function_prototype_ = true;
|
||||||
} else {
|
} else {
|
||||||
Literal* lit_key = key()->AsLiteral();
|
Literal* lit_key = key()->AsLiteral();
|
||||||
|
@ -1453,11 +1453,6 @@ BUILTIN(HandleApiCallAsConstructor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void Generate_LoadIC_FunctionPrototype(MacroAssembler* masm) {
|
|
||||||
LoadIC::GenerateFunctionPrototype(masm);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void Generate_LoadIC_Initialize(MacroAssembler* masm) {
|
static void Generate_LoadIC_Initialize(MacroAssembler* masm) {
|
||||||
LoadIC::GenerateInitialize(masm);
|
LoadIC::GenerateInitialize(masm);
|
||||||
}
|
}
|
||||||
|
@ -134,8 +134,6 @@ enum BuiltinExtraArguments {
|
|||||||
Code::kNoExtraICState) \
|
Code::kNoExtraICState) \
|
||||||
V(LoadIC_Normal, LOAD_IC, MONOMORPHIC, \
|
V(LoadIC_Normal, LOAD_IC, MONOMORPHIC, \
|
||||||
Code::kNoExtraICState) \
|
Code::kNoExtraICState) \
|
||||||
V(LoadIC_FunctionPrototype, LOAD_IC, MONOMORPHIC, \
|
|
||||||
Code::kNoExtraICState) \
|
|
||||||
V(LoadIC_Megamorphic, LOAD_IC, MEGAMORPHIC, \
|
V(LoadIC_Megamorphic, LOAD_IC, MEGAMORPHIC, \
|
||||||
Code::kNoExtraICState) \
|
Code::kNoExtraICState) \
|
||||||
V(LoadIC_Getter_ForDeopt, LOAD_IC, MONOMORPHIC, \
|
V(LoadIC_Getter_ForDeopt, LOAD_IC, MONOMORPHIC, \
|
||||||
|
@ -49,6 +49,7 @@ namespace internal {
|
|||||||
V(MathPow) \
|
V(MathPow) \
|
||||||
V(ArrayLength) \
|
V(ArrayLength) \
|
||||||
V(StringLength) \
|
V(StringLength) \
|
||||||
|
V(FunctionPrototype) \
|
||||||
V(RecordWrite) \
|
V(RecordWrite) \
|
||||||
V(StoreBufferOverflow) \
|
V(StoreBufferOverflow) \
|
||||||
V(RegExpExec) \
|
V(RegExpExec) \
|
||||||
@ -577,6 +578,16 @@ class ArrayLengthStub: public ICStub {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class FunctionPrototypeStub: public ICStub {
|
||||||
|
public:
|
||||||
|
explicit FunctionPrototypeStub(Code::Kind kind) : ICStub(kind) { }
|
||||||
|
virtual void Generate(MacroAssembler* masm);
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual CodeStub::Major MajorKey() { return FunctionPrototype; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class StringLengthStub: public ICStub {
|
class StringLengthStub: public ICStub {
|
||||||
public:
|
public:
|
||||||
StringLengthStub(Code::Kind kind, bool support_wrapper)
|
StringLengthStub(Code::Kind kind, bool support_wrapper)
|
||||||
|
@ -3278,6 +3278,25 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FunctionPrototypeStub::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()->prototype_symbol()));
|
||||||
|
__ j(not_equal, &miss);
|
||||||
|
}
|
||||||
|
|
||||||
|
StubCompiler::GenerateLoadFunctionPrototype(masm, edx, eax, ebx, &miss);
|
||||||
|
__ bind(&miss);
|
||||||
|
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void StringLengthStub::Generate(MacroAssembler* masm) {
|
void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- ecx : name
|
// -- ecx : name
|
||||||
|
@ -216,20 +216,6 @@ static void GenerateDictionaryStore(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
|
|
||||||
// ----------- S t a t e -------------
|
|
||||||
// -- ecx : name
|
|
||||||
// -- edx : receiver
|
|
||||||
// -- esp[0] : return address
|
|
||||||
// -----------------------------------
|
|
||||||
Label miss;
|
|
||||||
|
|
||||||
StubCompiler::GenerateLoadFunctionPrototype(masm, edx, eax, ebx, &miss);
|
|
||||||
__ bind(&miss);
|
|
||||||
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Checks the receiver for special cases (value type, slow case bits).
|
// Checks the receiver for special cases (value type, slow case bits).
|
||||||
// Falls through for regular JS object.
|
// Falls through for regular JS object.
|
||||||
static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
|
static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
|
||||||
|
@ -3315,32 +3315,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
|
|
||||||
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_function_prototype(), 1);
|
|
||||||
|
|
||||||
// Check that the name has not changed.
|
|
||||||
__ cmp(ecx, Immediate(name));
|
|
||||||
__ j(not_equal, &miss);
|
|
||||||
|
|
||||||
GenerateLoadFunctionPrototype(masm(), edx, eax, ebx, &miss);
|
|
||||||
__ bind(&miss);
|
|
||||||
__ DecrementCounter(counters->keyed_load_function_prototype(), 1);
|
|
||||||
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
|
||||||
|
|
||||||
// Return the generated code.
|
|
||||||
return GetCode(Code::CALLBACKS, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
|
Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
|
||||||
Handle<Map> receiver_map) {
|
Handle<Map> receiver_map) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
|
172
src/ic.cc
172
src/ic.cc
@ -836,59 +836,86 @@ bool IC::HandleLoad(State state,
|
|||||||
Handle<Object> object,
|
Handle<Object> object,
|
||||||
Handle<String> name,
|
Handle<String> name,
|
||||||
MaybeObject** result) {
|
MaybeObject** result) {
|
||||||
// Use specialized code for getting the length of strings and
|
if (FLAG_use_ic) {
|
||||||
// string wrapper objects. The length property of string wrapper
|
// Use specialized code for getting the length of strings and
|
||||||
// objects is read-only and therefore always returns the length of
|
// string wrapper objects. The length property of string wrapper
|
||||||
// the underlying string value. See ECMA-262 15.5.5.1.
|
// objects is read-only and therefore always returns the length of
|
||||||
if ((object->IsString() || object->IsStringWrapper()) &&
|
// the underlying string value. See ECMA-262 15.5.5.1.
|
||||||
name->Equals(isolate()->heap()->length_symbol())) {
|
if ((object->IsString() || object->IsStringWrapper()) &&
|
||||||
Handle<Code> stub;
|
name->Equals(isolate()->heap()->length_symbol())) {
|
||||||
if (state == UNINITIALIZED) {
|
Handle<Code> stub;
|
||||||
stub = pre_monomorphic_stub();
|
if (state == UNINITIALIZED) {
|
||||||
} else if (state == PREMONOMORPHIC) {
|
stub = pre_monomorphic_stub();
|
||||||
StringLengthStub string_length_stub(kind(), !object->IsString());
|
} else if (state == PREMONOMORPHIC) {
|
||||||
stub = string_length_stub.GetCode();
|
StringLengthStub string_length_stub(kind(), !object->IsString());
|
||||||
} else if (state == MONOMORPHIC && object->IsStringWrapper()) {
|
stub = string_length_stub.GetCode();
|
||||||
StringLengthStub string_length_stub(kind(), true);
|
} else if (state == MONOMORPHIC && object->IsStringWrapper()) {
|
||||||
stub = string_length_stub.GetCode();
|
StringLengthStub string_length_stub(kind(), true);
|
||||||
} else if (state != MEGAMORPHIC) {
|
stub = string_length_stub.GetCode();
|
||||||
ASSERT(state != GENERIC);
|
} else if (state != MEGAMORPHIC) {
|
||||||
stub = megamorphic_stub();
|
ASSERT(state != GENERIC);
|
||||||
}
|
stub = megamorphic_stub();
|
||||||
if (!stub.is_null()) {
|
}
|
||||||
set_target(*stub);
|
if (!stub.is_null()) {
|
||||||
|
set_target(*stub);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
|
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
// Get the string if we have a string wrapper object.
|
||||||
|
Handle<Object> string = object->IsJSValue()
|
||||||
|
? Handle<Object>(Handle<JSValue>::cast(object)->value())
|
||||||
|
: object;
|
||||||
|
*result = Smi::FromInt(String::cast(*string)->length());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
// Get the string if we have a string wrapper object.
|
|
||||||
Handle<Object> string = object->IsJSValue()
|
|
||||||
? Handle<Object>(Handle<JSValue>::cast(object)->value())
|
|
||||||
: object;
|
|
||||||
*result = Smi::FromInt(String::cast(*string)->length());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use specialized code for getting the length of arrays.
|
// Use specialized code for getting the length of arrays.
|
||||||
if (object->IsJSArray() && name->Equals(isolate()->heap()->length_symbol())) {
|
if (object->IsJSArray() &&
|
||||||
Handle<Code> stub;
|
name->Equals(isolate()->heap()->length_symbol())) {
|
||||||
if (state == UNINITIALIZED) {
|
Handle<Code> stub;
|
||||||
stub = pre_monomorphic_stub();
|
if (state == UNINITIALIZED) {
|
||||||
} else if (state == PREMONOMORPHIC) {
|
stub = pre_monomorphic_stub();
|
||||||
ArrayLengthStub array_length_stub(kind());
|
} else if (state == PREMONOMORPHIC) {
|
||||||
stub = array_length_stub.GetCode();
|
ArrayLengthStub array_length_stub(kind());
|
||||||
} else if (state != MEGAMORPHIC) {
|
stub = array_length_stub.GetCode();
|
||||||
ASSERT(state != GENERIC);
|
} else if (state != MEGAMORPHIC) {
|
||||||
stub = megamorphic_stub();
|
ASSERT(state != GENERIC);
|
||||||
}
|
stub = megamorphic_stub();
|
||||||
if (!stub.is_null()) {
|
}
|
||||||
set_target(*stub);
|
if (!stub.is_null()) {
|
||||||
|
set_target(*stub);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
|
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
*result = JSArray::cast(*object)->length();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use specialized code for getting prototype of functions.
|
||||||
|
if (object->IsJSFunction() &&
|
||||||
|
name->Equals(isolate()->heap()->prototype_symbol()) &&
|
||||||
|
Handle<JSFunction>::cast(object)->should_have_prototype()) {
|
||||||
|
Handle<Code> stub;
|
||||||
|
if (state == UNINITIALIZED) {
|
||||||
|
stub = pre_monomorphic_stub();
|
||||||
|
} else if (state == PREMONOMORPHIC) {
|
||||||
|
FunctionPrototypeStub function_prototype_stub(kind());
|
||||||
|
stub = function_prototype_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 : +#prototype /function]\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
*result = Accessors::FunctionGetPrototype(*object, 0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
*result = JSArray::cast(*object)->length();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -904,33 +931,9 @@ MaybeObject* LoadIC::Load(State state,
|
|||||||
return TypeError("non_object_property_load", object, name);
|
return TypeError("non_object_property_load", object, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FLAG_use_ic) {
|
MaybeObject* result;
|
||||||
MaybeObject* result;
|
if (HandleLoad(state, object, name, &result)) {
|
||||||
if (HandleLoad(state, object, name, &result)) {
|
return result;
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use specialized code for getting prototype of functions.
|
|
||||||
if (object->IsJSFunction() &&
|
|
||||||
name->Equals(isolate()->heap()->prototype_symbol()) &&
|
|
||||||
Handle<JSFunction>::cast(object)->should_have_prototype()) {
|
|
||||||
Handle<Code> stub;
|
|
||||||
if (state == UNINITIALIZED) {
|
|
||||||
stub = pre_monomorphic_stub();
|
|
||||||
} else if (state == PREMONOMORPHIC) {
|
|
||||||
stub = isolate()->builtins()->LoadIC_FunctionPrototype();
|
|
||||||
} 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 : +#prototype /function]\n");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return Accessors::FunctionGetPrototype(*object, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the name is trivially convertible to an index and get
|
// Check if the name is trivially convertible to an index and get
|
||||||
@ -1170,26 +1173,9 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
|||||||
return TypeError("non_object_property_load", object, name);
|
return TypeError("non_object_property_load", object, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FLAG_use_ic) {
|
MaybeObject* result;
|
||||||
MaybeObject* result;
|
if (HandleLoad(state, object, name, &result)) {
|
||||||
if (HandleLoad(state, object, name, &result)) {
|
return result;
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(1073): don't ignore the current stub state.
|
|
||||||
// Use specialized code for getting prototype of functions.
|
|
||||||
if (object->IsJSFunction() &&
|
|
||||||
name->Equals(isolate()->heap()->prototype_symbol()) &&
|
|
||||||
Handle<JSFunction>::cast(object)->should_have_prototype()) {
|
|
||||||
Handle<JSFunction> function = Handle<JSFunction>::cast(object);
|
|
||||||
Handle<Code> code =
|
|
||||||
isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype(
|
|
||||||
name, function);
|
|
||||||
ASSERT(!code.is_null());
|
|
||||||
set_target(*code);
|
|
||||||
TRACE_IC("KeyedLoadIC", name, state, target());
|
|
||||||
return Accessors::FunctionGetPrototype(*object, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the name is trivially convertible to an index and get
|
// Check if the name is trivially convertible to an index and get
|
||||||
|
@ -348,24 +348,6 @@ Handle<Code> StubCache::ComputeKeyedLoadCallback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> StubCache::ComputeKeyedLoadFunctionPrototype(
|
|
||||||
Handle<String> name,
|
|
||||||
Handle<JSFunction> 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.CompileLoadFunctionPrototype(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::ComputeStoreField(Handle<String> name,
|
Handle<Code> StubCache::ComputeStoreField(Handle<String> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
int field_index,
|
int field_index,
|
||||||
|
@ -133,9 +133,6 @@ class StubCache {
|
|||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder);
|
Handle<JSObject> holder);
|
||||||
|
|
||||||
Handle<Code> ComputeKeyedLoadFunctionPrototype(Handle<String> name,
|
|
||||||
Handle<JSFunction> receiver);
|
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
Handle<Code> ComputeStoreField(Handle<String> name,
|
Handle<Code> ComputeStoreField(Handle<String> name,
|
||||||
@ -664,8 +661,6 @@ class KeyedLoadStubCompiler: public StubCompiler {
|
|||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<String> name);
|
Handle<String> name);
|
||||||
|
|
||||||
Handle<Code> CompileLoadFunctionPrototype(Handle<String> name);
|
|
||||||
|
|
||||||
Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
|
Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
|
||||||
|
|
||||||
Handle<Code> CompileLoadPolymorphic(MapHandleList* receiver_maps,
|
Handle<Code> CompileLoadPolymorphic(MapHandleList* receiver_maps,
|
||||||
|
@ -2387,6 +2387,33 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FunctionPrototypeStub::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()->prototype_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::GenerateLoadFunctionPrototype(masm, receiver, r8, r9, &miss);
|
||||||
|
__ bind(&miss);
|
||||||
|
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void StringLengthStub::Generate(MacroAssembler* masm) {
|
void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||||
Label miss;
|
Label miss;
|
||||||
Register receiver;
|
Register receiver;
|
||||||
|
@ -224,20 +224,6 @@ static void GenerateDictionaryStore(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
|
|
||||||
// ----------- S t a t e -------------
|
|
||||||
// -- rax : receiver
|
|
||||||
// -- rcx : name
|
|
||||||
// -- rsp[0] : return address
|
|
||||||
// -----------------------------------
|
|
||||||
Label miss;
|
|
||||||
|
|
||||||
StubCompiler::GenerateLoadFunctionPrototype(masm, rax, rdx, rbx, &miss);
|
|
||||||
__ bind(&miss);
|
|
||||||
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Checks the receiver for special cases (value type, slow case bits).
|
// Checks the receiver for special cases (value type, slow case bits).
|
||||||
// Falls through for regular JS object.
|
// Falls through for regular JS object.
|
||||||
static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
|
static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
|
||||||
|
@ -3128,32 +3128,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
|
|
||||||
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_function_prototype(), 1);
|
|
||||||
|
|
||||||
// Check that the name has not changed.
|
|
||||||
__ Cmp(rax, name);
|
|
||||||
__ j(not_equal, &miss);
|
|
||||||
|
|
||||||
GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss);
|
|
||||||
__ bind(&miss);
|
|
||||||
__ DecrementCounter(counters->keyed_load_function_prototype(), 1);
|
|
||||||
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
|
||||||
|
|
||||||
// Return the generated code.
|
|
||||||
return GetCode(Code::CALLBACKS, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
|
Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
|
||||||
Handle<Map> receiver_map) {
|
Handle<Map> receiver_map) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
|
Loading…
Reference in New Issue
Block a user