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(
}
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
......
......@@ -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) {
......
This diff is collapsed.
......@@ -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
......
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