Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Unified Diff: src/runtime.cc

Issue 11420011: Clean-up refactoring to eliminate GetLocalElementKind. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments. Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects-inl.h ('k') | test/mjsunit/regress/regress-1692.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index 7bd771be8640ba83e043ad2ec7d93c3e79c84905..701bc12967687091f6d0fa3b956dc1dedc632bb8 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -977,97 +977,109 @@ static void GetOwnPropertyImplementation(JSObject* obj,
Object* proto = obj->GetPrototype();
if (proto->IsJSObject() &&
- JSObject::cast(proto)->map()->is_hidden_prototype())
+ JSObject::cast(proto)->map()->is_hidden_prototype()) {
GetOwnPropertyImplementation(JSObject::cast(proto),
name, result);
+ }
}
-static bool CheckAccessException(LookupResult* result,
+static bool CheckAccessException(Object* callback,
v8::AccessType access_type) {
- if (result->type() == CALLBACKS) {
- Object* callback = result->GetCallbackObject();
- if (callback->IsAccessorInfo()) {
- AccessorInfo* info = AccessorInfo::cast(callback);
- bool can_access =
- (access_type == v8::ACCESS_HAS &&
- (info->all_can_read() || info->all_can_write())) ||
- (access_type == v8::ACCESS_GET && info->all_can_read()) ||
- (access_type == v8::ACCESS_SET && info->all_can_write());
- return can_access;
- }
+ if (callback->IsAccessorInfo()) {
+ AccessorInfo* info = AccessorInfo::cast(callback);
+ return
+ (access_type == v8::ACCESS_HAS &&
+ (info->all_can_read() || info->all_can_write())) ||
+ (access_type == v8::ACCESS_GET && info->all_can_read()) ||
+ (access_type == v8::ACCESS_SET && info->all_can_write());
}
-
return false;
}
-static bool CheckAccess(JSObject* obj,
- String* name,
- LookupResult* result,
- v8::AccessType access_type) {
- ASSERT(result->IsProperty());
-
- JSObject* holder = result->holder();
- JSObject* current = obj;
- Isolate* isolate = obj->GetIsolate();
- while (true) {
+template<class Key>
+static bool CheckGenericAccess(
+ JSObject* receiver,
+ JSObject* holder,
+ Key key,
+ v8::AccessType access_type,
+ bool (Isolate::*mayAccess)(JSObject*, Key, v8::AccessType)) {
+ Isolate* isolate = receiver->GetIsolate();
+ for (JSObject* current = receiver;
+ true;
+ current = JSObject::cast(current->GetPrototype())) {
if (current->IsAccessCheckNeeded() &&
- !isolate->MayNamedAccess(current, name, access_type)) {
- // Access check callback denied the access, but some properties
- // can have a special permissions which override callbacks descision
- // (currently see v8::AccessControl).
- break;
+ !(isolate->*mayAccess)(current, key, access_type)) {
+ return false;
}
+ if (current == holder) break;
+ }
+ return true;
+}
- if (current == holder) {
- return true;
- }
- current = JSObject::cast(current->GetPrototype());
+static bool CheckElementAccess(
+ JSObject* obj,
+ uint32_t index,
+ v8::AccessType access_type) {
+ // TODO(1095): we should traverse hidden prototype hierachy as well.
+ if (CheckGenericAccess(
+ obj, obj, index, access_type, &Isolate::MayIndexedAccess)) {
+ return true;
+ }
+
+ obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
+ return false;
+}
+
+
+static bool CheckPropertyAccess(
+ JSObject* obj,
+ String* name,
+ v8::AccessType access_type) {
+ uint32_t index;
+ if (name->AsArrayIndex(&index)) {
+ return CheckElementAccess(obj, index, access_type);
+ }
+
+ LookupResult lookup(obj->GetIsolate());
+ obj->LocalLookup(name, &lookup);
+
+ if (CheckGenericAccess<Object*>(
+ obj, lookup.holder(), name, access_type, &Isolate::MayNamedAccess)) {
+ return true;
}
+ // Access check callback denied the access, but some properties
+ // can have a special permissions which override callbacks descision
+ // (currently see v8::AccessControl).
// API callbacks can have per callback access exceptions.
- switch (result->type()) {
- case CALLBACKS: {
- if (CheckAccessException(result, access_type)) {
+ switch (lookup.type()) {
+ case CALLBACKS:
+ if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
return true;
}
break;
- }
- case INTERCEPTOR: {
+ case INTERCEPTOR:
// If the object has an interceptor, try real named properties.
// Overwrite the result to fetch the correct property later.
- holder->LookupRealNamedProperty(name, result);
- if (result->IsProperty()) {
- if (CheckAccessException(result, access_type)) {
+ lookup.holder()->LookupRealNamedProperty(name, &lookup);
+ if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) {
+ if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
return true;
}
}
break;
- }
default:
break;
}
- isolate->ReportFailedAccessCheck(current, access_type);
+ obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
return false;
}
-// TODO(1095): we should traverse hidden prototype hierachy as well.
-static bool CheckElementAccess(JSObject* obj,
- uint32_t index,
- v8::AccessType access_type) {
- if (obj->IsAccessCheckNeeded() &&
- !obj->GetIsolate()->MayIndexedAccess(obj, index, access_type)) {
- return false;
- }
-
- return true;
-}
-
-
// Enumerator used as indices into the array returned from GetOwnProperty
enum PropertyDescriptorIndices {
IS_ACCESSOR_INDEX,
@@ -1085,141 +1097,33 @@ static MaybeObject* GetOwnProperty(Isolate* isolate,
Handle<JSObject> obj,
Handle<String> name) {
Heap* heap = isolate->heap();
- Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
- Handle<JSArray> desc = isolate->factory()->NewJSArrayWithElements(elms);
- LookupResult result(isolate);
- // This could be an element.
- uint32_t index;
- if (name->AsArrayIndex(&index)) {
- switch (obj->GetLocalElementKind(index)) {
- case JSObject::UNDEFINED_ELEMENT:
- return heap->undefined_value();
-
- case JSObject::STRING_CHARACTER_ELEMENT: {
- // Special handling of string objects according to ECMAScript 5
- // 15.5.5.2. Note that this might be a string object with elements
- // other than the actual string value. This is covered by the
- // subsequent cases.
- Handle<JSValue> js_value = Handle<JSValue>::cast(obj);
- Handle<String> str(String::cast(js_value->value()));
- Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED);
-
- elms->set(IS_ACCESSOR_INDEX, heap->false_value());
- elms->set(VALUE_INDEX, *substr);
- elms->set(WRITABLE_INDEX, heap->false_value());
- elms->set(ENUMERABLE_INDEX, heap->true_value());
- elms->set(CONFIGURABLE_INDEX, heap->false_value());
- return *desc;
- }
+ PropertyAttributes attrs = obj->GetLocalPropertyAttribute(*name);
+ if (attrs == ABSENT) return heap->undefined_value();
+ AccessorPair* accessors = obj->GetLocalPropertyAccessorPair(*name);
- case JSObject::INTERCEPTED_ELEMENT:
- case JSObject::FAST_ELEMENT: {
- elms->set(IS_ACCESSOR_INDEX, heap->false_value());
- Handle<Object> value = Object::GetElement(obj, index);
- RETURN_IF_EMPTY_HANDLE(isolate, value);
- elms->set(VALUE_INDEX, *value);
- elms->set(WRITABLE_INDEX, heap->true_value());
- elms->set(ENUMERABLE_INDEX, heap->true_value());
- elms->set(CONFIGURABLE_INDEX, heap->true_value());
- return *desc;
- }
-
- case JSObject::DICTIONARY_ELEMENT: {
- Handle<JSObject> holder = obj;
- if (obj->IsJSGlobalProxy()) {
- Object* proto = obj->GetPrototype();
- if (proto->IsNull()) return heap->undefined_value();
- ASSERT(proto->IsJSGlobalObject());
- holder = Handle<JSObject>(JSObject::cast(proto));
- }
- FixedArray* elements = FixedArray::cast(holder->elements());
- SeededNumberDictionary* dictionary = NULL;
- if (elements->map() == heap->non_strict_arguments_elements_map()) {
- dictionary = SeededNumberDictionary::cast(elements->get(1));
- } else {
- dictionary = SeededNumberDictionary::cast(elements);
- }
- int entry = dictionary->FindEntry(index);
- ASSERT(entry != SeededNumberDictionary::kNotFound);
- PropertyDetails details = dictionary->DetailsAt(entry);
- switch (details.type()) {
- case CALLBACKS: {
- // This is an accessor property with getter and/or setter.
- AccessorPair* accessors =
- AccessorPair::cast(dictionary->ValueAt(entry));
- elms->set(IS_ACCESSOR_INDEX, heap->true_value());
- if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) {
- elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER));
- }
- if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) {
- elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER));
- }
- break;
- }
- case NORMAL: {
- // This is a data property.
- elms->set(IS_ACCESSOR_INDEX, heap->false_value());
- Handle<Object> value = Object::GetElement(obj, index);
- ASSERT(!value.is_null());
- elms->set(VALUE_INDEX, *value);
- elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly()));
- break;
- }
- default:
- UNREACHABLE();
- break;
- }
- elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!details.IsDontEnum()));
- elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!details.IsDontDelete()));
- return *desc;
- }
- }
- }
-
- // Use recursive implementation to also traverse hidden prototypes
- GetOwnPropertyImplementation(*obj, *name, &result);
-
- if (!result.IsProperty()) {
- return heap->undefined_value();
- }
-
- if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) {
- return heap->false_value();
- }
-
- elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum()));
- elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete()));
-
- bool is_js_accessor = result.IsPropertyCallbacks() &&
- (result.GetCallbackObject()->IsAccessorPair());
-
- if (is_js_accessor) {
- // __defineGetter__/__defineSetter__ callback.
- elms->set(IS_ACCESSOR_INDEX, heap->true_value());
-
- AccessorPair* accessors = AccessorPair::cast(result.GetCallbackObject());
+ Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
+ elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
+ elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
+ elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(accessors != NULL));
+
+ if (accessors == NULL) {
+ elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
+ // GetProperty does access check.
+ elms->set(VALUE_INDEX, *GetProperty(obj, name));
+ } else {
+ // Access checks are performed for both accessors separately.
+ // When they fail, the respective field is not set in the descriptor.
Object* getter = accessors->GetComponent(ACCESSOR_GETTER);
- if (!getter->IsMap() && CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) {
+ Object* setter = accessors->GetComponent(ACCESSOR_SETTER);
+ if (!getter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_GET)) {
elms->set(GETTER_INDEX, getter);
}
- Object* setter = accessors->GetComponent(ACCESSOR_SETTER);
- if (!setter->IsMap() && CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) {
+ if (!setter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_SET)) {
elms->set(SETTER_INDEX, setter);
}
- } else {
- elms->set(IS_ACCESSOR_INDEX, heap->false_value());
- elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly()));
-
- PropertyAttributes attrs;
- Object* value;
- // GetProperty will check access and report any violations.
- { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs);
- if (!maybe_value->ToObject(&value)) return maybe_value;
- }
- elms->set(VALUE_INDEX, value);
}
- return *desc;
+ return *isolate->factory()->NewJSArrayWithElements(elms);
}
@@ -4727,41 +4631,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
CONVERT_ARG_CHECKED(JSObject, object, 0);
CONVERT_ARG_CHECKED(String, key, 1);
- uint32_t index;
- if (key->AsArrayIndex(&index)) {
- JSObject::LocalElementKind type = object->GetLocalElementKind(index);
- switch (type) {
- case JSObject::UNDEFINED_ELEMENT:
- case JSObject::STRING_CHARACTER_ELEMENT:
- return isolate->heap()->false_value();
- case JSObject::INTERCEPTED_ELEMENT:
- case JSObject::FAST_ELEMENT:
- return isolate->heap()->true_value();
- case JSObject::DICTIONARY_ELEMENT: {
- if (object->IsJSGlobalProxy()) {
- Object* proto = object->GetPrototype();
- if (proto->IsNull()) {
- return isolate->heap()->false_value();
- }
- ASSERT(proto->IsJSGlobalObject());
- object = JSObject::cast(proto);
- }
- FixedArray* elements = FixedArray::cast(object->elements());
- SeededNumberDictionary* dictionary = NULL;
- if (elements->map() ==
- isolate->heap()->non_strict_arguments_elements_map()) {
- dictionary = SeededNumberDictionary::cast(elements->get(1));
- } else {
- dictionary = SeededNumberDictionary::cast(elements);
- }
- int entry = dictionary->FindEntry(index);
- ASSERT(entry != SeededNumberDictionary::kNotFound);
- PropertyDetails details = dictionary->DetailsAt(entry);
- return isolate->heap()->ToBoolean(!details.IsDontEnum());
- }
- }
- }
-
PropertyAttributes att = object->GetLocalPropertyAttribute(key);
return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
}
« no previous file with comments | « src/objects-inl.h ('k') | test/mjsunit/regress/regress-1692.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698