Author: [email protected]
Date: Tue May 12 15:07:10 2009
New Revision: 1924

Modified:
    branches/bleeding_edge/src/handles.cc
    branches/bleeding_edge/src/handles.h
    branches/bleeding_edge/src/objects.cc
    branches/bleeding_edge/src/objects.h
    branches/bleeding_edge/test/cctest/test-api.cc

Log:
Fix for issue 339:
- Move GetHiddenProperties functionality from object.cc to handle.cc to
   be more robust in the presence of GC in the middle of the function.

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

Modified: branches/bleeding_edge/src/handles.cc
==============================================================================
--- branches/bleeding_edge/src/handles.cc       (original)
+++ branches/bleeding_edge/src/handles.cc       Tue May 12 15:07:10 2009
@@ -273,7 +273,35 @@

  Handle<Object> GetHiddenProperties(Handle<JSObject> obj,
                                     bool create_if_needed) {
-  CALL_HEAP_FUNCTION(obj->GetHiddenProperties(create_if_needed), Object);
+  Handle<String> key = Factory::hidden_symbol();
+
+  if (obj->HasFastProperties()) {
+    // If the object has fast properties, check whether the first slot
+    // in the descriptor array matches the hidden symbol. Since the
+    // hidden symbols hash code is zero (and no other string has hash
+    // code zero) it will always occupy the first entry if present.
+    DescriptorArray* descriptors = obj->map()->instance_descriptors();
+    DescriptorReader r(descriptors);
+    if (!r.eos() && (r.GetKey() == *key) && r.IsProperty()) {
+      ASSERT(r.type() == FIELD);
+      return Handle<Object>(obj->FastPropertyAt(r.GetFieldIndex()));
+    }
+  }
+
+  // Only attempt to find the hidden properties in the local object and not
+  // in the prototype chain.  Note that HasLocalProperty() can cause a GC  
in
+  // the general case in the presence of interceptors.
+  if (!obj->HasLocalProperty(*key)) {
+    // Hidden properties object not found. Allocate a new hidden properties
+    // object if requested. Otherwise return the undefined value.
+    if (create_if_needed) {
+      Handle<Object> hidden_obj =  
Factory::NewJSObject(Top::object_function());
+      return SetProperty(obj, key, hidden_obj, DONT_ENUM);
+    } else {
+      return Factory::undefined_value();
+    }
+  }
+  return GetProperty(obj, key);
  }



Modified: branches/bleeding_edge/src/handles.h
==============================================================================
--- branches/bleeding_edge/src/handles.h        (original)
+++ branches/bleeding_edge/src/handles.h        Tue May 12 15:07:10 2009
@@ -228,6 +228,9 @@

  Handle<Object> GetPrototype(Handle<Object> obj);

+// Return the object's hidden properties object. If the object has no  
hidden
+// properties and create_if_needed is true, then a new hidden property  
object
+// will be allocated. Otherwise the Heap::undefined_value is returned.
  Handle<Object> GetHiddenProperties(Handle<JSObject> obj, bool  
create_if_needed);

  Handle<Object> DeleteElement(Handle<JSObject> obj, uint32_t index);

Modified: branches/bleeding_edge/src/objects.cc
==============================================================================
--- branches/bleeding_edge/src/objects.cc       (original)
+++ branches/bleeding_edge/src/objects.cc       Tue May 12 15:07:10 2009
@@ -5145,42 +5145,6 @@
  }


-Object* JSObject::GetHiddenProperties(bool create_if_needed) {
-  String* key = Heap::hidden_symbol();
-  if (this->HasFastProperties()) {
-    // If the object has fast properties, check whether the first slot
-    // in the descriptor array matches the hidden symbol. Since the
-    // hidden symbols hash code is zero (and no other string has hash
-    // code zero) it will always occupy the first entry if present.
-    DescriptorArray* descriptors = this->map()->instance_descriptors();
-    DescriptorReader r(descriptors);
-    if (!r.eos() && (r.GetKey() == key) && r.IsProperty()) {
-      ASSERT(r.type() == FIELD);
-      return FastPropertyAt(r.GetFieldIndex());
-    }
-  }
-
-  // Only attempt to find the hidden properties in the local object and not
-  // in the prototype chain.  Note that HasLocalProperty() can cause a GC  
in
-  // the general case, but in this case we know it won't hit an  
interceptor.
-  if (!this->HasLocalProperty(key)) {
-    // Hidden properties object not found. Allocate a new hidden properties
-    // object if requested. Otherwise return the undefined value.
-    if (create_if_needed) {
-      Object* obj = Heap::AllocateJSObject(
-          Top::context()->global_context()->object_function());
-      if (obj->IsFailure()) {
-        return obj;
-      }
-      return this->SetProperty(key, obj, DONT_ENUM);
-    } else {
-      return Heap::undefined_value();
-    }
-  }
-  return this->GetProperty(key);
-}
-
-
  bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) {
    // Check access rights if needed.
    if (IsAccessCheckNeeded() &&

Modified: branches/bleeding_edge/src/objects.h
==============================================================================
--- branches/bleeding_edge/src/objects.h        (original)
+++ branches/bleeding_edge/src/objects.h        Tue May 12 15:07:10 2009
@@ -1286,11 +1286,6 @@
    // Return the object's prototype (might be Heap::null_value()).
    inline Object* GetPrototype();

-  // Return the object's hidden properties object. If the object has no  
hidden
-  // properties and create_if_needed is true, then a new hidden property  
object
-  // will be allocated. Otherwise the Heap::undefined_value is returned.
-  Object* GetHiddenProperties(bool create_if_needed);
-
    // Tells whether the index'th element is present.
    inline bool HasElement(uint32_t index);
    bool HasElementWithReceiver(JSObject* receiver, uint32_t index);

Modified: branches/bleeding_edge/test/cctest/test-api.cc
==============================================================================
--- branches/bleeding_edge/test/cctest/test-api.cc      (original)
+++ branches/bleeding_edge/test/cctest/test-api.cc      Tue May 12 15:07:10 2009
@@ -1327,6 +1327,38 @@
  }


+static v8::Handle<Value> InterceptorForHiddenProperties(
+    Local<String> name, const AccessorInfo& info) {
+  // Make sure objects move.
+  bool saved_always_compact = i::FLAG_always_compact;
+  if (!i::FLAG_never_compact) {
+    i::FLAG_always_compact = true;
+  }
+  // The whole goal of this interceptor is to cause a GC during local  
property
+  // lookup.
+  i::Heap::CollectAllGarbage();
+  i::FLAG_always_compact = saved_always_compact;
+  return v8::Handle<Value>();
+}
+
+
+THREADED_TEST(HiddenPropertiesWithInterceptors) {
+  v8::HandleScope scope;
+  LocalContext context;
+
+  v8::Local<v8::String> key = v8_str("api-test::hidden-key");
+
+  // Associate an interceptor with an object and start setting hidden  
values.
+  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+  Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
+  instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
+  Local<v8::Function> function = fun_templ->GetFunction();
+  Local<v8::Object> obj = function->NewInstance();
+  CHECK(obj->SetHiddenValue(key, v8::Integer::New(2302)));
+  CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
+}
+
+
  THREADED_TEST(External) {
    v8::HandleScope scope;
    int x = 3;

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to