Handlify JSObject::LookupAccessor method.

R=yangguo@chromium.org

Review URL: https://codereview.chromium.org/25508002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17048 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mstarzinger@chromium.org 2013-10-01 14:26:15 +00:00
parent b3c440f8da
commit d67ffdaa52
3 changed files with 44 additions and 29 deletions

View File

@ -6167,7 +6167,7 @@ void JSObject::DefineAccessor(Handle<JSObject> object,
// Make sure that the top context does not change when doing callbacks or // Make sure that the top context does not change when doing callbacks or
// interceptor calls. // interceptor calls.
AssertNoContextChangeWithHandleScope ncc; AssertNoContextChange ncc;
// Try to flatten before operating on the string. // Try to flatten before operating on the string.
if (name->IsString()) String::cast(*name)->TryFlatten(); if (name->IsString()) String::cast(*name)->TryFlatten();
@ -6412,58 +6412,62 @@ Handle<Object> JSObject::SetAccessor(Handle<JSObject> object,
} }
MaybeObject* JSObject::LookupAccessor(Name* name, AccessorComponent component) { Handle<Object> JSObject::GetAccessor(Handle<JSObject> object,
Heap* heap = GetHeap(); Handle<Name> name,
AccessorComponent component) {
Isolate* isolate = object->GetIsolate();
// Make sure that the top context does not change when doing callbacks or // Make sure that the top context does not change when doing callbacks or
// interceptor calls. // interceptor calls.
AssertNoContextChangeWithHandleScope ncc; AssertNoContextChange ncc;
// Check access rights if needed. // Check access rights if needed.
if (IsAccessCheckNeeded() && if (object->IsAccessCheckNeeded() &&
!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) { !isolate->MayNamedAccess(*object, *name, v8::ACCESS_HAS)) {
heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS);
RETURN_IF_SCHEDULED_EXCEPTION(heap->isolate()); RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
return heap->undefined_value(); return isolate->factory()->undefined_value();
} }
// Make the lookup and include prototypes. // Make the lookup and include prototypes.
uint32_t index = 0; uint32_t index = 0;
if (name->AsArrayIndex(&index)) { if (name->AsArrayIndex(&index)) {
for (Object* obj = this; for (Handle<Object> obj = object;
obj != heap->null_value(); *obj != isolate->heap()->null_value();
obj = JSReceiver::cast(obj)->GetPrototype()) { obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) {
if (obj->IsJSObject() && JSObject::cast(obj)->HasDictionaryElements()) { if (obj->IsJSObject() && JSObject::cast(*obj)->HasDictionaryElements()) {
JSObject* js_object = JSObject::cast(obj); JSObject* js_object = JSObject::cast(*obj);
SeededNumberDictionary* dictionary = js_object->element_dictionary(); SeededNumberDictionary* dictionary = js_object->element_dictionary();
int entry = dictionary->FindEntry(index); int entry = dictionary->FindEntry(index);
if (entry != SeededNumberDictionary::kNotFound) { if (entry != SeededNumberDictionary::kNotFound) {
Object* element = dictionary->ValueAt(entry); Object* element = dictionary->ValueAt(entry);
if (dictionary->DetailsAt(entry).type() == CALLBACKS && if (dictionary->DetailsAt(entry).type() == CALLBACKS &&
element->IsAccessorPair()) { element->IsAccessorPair()) {
return AccessorPair::cast(element)->GetComponent(component); return handle(AccessorPair::cast(element)->GetComponent(component),
isolate);
} }
} }
} }
} }
} else { } else {
for (Object* obj = this; for (Handle<Object> obj = object;
obj != heap->null_value(); *obj != isolate->heap()->null_value();
obj = JSReceiver::cast(obj)->GetPrototype()) { obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) {
LookupResult result(heap->isolate()); LookupResult result(isolate);
JSReceiver::cast(obj)->LocalLookup(name, &result); JSReceiver::cast(*obj)->LocalLookup(*name, &result);
if (result.IsFound()) { if (result.IsFound()) {
if (result.IsReadOnly()) return heap->undefined_value(); if (result.IsReadOnly()) return isolate->factory()->undefined_value();
if (result.IsPropertyCallbacks()) { if (result.IsPropertyCallbacks()) {
Object* obj = result.GetCallbackObject(); Object* obj = result.GetCallbackObject();
if (obj->IsAccessorPair()) { if (obj->IsAccessorPair()) {
return AccessorPair::cast(obj)->GetComponent(component); return handle(AccessorPair::cast(obj)->GetComponent(component),
isolate);
} }
} }
} }
} }
} }
return heap->undefined_value(); return isolate->factory()->undefined_value();
} }

View File

@ -2218,6 +2218,15 @@ class JSObject: public JSReceiver {
uint32_t index, uint32_t index,
bool continue_search); bool continue_search);
// Retrieves an AccessorPair property from the given object. Might return
// undefined if the property doesn't exist or is of a different kind.
static Handle<Object> GetAccessor(Handle<JSObject> object,
Handle<Name> name,
AccessorComponent component);
// Defines an AccessorPair property on the given object.
// TODO(mstarzinger): Rename to SetAccessor() and return empty handle on
// exception instead of letting callers check for scheduled exception.
static void DefineAccessor(Handle<JSObject> object, static void DefineAccessor(Handle<JSObject> object,
Handle<Name> name, Handle<Name> name,
Handle<Object> getter, Handle<Object> getter,
@ -2225,8 +2234,7 @@ class JSObject: public JSReceiver {
PropertyAttributes attributes, PropertyAttributes attributes,
v8::AccessControl access_control = v8::DEFAULT); v8::AccessControl access_control = v8::DEFAULT);
MaybeObject* LookupAccessor(Name* name, AccessorComponent component); // Defines an AccessorInfo property on the given object.
static Handle<Object> SetAccessor(Handle<JSObject> object, static Handle<Object> SetAccessor(Handle<JSObject> object,
Handle<AccessorInfo> info); Handle<AccessorInfo> info);

View File

@ -10582,14 +10582,17 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) { RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
SealHandleScope shs(isolate); HandleScope scope(isolate);
ASSERT(args.length() == 3); ASSERT(args.length() == 3);
CONVERT_ARG_CHECKED(JSReceiver, receiver, 0); CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
CONVERT_ARG_CHECKED(Name, name, 1); CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
CONVERT_SMI_ARG_CHECKED(flag, 2); CONVERT_SMI_ARG_CHECKED(flag, 2);
AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER; AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
if (!receiver->IsJSObject()) return isolate->heap()->undefined_value(); if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
return JSObject::cast(receiver)->LookupAccessor(name, component); Handle<Object> result =
JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component);
RETURN_IF_EMPTY_HANDLE(isolate, result);
return *result;
} }