Make the GC aware of JSReceiver pointers in LookupResults.

The LookupResult utility class is used in handlified code, but it can
contain a raw pointer to the lookup's holder object.  Create a per-thread
stack of live LookupResults and iterate all the live ones on GC.

R=vegorov@chromium.org,erik.corry@gmail.com
BUG=
TEST=

Review URL: http://codereview.chromium.org/8341009

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9676 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2011-10-18 11:18:55 +00:00
parent 96a2c24a16
commit 56c763f023
20 changed files with 135 additions and 95 deletions

View File

@ -3110,7 +3110,7 @@ Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
ENTER_V8(isolate);
i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
i::LookupResult lookup;
i::LookupResult lookup(isolate);
self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup);
}
@ -3123,7 +3123,7 @@ Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
ENTER_V8(isolate);
i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
i::LookupResult lookup;
i::LookupResult lookup(isolate);
self_obj->LookupRealNamedProperty(*key_obj, &lookup);
return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup);
}

View File

@ -2320,7 +2320,7 @@ void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
Register object,
Handle<Map> type,
Handle<String> name) {
LookupResult lookup;
LookupResult lookup(isolate());
type->LookupInDescriptors(NULL, *name, &lookup);
ASSERT(lookup.IsProperty() &&
(lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));

View File

@ -2504,7 +2504,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// Get the number of arguments.
const int argc = arguments().immediate();
LookupResult lookup;
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
// Get the receiver from the stack.
@ -2908,7 +2908,7 @@ MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
// -----------------------------------
Label miss;
LookupResult lookup;
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
GenerateLoadInterceptor(object,
holder,
@ -3066,7 +3066,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
__ cmp(r0, Operand(Handle<String>(name)));
__ b(ne, &miss);
LookupResult lookup;
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
GenerateLoadInterceptor(receiver,
holder,

View File

@ -720,7 +720,7 @@ bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) {
holder_ = Handle<JSObject>::null();
}
while (true) {
LookupResult lookup;
LookupResult lookup(type->GetIsolate());
type->LookupInDescriptors(NULL, *name, &lookup);
// If the function wasn't found directly in the map, we start
// looking upwards through the prototype chain.

View File

@ -1065,7 +1065,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
DONT_ENUM);
#ifdef DEBUG
LookupResult lookup;
LookupResult lookup(isolate);
result->LocalLookup(heap->callee_symbol(), &lookup);
ASSERT(lookup.IsProperty() && (lookup.type() == FIELD));
ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsCalleeIndex);
@ -1162,7 +1162,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
DONT_ENUM);
#ifdef DEBUG
LookupResult lookup;
LookupResult lookup(isolate);
result->LocalLookup(heap->length_symbol(), &lookup);
ASSERT(lookup.IsProperty() && (lookup.type() == FIELD));
ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsLengthIndex);
@ -2088,7 +2088,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
break;
}
case CALLBACKS: {
LookupResult result;
LookupResult result(isolate());
to->LocalLookup(descs->GetKey(i), &result);
// If the property is already there we skip it
if (result.IsProperty()) continue;
@ -2126,7 +2126,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
if (properties->IsKey(raw_key)) {
ASSERT(raw_key->IsString());
// If the property is already there we skip it.
LookupResult result;
LookupResult result(isolate());
to->LocalLookup(String::cast(raw_key), &result);
if (result.IsProperty()) continue;
// Set the property.

View File

@ -1390,7 +1390,7 @@ HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
i < types->length() && types_.length() < kMaxLoadPolymorphism;
++i) {
Handle<Map> map = types->at(i);
LookupResult lookup;
LookupResult lookup(map->GetIsolate());
map->LookupInDescriptors(NULL, *name, &lookup);
if (lookup.IsProperty()) {
switch (lookup.type()) {

View File

@ -3156,7 +3156,7 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
return ast_context()->ReturnInstruction(instr, expr->id());
}
LookupResult lookup;
LookupResult lookup(isolate());
GlobalPropertyAccess type =
LookupGlobalProperty(variable, &lookup, false);
@ -3471,7 +3471,7 @@ HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
Handle<String> name = Handle<String>::cast(key->handle());
ASSERT(!name.is_null());
LookupResult lookup;
LookupResult lookup(isolate());
SmallMapList* types = expr->GetReceiverTypes();
bool is_monomorphic = expr->IsMonomorphic() &&
ComputeStoredField(types->first(), name, &lookup);
@ -3495,7 +3495,7 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
HBasicBlock* join = NULL;
for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
Handle<Map> map = types->at(i);
LookupResult lookup;
LookupResult lookup(isolate());
if (ComputeStoredField(map, name, &lookup)) {
if (count == 0) {
AddInstruction(new(zone()) HCheckNonSmi(object)); // Only needed once.
@ -3578,7 +3578,7 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
ASSERT(!name.is_null());
SmallMapList* types = expr->GetReceiverTypes();
LookupResult lookup;
LookupResult lookup(isolate());
if (expr->IsMonomorphic()) {
instr = BuildStoreNamed(object, value, expr);
@ -3623,7 +3623,7 @@ void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
HValue* value,
int position,
int ast_id) {
LookupResult lookup;
LookupResult lookup(isolate());
GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
if (type == kUseCell) {
Handle<GlobalObject> global(info()->global_object());
@ -3938,7 +3938,7 @@ HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj,
Property* expr,
Handle<Map> map,
Handle<String> name) {
LookupResult lookup;
LookupResult lookup(isolate());
map->LookupInDescriptors(NULL, *name, &lookup);
if (lookup.IsProperty() && lookup.type() == FIELD) {
return BuildLoadNamedField(obj,
@ -5012,7 +5012,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
// If there is a global property cell for the name at compile time and
// access check is not enabled we assume that the function will not change
// and generate optimized code for calling the function.
LookupResult lookup;
LookupResult lookup(isolate());
GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
if (type == kUseCell &&
!info()->global_object()->IsAccessCheckNeeded()) {
@ -5869,7 +5869,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
!info()->global_object()->IsAccessCheckNeeded()) {
Handle<String> name = proxy->name();
Handle<GlobalObject> global(info()->global_object());
LookupResult lookup;
LookupResult lookup(isolate());
global->Lookup(*name, &lookup);
if (lookup.IsProperty() &&
lookup.type() == NORMAL &&

View File

@ -2185,7 +2185,7 @@ void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
Register object,
Handle<Map> type,
Handle<String> name) {
LookupResult lookup;
LookupResult lookup(isolate());
type->LookupInDescriptors(NULL, *name, &lookup);
ASSERT(lookup.IsProperty() &&
(lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));

View File

@ -2372,7 +2372,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// Get the number of arguments.
const int argc = arguments().immediate();
LookupResult lookup;
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
// Get the receiver from the stack.
@ -2914,7 +2914,7 @@ MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
// -----------------------------------
Label miss;
LookupResult lookup;
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
// TODO(368): Compile in the whole chain: all the interceptors in
@ -3102,7 +3102,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
__ cmp(eax, Immediate(Handle<String>(name)));
__ j(not_equal, &miss);
LookupResult lookup;
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
GenerateLoadInterceptor(receiver,
holder,

View File

@ -483,7 +483,7 @@ MaybeObject* CallICBase::LoadFunction(State state,
}
// Lookup the property in the object.
LookupResult lookup;
LookupResult lookup(isolate());
LookupForRead(*object, *name, &lookup);
if (!lookup.IsProperty()) {
@ -935,7 +935,7 @@ MaybeObject* LoadIC::Load(State state,
if (name->AsArrayIndex(&index)) return object->GetElement(index);
// Named lookup in the object.
LookupResult lookup;
LookupResult lookup(isolate());
LookupForRead(*object, *name, &lookup);
// If we did not find a property, check if we need to throw an exception.
@ -1203,7 +1203,7 @@ MaybeObject* KeyedLoadIC::Load(State state,
}
// Named lookup.
LookupResult lookup;
LookupResult lookup(isolate());
LookupForRead(*object, *name, &lookup);
// If we did not find a property, check if we need to throw an exception.
@ -1435,7 +1435,7 @@ MaybeObject* StoreIC::Store(State state,
// Lookup the property locally in the receiver.
if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
LookupResult lookup;
LookupResult lookup(isolate());
if (LookupForWrite(*receiver, *name, &lookup)) {
// Generate a stub for this store.
@ -1849,7 +1849,7 @@ MaybeObject* KeyedStoreIC::Store(State state,
}
// Lookup the property locally in the receiver.
LookupResult lookup;
LookupResult lookup(isolate());
receiver->LocalLookup(*name, &lookup);
// Update inline cache and stub cache.

View File

@ -98,6 +98,7 @@ void ThreadLocalTop::InitializeInternal() {
failed_access_check_callback_ = NULL;
save_context_ = NULL;
catcher_ = NULL;
top_lookup_result_ = NULL;
// These members are re-initialized later after deserialization
// is complete.
@ -480,6 +481,9 @@ void Isolate::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
for (StackFrameIterator it(this, thread); !it.done(); it.Advance()) {
it.frame()->Iterate(v);
}
// Iterate pointers in live lookup results.
thread->top_lookup_result_->Iterate(v);
}

View File

@ -255,6 +255,9 @@ class ThreadLocalTop BASE_EMBEDDED {
// Call back function to report unsafe JS accesses.
v8::FailedAccessCheckCallback failed_access_check_callback_;
// Head of the list of live LookupResults.
LookupResult* top_lookup_result_;
// Whether out of memory exceptions should be ignored.
bool ignore_out_of_memory_;
@ -995,6 +998,13 @@ class Isolate {
void SetData(void* data) { embedder_data_ = data; }
void* GetData() { return embedder_data_; }
LookupResult* top_lookup_result() {
return thread_local_top_.top_lookup_result_;
}
void SetTopLookupResult(LookupResult* top) {
thread_local_top_.top_lookup_result_ = top;
}
private:
Isolate();

View File

@ -2515,7 +2515,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// Get the number of arguments.
const int argc = arguments().immediate();
LookupResult lookup;
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
// Get the receiver from the stack.
@ -2919,7 +2919,7 @@ MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
// -----------------------------------
Label miss;
LookupResult lookup;
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
GenerateLoadInterceptor(object,
holder,
@ -3073,7 +3073,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
// Check the key is the cached one.
__ Branch(&miss, ne, a0, Operand(Handle<String>(name)));
LookupResult lookup;
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
GenerateLoadInterceptor(receiver,
holder,

View File

@ -154,7 +154,7 @@ void Object::Lookup(String* name, LookupResult* result) {
MaybeObject* Object::GetPropertyWithReceiver(Object* receiver,
String* name,
PropertyAttributes* attributes) {
LookupResult result;
LookupResult result(name->GetIsolate());
Lookup(name, &result);
MaybeObject* value = GetProperty(receiver, &result, name, attributes);
ASSERT(*attributes <= ABSENT);
@ -310,7 +310,7 @@ MaybeObject* JSObject::GetPropertyWithFailedAccessCheck(
case FIELD:
case CONSTANT_FUNCTION: {
// Search ALL_CAN_READ accessors in prototype chain.
LookupResult r;
LookupResult r(GetIsolate());
result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
if (r.IsProperty()) {
return GetPropertyWithFailedAccessCheck(receiver,
@ -323,7 +323,7 @@ MaybeObject* JSObject::GetPropertyWithFailedAccessCheck(
case INTERCEPTOR: {
// If the object has an interceptor, try real named properties.
// No access check in GetPropertyAttributeWithInterceptor.
LookupResult r;
LookupResult r(GetIsolate());
result->holder()->LookupRealNamedProperty(name, &r);
if (r.IsProperty()) {
return GetPropertyWithFailedAccessCheck(receiver,
@ -370,7 +370,7 @@ PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
case CONSTANT_FUNCTION: {
if (!continue_search) break;
// Search ALL_CAN_READ accessors in prototype chain.
LookupResult r;
LookupResult r(GetIsolate());
result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
if (r.IsProperty()) {
return GetPropertyAttributeWithFailedAccessCheck(receiver,
@ -384,7 +384,7 @@ PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
case INTERCEPTOR: {
// If the object has an interceptor, try real named properties.
// No access check in GetPropertyAttributeWithInterceptor.
LookupResult r;
LookupResult r(GetIsolate());
if (continue_search) {
result->holder()->LookupRealNamedProperty(name, &r);
} else {
@ -404,7 +404,7 @@ PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
}
}
GetHeap()->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
GetIsolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
return ABSENT;
}
@ -1658,7 +1658,7 @@ MaybeObject* JSObject::SetPropertyPostInterceptor(
PropertyAttributes attributes,
StrictModeFlag strict_mode) {
// Check local property, ignore interceptor.
LookupResult result;
LookupResult result(GetIsolate());
LocalLookupRealNamedProperty(name, &result);
if (result.IsFound()) {
// An existing property, a map transition or a null descriptor was
@ -1840,7 +1840,7 @@ MaybeObject* JSReceiver::SetProperty(String* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode) {
LookupResult result;
LookupResult result(GetIsolate());
LocalLookup(name, &result);
return SetProperty(&result, name, value, attributes, strict_mode);
}
@ -2006,9 +2006,9 @@ MaybeObject* JSObject::SetPropertyWithCallbackSetterInPrototypes(
PropertyAttributes attributes,
bool* found,
StrictModeFlag strict_mode) {
LookupResult result;
LookupCallbackSetterInPrototypes(name, &result);
Heap* heap = GetHeap();
LookupResult result(heap->isolate());
LookupCallbackSetterInPrototypes(name, &result);
if (result.IsFound()) {
*found = true;
if (result.type() == CALLBACKS) {
@ -2020,7 +2020,7 @@ MaybeObject* JSObject::SetPropertyWithCallbackSetterInPrototypes(
} else if (result.type() == HANDLER) {
// We could not find a local property so let's check whether there is an
// accessor that wants to handle the property.
LookupResult accessor_result;
LookupResult accessor_result(heap->isolate());
LookupCallbackSetterInPrototypes(name, &accessor_result);
if (accessor_result.IsFound()) {
if (accessor_result.type() == CALLBACKS) {
@ -2423,7 +2423,7 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
case INTERCEPTOR: {
// Try lookup real named properties. Note that only property can be
// set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
LookupResult r;
LookupResult r(GetIsolate());
LookupRealNamedProperty(name, &r);
if (r.IsProperty()) {
return SetPropertyWithFailedAccessCheck(&r,
@ -2441,10 +2441,10 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
}
}
Heap* heap = GetHeap();
HandleScope scope(heap->isolate());
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
Handle<Object> value_handle(value);
heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
return *value_handle;
}
@ -2865,12 +2865,12 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
// Make sure that the top context does not change when doing callbacks or
// interceptor calls.
AssertNoContextChange ncc;
LookupResult result;
Isolate* isolate = GetIsolate();
LookupResult result(isolate);
LocalLookup(name, &result);
// Check access rights if needed.
if (IsAccessCheckNeeded()) {
Heap* heap = GetHeap();
if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) {
if (!isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
return SetPropertyWithFailedAccessCheck(&result,
name,
value,
@ -2941,7 +2941,7 @@ PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
String* name,
bool continue_search) {
// Check local property, ignore interceptor.
LookupResult result;
LookupResult result(GetIsolate());
LocalLookupRealNamedProperty(name, &result);
if (result.IsProperty()) return result.GetAttributes();
@ -3017,7 +3017,7 @@ PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver(
? NONE : ABSENT;
}
// Named property.
LookupResult result;
LookupResult result(GetIsolate());
Lookup(key, &result);
return GetPropertyAttribute(receiver, &result, key, true);
}
@ -3066,7 +3066,7 @@ PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) {
return ABSENT;
}
// Named property.
LookupResult result;
LookupResult result(GetIsolate());
LocalLookup(name, &result);
return GetPropertyAttribute(this, &result, name, false);
}
@ -3573,7 +3573,7 @@ MaybeObject* JSObject::SetHiddenPropertiesDictionary(
MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
DeleteMode mode) {
// Check local property, ignore interceptor.
LookupResult result;
LookupResult result(GetIsolate());
LocalLookupRealNamedProperty(name, &result);
if (!result.IsProperty()) return GetHeap()->true_value();
@ -3722,7 +3722,7 @@ MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
if (name->AsArrayIndex(&index)) {
return DeleteElement(index, mode);
} else {
LookupResult result;
LookupResult result(isolate);
LocalLookup(name, &result);
if (!result.IsProperty()) return isolate->heap()->true_value();
// Ignore attributes if forcing a deletion.
@ -4152,7 +4152,7 @@ MaybeObject* JSObject::DefineGetterSetter(String* name,
}
} else {
// Lookup the name.
LookupResult result;
LookupResult result(heap->isolate());
LocalLookup(name, &result);
if (result.IsProperty()) {
if (result.IsReadOnly()) return heap->undefined_value();
@ -4182,8 +4182,8 @@ MaybeObject* JSObject::DefineGetterSetter(String* name,
bool JSObject::CanSetCallback(String* name) {
ASSERT(!IsAccessCheckNeeded()
|| Isolate::Current()->MayNamedAccess(this, name, v8::ACCESS_SET));
ASSERT(!IsAccessCheckNeeded() ||
GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
// Check if there is an API defined callback object which prohibits
// callback overwriting in this object or it's prototype chain.
@ -4191,7 +4191,7 @@ bool JSObject::CanSetCallback(String* name) {
// certain accessors such as window.location should not be allowed
// to be overwritten because allowing overwriting could potentially
// cause security problems.
LookupResult callback_result;
LookupResult callback_result(GetIsolate());
LookupCallback(name, &callback_result);
if (callback_result.IsProperty()) {
Object* obj = callback_result.GetCallbackObject();
@ -4388,7 +4388,7 @@ MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
}
} else {
// Lookup the name.
LookupResult result;
LookupResult result(isolate);
LocalLookup(name, &result);
// ES5 forbids turning a property into an accessor if it's not
// configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5).
@ -4446,7 +4446,7 @@ Object* JSObject::LookupAccessor(String* name, bool is_getter) {
for (Object* obj = this;
obj != heap->null_value();
obj = JSObject::cast(obj)->GetPrototype()) {
LookupResult result;
LookupResult result(heap->isolate());
JSObject::cast(obj)->LocalLookup(name, &result);
if (result.IsProperty()) {
if (result.IsReadOnly()) return heap->undefined_value();
@ -7088,7 +7088,7 @@ bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) {
obj = obj->GetPrototype()) {
JSObject* js_object = JSObject::cast(obj);
for (int i = 0; i < this_property_assignments_count(); i++) {
LookupResult result;
LookupResult result(heap->isolate());
String* name = GetThisPropertyAssignmentName(i);
js_object->LocalLookupRealNamedProperty(name, &result);
if (result.IsProperty() && result.type() == CALLBACKS) {
@ -9634,7 +9634,7 @@ MaybeObject* JSObject::GetPropertyPostInterceptor(
String* name,
PropertyAttributes* attributes) {
// Check local property in holder, ignore interceptor.
LookupResult result;
LookupResult result(GetIsolate());
LocalLookupRealNamedProperty(name, &result);
if (result.IsProperty()) {
return GetProperty(receiver, &result, name, attributes);
@ -9652,7 +9652,7 @@ MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
String* name,
PropertyAttributes* attributes) {
// Check local property in holder, ignore interceptor.
LookupResult result;
LookupResult result(GetIsolate());
LocalLookupRealNamedProperty(name, &result);
if (result.IsProperty()) {
return GetProperty(receiver, &result, name, attributes);
@ -9703,15 +9703,15 @@ MaybeObject* JSObject::GetPropertyWithInterceptor(
bool JSObject::HasRealNamedProperty(String* key) {
// Check access rights if needed.
Isolate* isolate = GetIsolate();
if (IsAccessCheckNeeded()) {
Heap* heap = GetHeap();
if (!heap->isolate()->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
return false;
}
}
LookupResult result;
LookupResult result(isolate);
LocalLookupRealNamedProperty(key, &result);
return result.IsProperty() && (result.type() != INTERCEPTOR);
}
@ -9780,15 +9780,15 @@ bool JSObject::HasRealElementProperty(uint32_t index) {
bool JSObject::HasRealNamedCallbackProperty(String* key) {
// Check access rights if needed.
Isolate* isolate = GetIsolate();
if (IsAccessCheckNeeded()) {
Heap* heap = GetHeap();
if (!heap->isolate()->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
return false;
}
}
LookupResult result;
LookupResult result(isolate);
LocalLookupRealNamedProperty(key, &result);
return result.IsProperty() && (result.type() == CALLBACKS);
}

View File

@ -2166,15 +2166,16 @@ void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj,
String* V8HeapExplorer::GetConstructorName(JSObject* object) {
if (object->IsJSFunction()) return HEAP->closure_symbol();
Heap* heap = object->GetHeap();
if (object->IsJSFunction()) return heap->closure_symbol();
String* constructor_name = object->constructor_name();
if (constructor_name == HEAP->Object_symbol()) {
if (constructor_name == heap->Object_symbol()) {
// Look up an immediate "constructor" property, if it is a function,
// return its name. This is for instances of binding objects, which
// have prototype constructor type "Object".
Object* constructor_prop = NULL;
LookupResult result;
object->LocalLookupRealNamedProperty(HEAP->constructor_symbol(), &result);
LookupResult result(heap->isolate());
object->LocalLookupRealNamedProperty(heap->constructor_symbol(), &result);
if (result.IsProperty()) {
constructor_prop = result.GetLazyValue();
}

View File

@ -31,6 +31,15 @@ namespace v8 {
namespace internal {
void LookupResult::Iterate(ObjectVisitor* visitor) {
LookupResult* current = this; // Could be NULL.
while (current != NULL) {
visitor->VisitPointer(BitCast<Object**>(&current->holder_));
current = current->next_;
}
}
#ifdef OBJECT_PRINT
void LookupResult::Print(FILE* out) {
if (!IsFound()) {

View File

@ -164,10 +164,20 @@ class CallbacksDescriptor: public Descriptor {
class LookupResult BASE_EMBEDDED {
public:
LookupResult()
: lookup_type_(NOT_FOUND),
explicit LookupResult(Isolate* isolate)
: isolate_(isolate),
next_(isolate->top_lookup_result()),
lookup_type_(NOT_FOUND),
holder_(NULL),
cacheable_(true),
details_(NONE, NORMAL) {}
details_(NONE, NORMAL) {
isolate->SetTopLookupResult(this);
}
~LookupResult() {
ASSERT(isolate_->top_lookup_result() == this);
isolate_->SetTopLookupResult(next_);
}
void DescriptorResult(JSObject* holder, PropertyDetails details, int number) {
lookup_type_ = DESCRIPTOR_TYPE;
@ -215,6 +225,7 @@ class LookupResult BASE_EMBEDDED {
void NotFound() {
lookup_type_ = NOT_FOUND;
holder_ = NULL;
}
JSObject* holder() {
@ -346,7 +357,12 @@ class LookupResult BASE_EMBEDDED {
return holder()->GetNormalizedProperty(this);
}
void Iterate(ObjectVisitor* visitor);
private:
Isolate* isolate_;
LookupResult* next_;
// Where did we find the result;
enum {
NOT_FOUND,

View File

@ -961,7 +961,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
HandleScope scope(isolate);
Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
Handle<JSArray> desc = isolate->factory()->NewJSArrayWithElements(elms);
LookupResult result;
LookupResult result(isolate);
CONVERT_ARG_CHECKED(JSObject, obj, 0);
CONVERT_ARG_CHECKED(String, name, 1);
@ -1240,7 +1240,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
if (value->IsUndefined() || is_const_property) {
// Lookup the property in the global object, and don't set the
// value of the variable if the property is already there.
LookupResult lookup;
LookupResult lookup(isolate);
global->Lookup(*name, &lookup);
if (lookup.IsProperty()) {
// We found an existing property. Unless it was an interceptor
@ -1267,7 +1267,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
value = function;
}
LookupResult lookup;
LookupResult lookup(isolate);
global->LocalLookup(*name, &lookup);
// Compute the property attributes. According to ECMA-262, section
@ -1399,7 +1399,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
// not real JSObjects.
if (initial_value->IsTheHole() &&
!object->IsJSContextExtensionObject()) {
LookupResult lookup;
LookupResult lookup(isolate);
object->Lookup(*name, &lookup);
if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) {
return ThrowRedeclarationError(isolate, "const", name);
@ -1443,7 +1443,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
// Note that objects can have hidden prototypes, so we need to traverse
// the whole chain of hidden prototypes to do a 'local' lookup.
Object* object = global;
LookupResult lookup;
LookupResult lookup(isolate);
while (object->IsJSObject() &&
JSObject::cast(object)->map()->is_hidden_prototype()) {
JSObject* raw_holder = JSObject::cast(object);
@ -1497,7 +1497,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
// add it as a local property even in case of callbacks in the
// prototype chain (this rules out using SetProperty).
// We use SetLocalPropertyIgnoreAttributes instead
LookupResult lookup;
LookupResult lookup(isolate);
global->LocalLookup(*name, &lookup);
if (!lookup.IsProperty()) {
return global->SetLocalPropertyIgnoreAttributes(*name,
@ -1614,7 +1614,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
// This is the property that was introduced by the const declaration.
// Set it if it hasn't been set before. NOTE: We cannot use
// GetProperty() to get the current value as it 'unholes' the value.
LookupResult lookup;
LookupResult lookup(isolate);
object->LocalLookupRealNamedProperty(*name, &lookup);
ASSERT(lookup.IsProperty()); // the property was declared
ASSERT(lookup.IsReadOnly()); // and it was declared as read-only
@ -4135,7 +4135,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
return value->IsTheHole() ? isolate->heap()->undefined_value() : value;
}
// Lookup cache miss. Perform lookup and update the cache if appropriate.
LookupResult result;
LookupResult result(isolate);
receiver->LocalLookup(key, &result);
if (result.IsProperty() && result.type() == FIELD) {
int offset = result.GetFieldIndex();
@ -4190,7 +4190,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
int unchecked = flag_attr->value();
RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
RUNTIME_ASSERT(!obj->IsNull());
LookupResult result;
LookupResult result(isolate);
obj->LocalLookupRealNamedProperty(name, &result);
PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
@ -4274,7 +4274,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
return *obj_value;
}
LookupResult result;
LookupResult result(isolate);
js_object->LocalLookupRealNamedProperty(*name, &result);
// To be compatible with safari we do not change the value on API objects
@ -10361,7 +10361,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
// Try local lookup on each of the objects.
Handle<JSObject> jsproto = obj;
for (int i = 0; i < length; i++) {
LookupResult result;
LookupResult result(isolate);
jsproto->LocalLookup(*name, &result);
if (result.IsProperty()) {
// LookupResult is not GC safe as it holds raw object pointers.
@ -10418,7 +10418,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
CONVERT_ARG_CHECKED(JSObject, obj, 0);
CONVERT_ARG_CHECKED(String, name, 1);
LookupResult result;
LookupResult result(isolate);
obj->Lookup(*name, &result);
if (result.IsProperty()) {
return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);

View File

@ -2129,7 +2129,7 @@ void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
Register object,
Handle<Map> type,
Handle<String> name) {
LookupResult lookup;
LookupResult lookup(isolate());
type->LookupInDescriptors(NULL, *name, &lookup);
ASSERT(lookup.IsProperty() &&
(lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));

View File

@ -2221,7 +2221,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// Get the number of arguments.
const int argc = arguments().immediate();
LookupResult lookup;
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
// Get the receiver from the stack.
@ -2765,7 +2765,7 @@ MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
// -----------------------------------
Label miss;
LookupResult lookup;
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
// TODO(368): Compile in the whole chain: all the interceptors in
@ -2949,7 +2949,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
__ Cmp(rax, Handle<String>(name));
__ j(not_equal, &miss);
LookupResult lookup;
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
GenerateLoadInterceptor(receiver,
holder,