Support slow-mode prototypes for load and call ICs.
This changes LoadNonExistent to handle negative lookups as well. Review URL: https://chromiumcodereview.appspot.com/12092043 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13571 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
1c1fdc7da2
commit
b1e5157e7b
@ -2894,9 +2894,11 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
|
||||
Handle<JSObject> object,
|
||||
Handle<JSObject> last) {
|
||||
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
|
||||
Handle<String> name,
|
||||
Handle<JSObject> object,
|
||||
Handle<JSObject> last,
|
||||
Handle<GlobalObject> global) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r0 : receiver
|
||||
// -- lr : return address
|
||||
@ -2906,14 +2908,24 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
|
||||
// Check that receiver is not a smi.
|
||||
__ JumpIfSmi(r0, &miss);
|
||||
|
||||
|
||||
Register scratch = r1;
|
||||
|
||||
// Check the maps of the full prototype chain.
|
||||
CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss);
|
||||
Register result =
|
||||
CheckPrototypes(object, r0, last, r3, scratch, r4, name, &miss);
|
||||
|
||||
// If the last object in the prototype chain is a global object,
|
||||
// check that the global property cell is empty.
|
||||
if (last->IsGlobalObject()) {
|
||||
GenerateCheckPropertyCell(
|
||||
masm(), Handle<GlobalObject>::cast(last), name, r1, &miss);
|
||||
if (!global.is_null()) {
|
||||
GenerateCheckPropertyCell(masm(), global, name, scratch, &miss);
|
||||
}
|
||||
|
||||
if (!last->HasFastProperties()) {
|
||||
__ ldr(scratch, FieldMemOperand(result, HeapObject::kMapOffset));
|
||||
__ ldr(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset));
|
||||
__ cmp(scratch, Operand(isolate()->factory()->null_value()));
|
||||
__ b(ne, &miss);
|
||||
}
|
||||
|
||||
// Return undefined if maps of the full prototype chain are still the
|
||||
|
@ -2964,9 +2964,11 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
|
||||
Handle<JSObject> object,
|
||||
Handle<JSObject> last) {
|
||||
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
|
||||
Handle<String> name,
|
||||
Handle<JSObject> object,
|
||||
Handle<JSObject> last,
|
||||
Handle<GlobalObject> global) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
@ -2977,18 +2979,25 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
|
||||
// Check that the receiver isn't a smi.
|
||||
__ JumpIfSmi(edx, &miss);
|
||||
|
||||
ASSERT(last->IsGlobalObject() || last->HasFastProperties());
|
||||
Register scratch = eax;
|
||||
|
||||
// Check the maps of the full prototype chain. Also check that
|
||||
// global property cells up to (but not including) the last object
|
||||
// in the prototype chain are empty.
|
||||
CheckPrototypes(object, edx, last, ebx, eax, edi, name, &miss);
|
||||
Register result =
|
||||
CheckPrototypes(object, edx, last, ebx, scratch, edi, name, &miss);
|
||||
|
||||
// If the last object in the prototype chain is a global object,
|
||||
// check that the global property cell is empty.
|
||||
if (last->IsGlobalObject()) {
|
||||
GenerateCheckPropertyCell(
|
||||
masm(), Handle<GlobalObject>::cast(last), name, eax, &miss);
|
||||
if (!global.is_null()) {
|
||||
GenerateCheckPropertyCell(masm(), global, name, scratch, &miss);
|
||||
}
|
||||
|
||||
if (!last->HasFastProperties()) {
|
||||
__ mov(scratch, FieldOperand(result, HeapObject::kMapOffset));
|
||||
__ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset));
|
||||
__ cmp(scratch, isolate()->factory()->null_value());
|
||||
__ j(not_equal, &miss);
|
||||
}
|
||||
|
||||
// Return undefined if maps of the full prototype chain are still the
|
||||
|
30
src/ic.cc
30
src/ic.cc
@ -169,26 +169,6 @@ Address IC::OriginalCodeAddress() const {
|
||||
#endif
|
||||
|
||||
|
||||
static bool HasNormalObjectsInPrototypeChain(Isolate* isolate,
|
||||
LookupResult* lookup,
|
||||
Object* receiver) {
|
||||
Object* end = lookup->IsProperty()
|
||||
? lookup->holder() : Object::cast(isolate->heap()->null_value());
|
||||
for (Object* current = receiver;
|
||||
current != end;
|
||||
current = current->GetPrototype()) {
|
||||
if (current->IsJSObject() &&
|
||||
!JSObject::cast(current)->HasFastProperties() &&
|
||||
!current->IsJSGlobalProxy() &&
|
||||
!current->IsJSGlobalObject()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
|
||||
Object* receiver,
|
||||
Object* name) {
|
||||
@ -700,14 +680,6 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
|
||||
// Bail out if we didn't find a result.
|
||||
if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
|
||||
|
||||
if (lookup->holder() != *object &&
|
||||
HasNormalObjectsInPrototypeChain(
|
||||
isolate(), lookup, object->GetPrototype())) {
|
||||
// Suppress optimization for prototype chains with slow properties objects
|
||||
// in the middle.
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute the number of arguments.
|
||||
int argc = target()->arguments_count();
|
||||
Handle<Code> code;
|
||||
@ -1023,8 +995,6 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
|
||||
// deal with non-JS objects here.
|
||||
if (!object->IsJSObject()) return;
|
||||
|
||||
if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
|
||||
|
||||
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
|
||||
Handle<Code> code;
|
||||
if (state == UNINITIALIZED) {
|
||||
|
@ -102,7 +102,6 @@ Code* StubCache::Set(String* name, Map* map, Code* code) {
|
||||
|
||||
Handle<Code> StubCache::ComputeLoadNonexistent(Handle<String> name,
|
||||
Handle<JSObject> receiver) {
|
||||
ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties());
|
||||
// If no global objects are present in the prototype chain, the load
|
||||
// nonexistent IC stub can be shared for all names for a given map
|
||||
// and we use the empty string for the map cache in that case. If
|
||||
@ -110,12 +109,20 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<String> name,
|
||||
// property cells in the stub and therefore the stub will be
|
||||
// specific to the name.
|
||||
Handle<String> cache_name = factory()->empty_string();
|
||||
if (receiver->IsGlobalObject()) cache_name = name;
|
||||
Handle<JSObject> last = receiver;
|
||||
while (last->GetPrototype() != heap()->null_value()) {
|
||||
last = Handle<JSObject>(JSObject::cast(last->GetPrototype()));
|
||||
if (last->IsGlobalObject()) cache_name = name;
|
||||
}
|
||||
Handle<JSObject> current;
|
||||
Handle<Object> next = receiver;
|
||||
Handle<GlobalObject> global;
|
||||
do {
|
||||
current = Handle<JSObject>::cast(next);
|
||||
next = Handle<Object>(current->GetPrototype());
|
||||
if (current->IsGlobalObject()) {
|
||||
global = Handle<GlobalObject>::cast(current);
|
||||
cache_name = name;
|
||||
} else if (!current->HasFastProperties()) {
|
||||
cache_name = name;
|
||||
}
|
||||
} while (!next->IsNull());
|
||||
|
||||
// Compile the stub that is either shared for all names or
|
||||
// name specific if there are global objects involved.
|
||||
Code::Flags flags =
|
||||
@ -126,7 +133,7 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<String> name,
|
||||
|
||||
LoadStubCompiler compiler(isolate_);
|
||||
Handle<Code> code =
|
||||
compiler.CompileLoadNonexistent(cache_name, receiver, last);
|
||||
compiler.CompileLoadNonexistent(cache_name, receiver, current, global);
|
||||
PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *cache_name));
|
||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *cache_name, *code));
|
||||
JSObject::UpdateMapCodeCache(receiver, cache_name, code);
|
||||
@ -138,9 +145,11 @@ Handle<Code> StubCache::ComputeLoadField(Handle<String> name,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<JSObject> holder,
|
||||
PropertyIndex field_index) {
|
||||
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||
InlineCacheHolderFlag cache_holder =
|
||||
IC::GetCodeCacheForObject(*receiver, *holder);
|
||||
Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::FIELD);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
||||
@ -149,7 +158,7 @@ Handle<Code> StubCache::ComputeLoadField(Handle<String> name,
|
||||
compiler.CompileLoadField(receiver, holder, field_index, name);
|
||||
PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
|
||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
|
||||
JSObject::UpdateMapCodeCache(receiver, name, code);
|
||||
JSObject::UpdateMapCodeCache(map_holder, name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
@ -159,10 +168,12 @@ Handle<Code> StubCache::ComputeLoadCallback(Handle<String> name,
|
||||
Handle<JSObject> holder,
|
||||
Handle<AccessorInfo> callback) {
|
||||
ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
|
||||
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||
InlineCacheHolderFlag cache_holder =
|
||||
IC::GetCodeCacheForObject(*receiver, *holder);
|
||||
Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
|
||||
Code::Flags flags =
|
||||
Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::CALLBACKS);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
||||
@ -171,7 +182,7 @@ Handle<Code> StubCache::ComputeLoadCallback(Handle<String> name,
|
||||
compiler.CompileLoadCallback(name, receiver, holder, callback);
|
||||
PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
|
||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
|
||||
JSObject::UpdateMapCodeCache(receiver, name, code);
|
||||
JSObject::UpdateMapCodeCache(map_holder, name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
@ -180,10 +191,12 @@ Handle<Code> StubCache::ComputeLoadViaGetter(Handle<String> name,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<JSObject> holder,
|
||||
Handle<JSFunction> getter) {
|
||||
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||
InlineCacheHolderFlag cache_holder =
|
||||
IC::GetCodeCacheForObject(*receiver, *holder);
|
||||
Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
|
||||
Code::Flags flags =
|
||||
Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::CALLBACKS);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
||||
@ -192,7 +205,7 @@ Handle<Code> StubCache::ComputeLoadViaGetter(Handle<String> name,
|
||||
compiler.CompileLoadViaGetter(name, receiver, holder, getter);
|
||||
PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
|
||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
|
||||
JSObject::UpdateMapCodeCache(receiver, name, code);
|
||||
JSObject::UpdateMapCodeCache(map_holder, name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
@ -201,10 +214,12 @@ Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<JSObject> holder,
|
||||
Handle<JSFunction> value) {
|
||||
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||
InlineCacheHolderFlag cache_holder =
|
||||
IC::GetCodeCacheForObject(*receiver, *holder);
|
||||
Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
|
||||
Code::Flags flags =
|
||||
Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::CONSTANT_FUNCTION);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
||||
@ -213,7 +228,7 @@ Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name,
|
||||
compiler.CompileLoadConstant(receiver, holder, value, name);
|
||||
PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
|
||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
|
||||
JSObject::UpdateMapCodeCache(receiver, name, code);
|
||||
JSObject::UpdateMapCodeCache(map_holder, name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
@ -221,10 +236,12 @@ Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name,
|
||||
Handle<Code> StubCache::ComputeLoadInterceptor(Handle<String> name,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<JSObject> holder) {
|
||||
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||
InlineCacheHolderFlag cache_holder =
|
||||
IC::GetCodeCacheForObject(*receiver, *holder);
|
||||
Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
|
||||
Code::Flags flags =
|
||||
Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::INTERCEPTOR);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
||||
@ -233,7 +250,7 @@ Handle<Code> StubCache::ComputeLoadInterceptor(Handle<String> name,
|
||||
compiler.CompileLoadInterceptor(receiver, holder, name);
|
||||
PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
|
||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
|
||||
JSObject::UpdateMapCodeCache(receiver, name, code);
|
||||
JSObject::UpdateMapCodeCache(map_holder, name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
@ -248,10 +265,12 @@ Handle<Code> StubCache::ComputeLoadGlobal(Handle<String> name,
|
||||
Handle<GlobalObject> holder,
|
||||
Handle<JSGlobalPropertyCell> cell,
|
||||
bool is_dont_delete) {
|
||||
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||
InlineCacheHolderFlag cache_holder =
|
||||
IC::GetCodeCacheForObject(*receiver, *holder);
|
||||
Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
|
||||
Code::Flags flags =
|
||||
Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::NORMAL);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
||||
@ -260,7 +279,7 @@ Handle<Code> StubCache::ComputeLoadGlobal(Handle<String> name,
|
||||
compiler.CompileLoadGlobal(receiver, holder, cell, name, is_dont_delete);
|
||||
PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
|
||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
|
||||
JSObject::UpdateMapCodeCache(receiver, name, code);
|
||||
JSObject::UpdateMapCodeCache(map_holder, name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
@ -269,10 +288,12 @@ Handle<Code> StubCache::ComputeKeyedLoadField(Handle<String> name,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<JSObject> holder,
|
||||
PropertyIndex field_index) {
|
||||
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||
InlineCacheHolderFlag cache_holder =
|
||||
IC::GetCodeCacheForObject(*receiver, *holder);
|
||||
Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
|
||||
Code::Flags flags =
|
||||
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::FIELD);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
||||
@ -281,7 +302,7 @@ Handle<Code> StubCache::ComputeKeyedLoadField(Handle<String> name,
|
||||
compiler.CompileLoadField(name, receiver, holder, field_index);
|
||||
PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
|
||||
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
|
||||
JSObject::UpdateMapCodeCache(receiver, name, code);
|
||||
JSObject::UpdateMapCodeCache(map_holder, name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
@ -290,10 +311,12 @@ Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<JSObject> holder,
|
||||
Handle<JSFunction> value) {
|
||||
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||
InlineCacheHolderFlag cache_holder =
|
||||
IC::GetCodeCacheForObject(*receiver, *holder);
|
||||
Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC,
|
||||
Code::CONSTANT_FUNCTION);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
||||
@ -302,7 +325,7 @@ Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name,
|
||||
compiler.CompileLoadConstant(name, receiver, holder, value);
|
||||
PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
|
||||
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
|
||||
JSObject::UpdateMapCodeCache(receiver, name, code);
|
||||
JSObject::UpdateMapCodeCache(map_holder, name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
@ -310,10 +333,12 @@ Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name,
|
||||
Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<String> name,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<JSObject> holder) {
|
||||
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||
InlineCacheHolderFlag cache_holder =
|
||||
IC::GetCodeCacheForObject(*receiver, *holder);
|
||||
Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
|
||||
Code::Flags flags =
|
||||
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::INTERCEPTOR);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
||||
@ -321,7 +346,7 @@ Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<String> name,
|
||||
Handle<Code> code = compiler.CompileLoadInterceptor(receiver, holder, name);
|
||||
PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
|
||||
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
|
||||
JSObject::UpdateMapCodeCache(receiver, name, code);
|
||||
JSObject::UpdateMapCodeCache(map_holder, name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
@ -331,10 +356,12 @@ Handle<Code> StubCache::ComputeKeyedLoadCallback(
|
||||
Handle<JSObject> receiver,
|
||||
Handle<JSObject> holder,
|
||||
Handle<AccessorInfo> callback) {
|
||||
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||
InlineCacheHolderFlag cache_holder =
|
||||
IC::GetCodeCacheForObject(*receiver, *holder);
|
||||
Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
|
||||
Code::Flags flags =
|
||||
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::CALLBACKS);
|
||||
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
|
||||
Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags),
|
||||
isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
||||
@ -343,7 +370,7 @@ Handle<Code> StubCache::ComputeKeyedLoadCallback(
|
||||
compiler.CompileLoadCallback(name, receiver, holder, callback);
|
||||
PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
|
||||
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
|
||||
JSObject::UpdateMapCodeCache(receiver, name, code);
|
||||
JSObject::UpdateMapCodeCache(map_holder, name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -608,7 +608,8 @@ class LoadStubCompiler: public StubCompiler {
|
||||
|
||||
Handle<Code> CompileLoadNonexistent(Handle<String> name,
|
||||
Handle<JSObject> object,
|
||||
Handle<JSObject> last);
|
||||
Handle<JSObject> last,
|
||||
Handle<GlobalObject> global);
|
||||
|
||||
Handle<Code> CompileLoadField(Handle<JSObject> object,
|
||||
Handle<JSObject> holder,
|
||||
|
@ -2789,9 +2789,11 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
|
||||
Handle<JSObject> object,
|
||||
Handle<JSObject> last) {
|
||||
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
|
||||
Handle<String> name,
|
||||
Handle<JSObject> object,
|
||||
Handle<JSObject> last,
|
||||
Handle<GlobalObject> global) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : receiver
|
||||
// -- rcx : name
|
||||
@ -2805,13 +2807,21 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
|
||||
// Check the maps of the full prototype chain. Also check that
|
||||
// global property cells up to (but not including) the last object
|
||||
// in the prototype chain are empty.
|
||||
CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss);
|
||||
Register scratch = rdx;
|
||||
Register result =
|
||||
CheckPrototypes(object, rax, last, rbx, scratch, rdi, name, &miss);
|
||||
|
||||
// If the last object in the prototype chain is a global object,
|
||||
// check that the global property cell is empty.
|
||||
if (last->IsGlobalObject()) {
|
||||
GenerateCheckPropertyCell(
|
||||
masm(), Handle<GlobalObject>::cast(last), name, rdx, &miss);
|
||||
if (!global.is_null()) {
|
||||
GenerateCheckPropertyCell(masm(), global, name, scratch, &miss);
|
||||
}
|
||||
|
||||
if (!last->HasFastProperties()) {
|
||||
__ movq(scratch, FieldOperand(result, HeapObject::kMapOffset));
|
||||
__ movq(scratch, FieldOperand(scratch, Map::kPrototypeOffset));
|
||||
__ Cmp(scratch, isolate()->factory()->null_value());
|
||||
__ j(not_equal, &miss);
|
||||
}
|
||||
|
||||
// Return undefined if maps of the full prototype chain are still the
|
||||
|
Loading…
Reference in New Issue
Block a user