Commit 8e31371d authored by lrn@chromium.org's avatar lrn@chromium.org

Move logic for hidden properties into the JSObject.

Previously, the logic using the hidden properties backing object was
spread accross use sites. Now it's all contained in JSObject, with
only simple accessors available.
Also change the backing object to be a StringDictionary rather than a JSObject.
There's still room for improvement by making a hash-table that don't
store property details as well.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9510 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4750f0c3
...@@ -3210,21 +3210,10 @@ bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key, ...@@ -3210,21 +3210,10 @@ bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
ENTER_V8(isolate); ENTER_V8(isolate);
i::HandleScope scope(isolate); i::HandleScope scope(isolate);
i::Handle<i::JSObject> self = Utils::OpenHandle(this); i::Handle<i::JSObject> self = Utils::OpenHandle(this);
i::Handle<i::Object> hidden_props(i::GetHiddenProperties( i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
self,
i::ALLOW_CREATION));
i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
EXCEPTION_PREAMBLE(isolate); i::Handle<i::Object> result = i::SetHiddenProperty(self, key_obj, value_obj);
i::Handle<i::Object> obj = i::SetProperty( return *result == *self;
hidden_props,
key_obj,
value_obj,
static_cast<PropertyAttributes>(None),
i::kNonStrictMode);
has_pending_exception = obj.is_null();
EXCEPTION_BAILOUT_CHECK(isolate, false);
return true;
} }
...@@ -3234,20 +3223,9 @@ v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) { ...@@ -3234,20 +3223,9 @@ v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
return Local<v8::Value>()); return Local<v8::Value>());
ENTER_V8(isolate); ENTER_V8(isolate);
i::Handle<i::JSObject> self = Utils::OpenHandle(this); i::Handle<i::JSObject> self = Utils::OpenHandle(this);
i::Handle<i::Object> hidden_props(i::GetHiddenProperties(
self,
i::OMIT_CREATION));
if (hidden_props->IsUndefined()) {
return v8::Local<v8::Value>();
}
i::Handle<i::String> key_obj = Utils::OpenHandle(*key); i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
EXCEPTION_PREAMBLE(isolate); i::Handle<i::Object> result(self->GetHiddenProperty(*key_obj));
i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj); if (result->IsUndefined()) return v8::Local<v8::Value>();
has_pending_exception = result.is_null();
EXCEPTION_BAILOUT_CHECK(isolate, v8::Local<v8::Value>());
if (result->IsUndefined()) {
return v8::Local<v8::Value>();
}
return Utils::ToLocal(result); return Utils::ToLocal(result);
} }
...@@ -3258,15 +3236,9 @@ bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) { ...@@ -3258,15 +3236,9 @@ bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
ENTER_V8(isolate); ENTER_V8(isolate);
i::HandleScope scope(isolate); i::HandleScope scope(isolate);
i::Handle<i::JSObject> self = Utils::OpenHandle(this); i::Handle<i::JSObject> self = Utils::OpenHandle(this);
i::Handle<i::Object> hidden_props(i::GetHiddenProperties(
self,
i::OMIT_CREATION));
if (hidden_props->IsUndefined()) {
return true;
}
i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
i::Handle<i::String> key_obj = Utils::OpenHandle(*key); i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
return i::DeleteProperty(js_obj, key_obj)->IsTrue(); self->DeleteHiddenProperty(*key_obj);
return true;
} }
......
...@@ -421,9 +421,11 @@ Handle<Object> PreventExtensions(Handle<JSObject> object) { ...@@ -421,9 +421,11 @@ Handle<Object> PreventExtensions(Handle<JSObject> object) {
} }
Handle<Object> GetHiddenProperties(Handle<JSObject> obj, CreationFlag flag) { Handle<Object> SetHiddenProperty(Handle<JSObject> obj,
Handle<String> key,
Handle<Object> value) {
CALL_HEAP_FUNCTION(obj->GetIsolate(), CALL_HEAP_FUNCTION(obj->GetIsolate(),
obj->GetHiddenProperties(flag), obj->SetHiddenProperty(*key, *value),
Object); Object);
} }
......
...@@ -265,11 +265,11 @@ Handle<Object> GetPrototype(Handle<Object> obj); ...@@ -265,11 +265,11 @@ Handle<Object> GetPrototype(Handle<Object> obj);
Handle<Object> SetPrototype(Handle<JSObject> obj, Handle<Object> value); Handle<Object> SetPrototype(Handle<JSObject> obj, Handle<Object> value);
// Return the object's hidden properties object. If the object has no hidden // Sets a hidden property on an object. Returns obj on success, undefined
// properties and HiddenPropertiesFlag::ALLOW_CREATION is passed, then a new // if trying to set the property on a detached proxy.
// hidden property object will be allocated. Otherwise Heap::undefined_value Handle<Object> SetHiddenProperty(Handle<JSObject> obj,
// is returned. Handle<String> key,
Handle<Object> GetHiddenProperties(Handle<JSObject> obj, CreationFlag flag); Handle<Object> value);
int GetIdentityHash(Handle<JSReceiver> obj); int GetIdentityHash(Handle<JSReceiver> obj);
......
...@@ -4347,42 +4347,6 @@ MaybeObject* JSReceiver::GetIdentityHash(CreationFlag flag) { ...@@ -4347,42 +4347,6 @@ MaybeObject* JSReceiver::GetIdentityHash(CreationFlag flag) {
} }
bool JSObject::HasHiddenPropertiesObject() {
ASSERT(!IsJSGlobalProxy());
return GetPropertyAttributePostInterceptor(this,
GetHeap()->hidden_symbol(),
false) != ABSENT;
}
Object* JSObject::GetHiddenPropertiesObject() {
ASSERT(!IsJSGlobalProxy());
PropertyAttributes attributes;
// You can't install a getter on a property indexed by the hidden symbol,
// so we can be sure that GetLocalPropertyPostInterceptor returns a real
// object.
Object* result =
GetLocalPropertyPostInterceptor(this,
GetHeap()->hidden_symbol(),
&attributes)->ToObjectUnchecked();
return result;
}
MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
ASSERT(!IsJSGlobalProxy());
return SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
hidden_obj,
DONT_ENUM,
kNonStrictMode);
}
bool JSObject::HasHiddenProperties() {
return !GetHiddenProperties(OMIT_CREATION)->ToObjectChecked()->IsUndefined();
}
bool JSReceiver::HasElement(uint32_t index) { bool JSReceiver::HasElement(uint32_t index) {
if (IsJSProxy()) { if (IsJSProxy()) {
return JSProxy::cast(this)->HasElementWithHandler(index); return JSProxy::cast(this)->HasElementWithHandler(index);
......
This diff is collapsed.
...@@ -1577,27 +1577,25 @@ class JSObject: public JSReceiver { ...@@ -1577,27 +1577,25 @@ class JSObject: public JSReceiver {
// Accessors for hidden properties object. // Accessors for hidden properties object.
// //
// Hidden properties are not local properties of the object itself. // Hidden properties are not local properties of the object itself.
// Instead they are stored on an auxiliary JSObject stored as a local // Instead they are stored in an auxiliary structure kept as a local
// property with a special name Heap::hidden_symbol(). But if the // property with a special name Heap::hidden_symbol(). But if the
// receiver is a JSGlobalProxy then the auxiliary object is a property // receiver is a JSGlobalProxy then the auxiliary object is a property
// of its prototype. // of its prototype, and if it's a detached proxy, then you can't have
// // hidden properties.
// Has/Get/SetHiddenPropertiesObject methods don't allow the holder to be
// a JSGlobalProxy. Use BypassGlobalProxy method above to get to the real // Sets a hidden property on this object. Returns this object if successful,
// holder. // undefined if called on a detached proxy, and a failure if a GC
// // is required
// These accessors do not touch interceptors or accessors. MaybeObject* SetHiddenProperty(String* key, Object* value);
inline bool HasHiddenPropertiesObject(); // Gets the value of a hidden property with the given key. Returns undefined
inline Object* GetHiddenPropertiesObject(); // if the property doesn't exist (or if called on a detached proxy),
MUST_USE_RESULT inline MaybeObject* SetHiddenPropertiesObject( // otherwise returns the value set for the key.
Object* hidden_obj); Object* GetHiddenProperty(String* key);
// Deletes a hidden property. Deleting a non-existing property is
// Retrieves the hidden properties object. // considered successful.
// void DeleteHiddenProperty(String* key);
// The undefined value might be returned in case no hidden properties object // Returns true if the object has a property with the hidden symbol as name.
// is present and creation was omitted. bool HasHiddenProperties();
inline bool HasHiddenProperties();
MUST_USE_RESULT MaybeObject* GetHiddenProperties(CreationFlag flag);
MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag); MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag);
MUST_USE_RESULT MaybeObject* SetIdentityHash(Object* hash, CreationFlag flag); MUST_USE_RESULT MaybeObject* SetIdentityHash(Object* hash, CreationFlag flag);
...@@ -2038,6 +2036,15 @@ class JSObject: public JSReceiver { ...@@ -2038,6 +2036,15 @@ class JSObject: public JSReceiver {
void LookupInDescriptor(String* name, LookupResult* result); void LookupInDescriptor(String* name, LookupResult* result);
// Returns the hidden properties backing store object, currently
// a StringDictionary, stored on this object.
// If no hidden properties object has been put on this object,
// return undefined, unless create_if_absent is true, in which case
// a new dictionary is created, added to this object, and returned.
MaybeObject* GetHiddenPropertiesDictionary(bool create_if_absent);
// Updates the existing hidden properties dictionary.
MaybeObject* SetHiddenPropertiesDictionary(StringDictionary* dictionary);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject); DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
}; };
...@@ -2863,7 +2870,7 @@ class StringDictionary: public Dictionary<StringDictionaryShape, String*> { ...@@ -2863,7 +2870,7 @@ class StringDictionary: public Dictionary<StringDictionaryShape, String*> {
JSObject* obj, JSObject* obj,
int unused_property_fields); int unused_property_fields);
// Find entry for key otherwise return kNotFound. Optimzed version of // Find entry for key, otherwise return kNotFound. Optimized version of
// HashTable::FindEntry. // HashTable::FindEntry.
int FindEntry(String* key); int FindEntry(String* key);
}; };
......
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