Commit 806c15e4 authored by ager@chromium.org's avatar ager@chromium.org

Remove the LookupResult IsValid method because it is confusing.

Replaced IsValid by IsPropertyOrTransition and used IsProperty in most
of the places where IsValid was used before.  Most of the time when
inspecting a lookup result we really want to know if there is a real
property present.  Only for stores are we interested in transitions.

BUG=http://crbug.com/20104
TEST=cctest/test-api/NamedInterceptorMapTransitionRead
Review URL: http://codereview.chromium.org/647015

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3901 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0d6fe0a4
...@@ -2207,7 +2207,7 @@ Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain( ...@@ -2207,7 +2207,7 @@ Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
i::Handle<i::String> key_obj = Utils::OpenHandle(*key); i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
i::LookupResult lookup; i::LookupResult lookup;
self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup); self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
if (lookup.IsValid()) { if (lookup.IsProperty()) {
PropertyAttributes attributes; PropertyAttributes attributes;
i::Handle<i::Object> result(self_obj->GetProperty(*self_obj, i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
&lookup, &lookup,
...@@ -2226,7 +2226,7 @@ Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) { ...@@ -2226,7 +2226,7 @@ Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
i::Handle<i::String> key_obj = Utils::OpenHandle(*key); i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
i::LookupResult lookup; i::LookupResult lookup;
self_obj->LookupRealNamedProperty(*key_obj, &lookup); self_obj->LookupRealNamedProperty(*key_obj, &lookup);
if (lookup.IsValid()) { if (lookup.IsProperty()) {
PropertyAttributes attributes; PropertyAttributes attributes;
i::Handle<i::Object> result(self_obj->GetProperty(*self_obj, i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
&lookup, &lookup,
......
...@@ -579,7 +579,7 @@ static void CompileLoadInterceptor(LoadInterceptorCompiler* compiler, ...@@ -579,7 +579,7 @@ static void CompileLoadInterceptor(LoadInterceptorCompiler* compiler,
stub_compiler->CheckPrototypes(object, receiver, holder, stub_compiler->CheckPrototypes(object, receiver, holder,
scratch1, scratch2, name, miss); scratch1, scratch2, name, miss);
if (lookup->IsValid() && lookup->IsCacheable()) { if (lookup->IsProperty() && lookup->IsCacheable()) {
compiler->CompileCacheable(masm, compiler->CompileCacheable(masm,
stub_compiler, stub_compiler,
receiver, receiver,
...@@ -985,7 +985,7 @@ Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, ...@@ -985,7 +985,7 @@ Object* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// If we call a constant function when the interceptor returns // If we call a constant function when the interceptor returns
// the no-result sentinel, generate code that optimizes this case. // the no-result sentinel, generate code that optimizes this case.
if (lookup.IsValid() && if (lookup.IsProperty() &&
lookup.IsCacheable() && lookup.IsCacheable() &&
lookup.type() == CONSTANT_FUNCTION && lookup.type() == CONSTANT_FUNCTION &&
lookup.GetConstantFunction()->is_compiled() && lookup.GetConstantFunction()->is_compiled() &&
......
...@@ -723,11 +723,11 @@ void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template, ...@@ -723,11 +723,11 @@ void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
#ifdef DEBUG #ifdef DEBUG
LookupResult lookup; LookupResult lookup;
result->LocalLookup(Heap::callee_symbol(), &lookup); result->LocalLookup(Heap::callee_symbol(), &lookup);
ASSERT(lookup.IsValid() && (lookup.type() == FIELD)); ASSERT(lookup.IsProperty() && (lookup.type() == FIELD));
ASSERT(lookup.GetFieldIndex() == Heap::arguments_callee_index); ASSERT(lookup.GetFieldIndex() == Heap::arguments_callee_index);
result->LocalLookup(Heap::length_symbol(), &lookup); result->LocalLookup(Heap::length_symbol(), &lookup);
ASSERT(lookup.IsValid() && (lookup.type() == FIELD)); ASSERT(lookup.IsProperty() && (lookup.type() == FIELD));
ASSERT(lookup.GetFieldIndex() == Heap::arguments_length_index); ASSERT(lookup.GetFieldIndex() == Heap::arguments_length_index);
ASSERT(result->map()->inobject_properties() > Heap::arguments_callee_index); ASSERT(result->map()->inobject_properties() > Heap::arguments_callee_index);
...@@ -1352,7 +1352,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from, ...@@ -1352,7 +1352,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
LookupResult result; LookupResult result;
to->LocalLookup(descs->GetKey(i), &result); to->LocalLookup(descs->GetKey(i), &result);
// If the property is already there we skip it // If the property is already there we skip it
if (result.IsValid()) continue; if (result.IsProperty()) continue;
HandleScope inner; HandleScope inner;
Handle<DescriptorArray> inst_descs = Handle<DescriptorArray> inst_descs =
Handle<DescriptorArray>(to->map()->instance_descriptors()); Handle<DescriptorArray>(to->map()->instance_descriptors());
...@@ -1389,7 +1389,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from, ...@@ -1389,7 +1389,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
// If the property is already there we skip it. // If the property is already there we skip it.
LookupResult result; LookupResult result;
to->LocalLookup(String::cast(raw_key), &result); to->LocalLookup(String::cast(raw_key), &result);
if (result.IsValid()) continue; if (result.IsProperty()) continue;
// Set the property. // Set the property.
Handle<String> key = Handle<String>(String::cast(raw_key)); Handle<String> key = Handle<String>(String::cast(raw_key));
Handle<Object> value = Handle<Object>(properties->ValueAt(i)); Handle<Object> value = Handle<Object>(properties->ValueAt(i));
......
...@@ -220,7 +220,7 @@ void FastCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) { ...@@ -220,7 +220,7 @@ void FastCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) {
if (info()->has_global_object()) { if (info()->has_global_object()) {
LookupResult lookup; LookupResult lookup;
info()->global_object()->Lookup(*expr->name(), &lookup); info()->global_object()->Lookup(*expr->name(), &lookup);
if (!lookup.IsValid()) { if (!lookup.IsProperty()) {
BAILOUT("Non-existing global variable"); BAILOUT("Non-existing global variable");
} }
// We do not handle global variables with accessors or interceptors. // We do not handle global variables with accessors or interceptors.
...@@ -284,7 +284,7 @@ void FastCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) { ...@@ -284,7 +284,7 @@ void FastCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) {
Handle<String> name = Handle<String>::cast(key->handle()); Handle<String> name = Handle<String>::cast(key->handle());
LookupResult lookup; LookupResult lookup;
receiver->Lookup(*name, &lookup); receiver->Lookup(*name, &lookup);
if (!lookup.IsValid()) { if (!lookup.IsProperty()) {
BAILOUT("Assigned property not found at compile time"); BAILOUT("Assigned property not found at compile time");
} }
if (lookup.holder() != *receiver) BAILOUT("Non-own property assignment"); if (lookup.holder() != *receiver) BAILOUT("Non-own property assignment");
...@@ -322,7 +322,7 @@ void FastCodeGenSyntaxChecker::VisitProperty(Property* expr) { ...@@ -322,7 +322,7 @@ void FastCodeGenSyntaxChecker::VisitProperty(Property* expr) {
Handle<String> name = Handle<String>::cast(key->handle()); Handle<String> name = Handle<String>::cast(key->handle());
LookupResult lookup; LookupResult lookup;
receiver->Lookup(*name, &lookup); receiver->Lookup(*name, &lookup);
if (!lookup.IsValid()) { if (!lookup.IsProperty()) {
BAILOUT("Referenced property not found at compile time"); BAILOUT("Referenced property not found at compile time");
} }
if (lookup.holder() != *receiver) BAILOUT("Non-own property reference"); if (lookup.holder() != *receiver) BAILOUT("Non-own property reference");
...@@ -586,7 +586,7 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { ...@@ -586,7 +586,7 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
info()->global_object()->Lookup(*expr->name(), &lookup); info()->global_object()->Lookup(*expr->name(), &lookup);
// We only support normal (non-accessor/interceptor) DontDelete properties // We only support normal (non-accessor/interceptor) DontDelete properties
// for now. // for now.
ASSERT(lookup.IsValid()); ASSERT(lookup.IsProperty());
ASSERT_EQ(NORMAL, lookup.type()); ASSERT_EQ(NORMAL, lookup.type());
ASSERT(lookup.IsDontDelete()); ASSERT(lookup.IsDontDelete());
Handle<Object> cell(info()->global_object()->GetPropertyCell(&lookup)); Handle<Object> cell(info()->global_object()->GetPropertyCell(&lookup));
......
...@@ -323,7 +323,7 @@ static void CompileLoadInterceptor(Compiler* compiler, ...@@ -323,7 +323,7 @@ static void CompileLoadInterceptor(Compiler* compiler,
stub_compiler->CheckPrototypes(object, receiver, holder, stub_compiler->CheckPrototypes(object, receiver, holder,
scratch1, scratch2, name, miss); scratch1, scratch2, name, miss);
if (lookup->IsValid() && lookup->IsCacheable()) { if (lookup->IsProperty() && lookup->IsCacheable()) {
compiler->CompileCacheable(masm, compiler->CompileCacheable(masm,
stub_compiler, stub_compiler,
receiver, receiver,
...@@ -484,7 +484,7 @@ class CallOptimization BASE_EMBEDDED { ...@@ -484,7 +484,7 @@ class CallOptimization BASE_EMBEDDED {
is_simple_api_call_(false), is_simple_api_call_(false),
expected_receiver_type_(NULL), expected_receiver_type_(NULL),
api_call_info_(NULL) { api_call_info_(NULL) {
if (!lookup->IsValid() || !lookup->IsCacheable()) return; if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
// We only optimize constant function calls. // We only optimize constant function calls.
if (lookup->type() != CONSTANT_FUNCTION) return; if (lookup->type() != CONSTANT_FUNCTION) return;
......
...@@ -330,10 +330,11 @@ static void LookupForRead(Object* object, ...@@ -330,10 +330,11 @@ static void LookupForRead(Object* object,
while (true) { while (true) {
object->Lookup(name, lookup); object->Lookup(name, lookup);
// Besides normal conditions (property not found or it's not // Besides normal conditions (property not found or it's not
// an interceptor), bail out of lookup is not cacheable: we won't // an interceptor), bail out if lookup is not cacheable: we won't
// be able to IC it anyway and regular lookup should work fine. // be able to IC it anyway and regular lookup should work fine.
if (lookup->IsNotFound() || lookup->type() != INTERCEPTOR || if (!lookup->IsFound()
!lookup->IsCacheable()) { || (lookup->type() != INTERCEPTOR)
|| !lookup->IsCacheable()) {
return; return;
} }
...@@ -343,7 +344,7 @@ static void LookupForRead(Object* object, ...@@ -343,7 +344,7 @@ static void LookupForRead(Object* object,
} }
holder->LocalLookupRealNamedProperty(name, lookup); holder->LocalLookupRealNamedProperty(name, lookup);
if (lookup->IsValid()) { if (lookup->IsProperty()) {
ASSERT(lookup->type() != INTERCEPTOR); ASSERT(lookup->type() != INTERCEPTOR);
return; return;
} }
...@@ -422,7 +423,7 @@ Object* CallIC::LoadFunction(State state, ...@@ -422,7 +423,7 @@ Object* CallIC::LoadFunction(State state,
LookupResult lookup; LookupResult lookup;
LookupForRead(*object, *name, &lookup); LookupForRead(*object, *name, &lookup);
if (!lookup.IsValid()) { if (!lookup.IsProperty()) {
// If the object does not have the requested property, check which // If the object does not have the requested property, check which
// exception we need to throw. // exception we need to throw.
if (IsContextual(object)) { if (IsContextual(object)) {
...@@ -493,7 +494,7 @@ void CallIC::UpdateCaches(LookupResult* lookup, ...@@ -493,7 +494,7 @@ void CallIC::UpdateCaches(LookupResult* lookup,
Handle<String> name) { Handle<String> name) {
ASSERT(lookup->IsLoaded()); ASSERT(lookup->IsLoaded());
// Bail out if we didn't find a result. // Bail out if we didn't find a result.
if (!lookup->IsValid() || !lookup->IsCacheable()) return; if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
// Compute the number of arguments. // Compute the number of arguments.
int argc = target()->arguments_count(); int argc = target()->arguments_count();
...@@ -642,8 +643,8 @@ Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) { ...@@ -642,8 +643,8 @@ Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) {
LookupResult lookup; LookupResult lookup;
LookupForRead(*object, *name, &lookup); LookupForRead(*object, *name, &lookup);
// If lookup is invalid, check if we need to throw an exception. // If we did not find a property, check if we need to throw an exception.
if (!lookup.IsValid()) { if (!lookup.IsProperty()) {
if (FLAG_strict || IsContextual(object)) { if (FLAG_strict || IsContextual(object)) {
return ReferenceError("not_defined", name); return ReferenceError("not_defined", name);
} }
...@@ -653,7 +654,7 @@ Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) { ...@@ -653,7 +654,7 @@ Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) {
bool can_be_inlined = bool can_be_inlined =
FLAG_use_ic && FLAG_use_ic &&
state == PREMONOMORPHIC && state == PREMONOMORPHIC &&
lookup.IsValid() && lookup.IsProperty() &&
lookup.IsLoaded() && lookup.IsLoaded() &&
lookup.IsCacheable() && lookup.IsCacheable() &&
lookup.holder() == *object && lookup.holder() == *object &&
...@@ -681,7 +682,7 @@ Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) { ...@@ -681,7 +682,7 @@ Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) {
} }
PropertyAttributes attr; PropertyAttributes attr;
if (lookup.IsValid() && lookup.type() == INTERCEPTOR) { if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
// Get the property. // Get the property.
Object* result = object->GetProperty(*object, &lookup, *name, &attr); Object* result = object->GetProperty(*object, &lookup, *name, &attr);
if (result->IsFailure()) return result; if (result->IsFailure()) return result;
...@@ -704,7 +705,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup, ...@@ -704,7 +705,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
Handle<String> name) { Handle<String> name) {
ASSERT(lookup->IsLoaded()); ASSERT(lookup->IsLoaded());
// Bail out if we didn't find a result. // Bail out if we didn't find a result.
if (!lookup->IsValid() || !lookup->IsCacheable()) return; if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
// Loading properties from values is not common, so don't try to // Loading properties from values is not common, so don't try to
// deal with non-JS objects here. // deal with non-JS objects here.
...@@ -857,8 +858,8 @@ Object* KeyedLoadIC::Load(State state, ...@@ -857,8 +858,8 @@ Object* KeyedLoadIC::Load(State state,
LookupResult lookup; LookupResult lookup;
LookupForRead(*object, *name, &lookup); LookupForRead(*object, *name, &lookup);
// If lookup is invalid, check if we need to throw an exception. // If we did not find a property, check if we need to throw an exception.
if (!lookup.IsValid()) { if (!lookup.IsProperty()) {
if (FLAG_strict || IsContextual(object)) { if (FLAG_strict || IsContextual(object)) {
return ReferenceError("not_defined", name); return ReferenceError("not_defined", name);
} }
...@@ -869,7 +870,7 @@ Object* KeyedLoadIC::Load(State state, ...@@ -869,7 +870,7 @@ Object* KeyedLoadIC::Load(State state,
} }
PropertyAttributes attr; PropertyAttributes attr;
if (lookup.IsValid() && lookup.type() == INTERCEPTOR) { if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
// Get the property. // Get the property.
Object* result = object->GetProperty(*object, &lookup, *name, &attr); Object* result = object->GetProperty(*object, &lookup, *name, &attr);
if (result->IsFailure()) return result; if (result->IsFailure()) return result;
...@@ -921,7 +922,7 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, ...@@ -921,7 +922,7 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
Handle<Object> object, Handle<String> name) { Handle<Object> object, Handle<String> name) {
ASSERT(lookup->IsLoaded()); ASSERT(lookup->IsLoaded());
// Bail out if we didn't find a result. // Bail out if we didn't find a result.
if (!lookup->IsValid() || !lookup->IsCacheable()) return; if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
if (!object->IsJSObject()) return; if (!object->IsJSObject()) return;
Handle<JSObject> receiver = Handle<JSObject>::cast(object); Handle<JSObject> receiver = Handle<JSObject>::cast(object);
...@@ -994,7 +995,7 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, ...@@ -994,7 +995,7 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
static bool StoreICableLookup(LookupResult* lookup) { static bool StoreICableLookup(LookupResult* lookup) {
// Bail out if we didn't find a result. // Bail out if we didn't find a result.
if (!lookup->IsValid() || !lookup->IsCacheable()) return false; if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false;
// If the property is read-only, we leave the IC in its current // If the property is read-only, we leave the IC in its current
// state. // state.
...@@ -1214,7 +1215,7 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup, ...@@ -1214,7 +1215,7 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
if (receiver->IsJSGlobalProxy()) return; if (receiver->IsJSGlobalProxy()) return;
// Bail out if we didn't find a result. // Bail out if we didn't find a result.
if (!lookup->IsValid() || !lookup->IsCacheable()) return; if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return;
// If the property is read-only, we leave the IC in its current // If the property is read-only, we leave the IC in its current
// state. // state.
......
This diff is collapsed.
...@@ -33,7 +33,7 @@ namespace internal { ...@@ -33,7 +33,7 @@ namespace internal {
#ifdef DEBUG #ifdef DEBUG
void LookupResult::Print() { void LookupResult::Print() {
if (!IsValid()) { if (!IsFound()) {
PrintF("Not Found\n"); PrintF("Not Found\n");
return; return;
} }
......
...@@ -201,23 +201,17 @@ class LookupResult BASE_EMBEDDED { ...@@ -201,23 +201,17 @@ class LookupResult BASE_EMBEDDED {
} }
JSObject* holder() { JSObject* holder() {
ASSERT(IsValid()); ASSERT(IsFound());
return holder_; return holder_;
} }
PropertyType type() { PropertyType type() {
ASSERT(IsValid()); ASSERT(IsFound());
return details_.type(); return details_.type();
} }
bool IsTransitionType() {
PropertyType t = type();
if (t == MAP_TRANSITION || t == CONSTANT_TRANSITION) return true;
return false;
}
PropertyAttributes GetAttributes() { PropertyAttributes GetAttributes() {
ASSERT(IsValid()); ASSERT(IsFound());
return details_.attributes(); return details_.attributes();
} }
...@@ -229,14 +223,17 @@ class LookupResult BASE_EMBEDDED { ...@@ -229,14 +223,17 @@ class LookupResult BASE_EMBEDDED {
bool IsDontDelete() { return details_.IsDontDelete(); } bool IsDontDelete() { return details_.IsDontDelete(); }
bool IsDontEnum() { return details_.IsDontEnum(); } bool IsDontEnum() { return details_.IsDontEnum(); }
bool IsDeleted() { return details_.IsDeleted(); } bool IsDeleted() { return details_.IsDeleted(); }
bool IsFound() { return lookup_type_ != NOT_FOUND; }
bool IsValid() { return lookup_type_ != NOT_FOUND; } // Is the result is a property excluding transitions and the null
bool IsNotFound() { return lookup_type_ == NOT_FOUND; } // descriptor?
// Tells whether the result is a property.
// Excluding transitions and the null descriptor.
bool IsProperty() { bool IsProperty() {
return IsValid() && type() < FIRST_PHANTOM_PROPERTY_TYPE; return IsFound() && (type() < FIRST_PHANTOM_PROPERTY_TYPE);
}
// Is the result a property or a transition?
bool IsPropertyOrTransition() {
return IsFound() && (type() != NULL_DESCRIPTOR);
} }
bool IsCacheable() { return cacheable_; } bool IsCacheable() { return cacheable_; }
......
...@@ -2895,7 +2895,7 @@ static Object* Runtime_DefineOrRedefineAccessorProperty(Arguments args) { ...@@ -2895,7 +2895,7 @@ static Object* Runtime_DefineOrRedefineAccessorProperty(Arguments args) {
// If an existing property is either FIELD, NORMAL or CONSTANT_FUNCTION // If an existing property is either FIELD, NORMAL or CONSTANT_FUNCTION
// delete it to avoid running into trouble in DefineAccessor, which // delete it to avoid running into trouble in DefineAccessor, which
// handles this incorrectly if the property is readonly (does nothing) // handles this incorrectly if the property is readonly (does nothing)
if (result.IsValid() && if (result.IsProperty() &&
(result.type() == FIELD || result.type() == NORMAL (result.type() == FIELD || result.type() == NORMAL
|| result.type() == CONSTANT_FUNCTION)) { || result.type() == CONSTANT_FUNCTION)) {
obj->DeleteProperty(name, JSObject::NORMAL_DELETION); obj->DeleteProperty(name, JSObject::NORMAL_DELETION);
......
...@@ -1070,11 +1070,13 @@ Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) { ...@@ -1070,11 +1070,13 @@ Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) {
return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL)); return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
} }
void StubCompiler::LookupPostInterceptor(JSObject* holder, void StubCompiler::LookupPostInterceptor(JSObject* holder,
String* name, String* name,
LookupResult* lookup) { LookupResult* lookup) {
holder->LocalLookupRealNamedProperty(name, lookup); holder->LocalLookupRealNamedProperty(name, lookup);
if (lookup->IsNotFound()) { if (!lookup->IsProperty()) {
lookup->NotFound();
Object* proto = holder->GetPrototype(); Object* proto = holder->GetPrototype();
if (proto != Heap::null_value()) { if (proto != Heap::null_value()) {
proto->Lookup(name, lookup); proto->Lookup(name, lookup);
......
...@@ -399,7 +399,7 @@ static void CompileLoadInterceptor(Compiler* compiler, ...@@ -399,7 +399,7 @@ static void CompileLoadInterceptor(Compiler* compiler,
stub_compiler->CheckPrototypes(object, receiver, holder, stub_compiler->CheckPrototypes(object, receiver, holder,
scratch1, scratch2, name, miss); scratch1, scratch2, name, miss);
if (lookup->IsValid() && lookup->IsCacheable()) { if (lookup->IsProperty() && lookup->IsCacheable()) {
compiler->CompileCacheable(masm, compiler->CompileCacheable(masm,
stub_compiler, stub_compiler,
receiver, receiver,
......
...@@ -2528,6 +2528,33 @@ THREADED_TEST(NamedInterceptorPropertyRead) { ...@@ -2528,6 +2528,33 @@ THREADED_TEST(NamedInterceptorPropertyRead) {
} }
static v8::Handle<Value> SetXOnPrototypeGetter(Local<String> property,
const AccessorInfo& info) {
// Set x on the prototype object and do not handle the get request.
v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
v8::Handle<v8::Object>::Cast(proto)->Set(v8_str("x"), v8::Integer::New(23));
return v8::Handle<Value>();
}
// This is a regression test for http://crbug.com/20104. Map
// transitions should not interfere with post interceptor lookup.
THREADED_TEST(NamedInterceptorMapTransitionRead) {
v8::HandleScope scope;
Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New();
Local<v8::ObjectTemplate> instance_template
= function_template->InstanceTemplate();
instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
LocalContext context;
context->Global()->Set(v8_str("F"), function_template->GetFunction());
// Create an instance of F and introduce a map transition for x.
CompileRun("var o = new F(); o.x = 23;");
// Create an instance of F and invoke the getter. The result should be 23.
Local<Value> result = CompileRun("o = new F(); o.x");
CHECK_EQ(result->Int32Value(), 23);
}
static v8::Handle<Value> IndexedPropertyGetter(uint32_t index, static v8::Handle<Value> IndexedPropertyGetter(uint32_t index,
const AccessorInfo& info) { const AccessorInfo& info) {
ApiTestFuzzer::Fuzz(); ApiTestFuzzer::Fuzz();
......
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