Commit b1e5157e authored by verwaest@chromium.org's avatar verwaest@chromium.org

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
parent 1c1fdc7d
...@@ -2894,9 +2894,11 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal( ...@@ -2894,9 +2894,11 @@ Handle<Code> StoreStubCompiler::CompileStoreGlobal(
} }
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
Handle<JSObject> object, Handle<String> name,
Handle<JSObject> last) { Handle<JSObject> object,
Handle<JSObject> last,
Handle<GlobalObject> global) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : receiver // -- r0 : receiver
// -- lr : return address // -- lr : return address
...@@ -2906,14 +2908,24 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, ...@@ -2906,14 +2908,24 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
// Check that receiver is not a smi. // Check that receiver is not a smi.
__ JumpIfSmi(r0, &miss); __ JumpIfSmi(r0, &miss);
Register scratch = r1;
// Check the maps of the full prototype chain. // 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, // If the last object in the prototype chain is a global object,
// check that the global property cell is empty. // check that the global property cell is empty.
if (last->IsGlobalObject()) { if (!global.is_null()) {
GenerateCheckPropertyCell( GenerateCheckPropertyCell(masm(), global, name, scratch, &miss);
masm(), Handle<GlobalObject>::cast(last), name, r1, &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 // Return undefined if maps of the full prototype chain are still the
......
...@@ -2964,9 +2964,11 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( ...@@ -2964,9 +2964,11 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
} }
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
Handle<JSObject> object, Handle<String> name,
Handle<JSObject> last) { Handle<JSObject> object,
Handle<JSObject> last,
Handle<GlobalObject> global) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- ecx : name // -- ecx : name
// -- edx : receiver // -- edx : receiver
...@@ -2977,18 +2979,25 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, ...@@ -2977,18 +2979,25 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
// Check that the receiver isn't a smi. // Check that the receiver isn't a smi.
__ JumpIfSmi(edx, &miss); __ JumpIfSmi(edx, &miss);
ASSERT(last->IsGlobalObject() || last->HasFastProperties()); Register scratch = eax;
// Check the maps of the full prototype chain. Also check that // Check the maps of the full prototype chain. Also check that
// global property cells up to (but not including) the last object // global property cells up to (but not including) the last object
// in the prototype chain are empty. // 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, // If the last object in the prototype chain is a global object,
// check that the global property cell is empty. // check that the global property cell is empty.
if (last->IsGlobalObject()) { if (!global.is_null()) {
GenerateCheckPropertyCell( GenerateCheckPropertyCell(masm(), global, name, scratch, &miss);
masm(), Handle<GlobalObject>::cast(last), name, eax, &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 // Return undefined if maps of the full prototype chain are still the
......
...@@ -169,26 +169,6 @@ Address IC::OriginalCodeAddress() const { ...@@ -169,26 +169,6 @@ Address IC::OriginalCodeAddress() const {
#endif #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, static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
Object* receiver, Object* receiver,
Object* name) { Object* name) {
...@@ -700,14 +680,6 @@ void CallICBase::UpdateCaches(LookupResult* lookup, ...@@ -700,14 +680,6 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
// Bail out if we didn't find a result. // Bail out if we didn't find a result.
if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 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. // Compute the number of arguments.
int argc = target()->arguments_count(); int argc = target()->arguments_count();
Handle<Code> code; Handle<Code> code;
...@@ -1023,8 +995,6 @@ void LoadIC::UpdateCaches(LookupResult* lookup, ...@@ -1023,8 +995,6 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
// deal with non-JS objects here. // deal with non-JS objects here.
if (!object->IsJSObject()) return; if (!object->IsJSObject()) return;
if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
Handle<JSObject> receiver = Handle<JSObject>::cast(object); Handle<JSObject> receiver = Handle<JSObject>::cast(object);
Handle<Code> code; Handle<Code> code;
if (state == UNINITIALIZED) { if (state == UNINITIALIZED) {
......
This diff is collapsed.
...@@ -608,7 +608,8 @@ class LoadStubCompiler: public StubCompiler { ...@@ -608,7 +608,8 @@ class LoadStubCompiler: public StubCompiler {
Handle<Code> CompileLoadNonexistent(Handle<String> name, Handle<Code> CompileLoadNonexistent(Handle<String> name,
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSObject> last); Handle<JSObject> last,
Handle<GlobalObject> global);
Handle<Code> CompileLoadField(Handle<JSObject> object, Handle<Code> CompileLoadField(Handle<JSObject> object,
Handle<JSObject> holder, Handle<JSObject> holder,
......
...@@ -2789,9 +2789,11 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( ...@@ -2789,9 +2789,11 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
} }
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
Handle<JSObject> object, Handle<String> name,
Handle<JSObject> last) { Handle<JSObject> object,
Handle<JSObject> last,
Handle<GlobalObject> global) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver // -- rax : receiver
// -- rcx : name // -- rcx : name
...@@ -2805,13 +2807,21 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, ...@@ -2805,13 +2807,21 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
// Check the maps of the full prototype chain. Also check that // Check the maps of the full prototype chain. Also check that
// global property cells up to (but not including) the last object // global property cells up to (but not including) the last object
// in the prototype chain are empty. // 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, // If the last object in the prototype chain is a global object,
// check that the global property cell is empty. // check that the global property cell is empty.
if (last->IsGlobalObject()) { if (!global.is_null()) {
GenerateCheckPropertyCell( GenerateCheckPropertyCell(masm(), global, name, scratch, &miss);
masm(), Handle<GlobalObject>::cast(last), name, rdx, &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 // Return undefined if maps of the full prototype chain are still the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment