Reviewers: Rico,

Description:
Make 'Become' safe for retries.

[email protected]
BUG=
TEST=


Please review this at http://codereview.chromium.org/8138003/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/factory.h
  M src/factory.cc
  M src/heap.h
  M src/heap.cc
  M src/objects.cc


Index: src/factory.cc
diff --git a/src/factory.cc b/src/factory.cc
index 00fc6bbcb33c63c2f354ffebcc9d1c1a1f14fda0..252c97ced3177e5e0e32845e0fead4d765d34aab 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -948,6 +948,13 @@ void Factory::BecomeJSFunction(Handle<JSReceiver> object) {
 }


+void Factory::SetIdentityHash(Handle<JSObject> object, Object* hash) {
+  CALL_HEAP_FUNCTION_VOID(
+      isolate(),
+      object->SetIdentityHash(hash, ALLOW_CREATION));
+}
+
+
 Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
     Handle<String> name,
     int number_of_literals,
Index: src/factory.h
diff --git a/src/factory.h b/src/factory.h
index 3c45291f355dc3bac59b13e5ad6df234d8fe4ef7..85f46c530bc8df40785484d28d8f5c0db8a5004b 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -265,6 +265,8 @@ class Factory {
   void BecomeJSObject(Handle<JSReceiver> object);
   void BecomeJSFunction(Handle<JSReceiver> object);

+  void SetIdentityHash(Handle<JSObject> object, Object* hash);
+
   Handle<JSFunction> NewFunction(Handle<String> name,
                                  Handle<Object> prototype);

Index: src/heap.cc
diff --git a/src/heap.cc b/src/heap.cc
index 522861deda05e2a163861ac527be202631387441..94d73a2148ff9442e5da75cbdc5e0904cbe08aa5 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -3321,9 +3321,9 @@ MaybeObject* Heap::Allocate(Map* map, AllocationSpace space) {
 }


-MaybeObject* Heap::InitializeFunction(JSFunction* function,
-                                      SharedFunctionInfo* shared,
-                                      Object* prototype) {
+void Heap::InitializeFunction(JSFunction* function,
+                              SharedFunctionInfo* shared,
+                              Object* prototype) {
   ASSERT(!prototype->IsMap());
   function->initialize_properties();
   function->initialize_elements();
@@ -3333,7 +3333,6 @@ MaybeObject* Heap::InitializeFunction(JSFunction* function,
   function->set_context(undefined_value());
   function->set_literals(empty_fixed_array());
   function->set_next_function_link(undefined_value());
-  return function;
 }


@@ -3379,7 +3378,8 @@ MaybeObject* Heap::AllocateFunction(Map* function_map,
   { MaybeObject* maybe_result = Allocate(function_map, space);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
-  return InitializeFunction(JSFunction::cast(result), shared, prototype);
+  InitializeFunction(JSFunction::cast(result), shared, prototype);
+  return result;
 }


@@ -3819,9 +3819,6 @@ MaybeObject* Heap::ReinitializeJSReceiver(
     JSReceiver* object, InstanceType type, int size) {
   ASSERT(type >= FIRST_JS_OBJECT_TYPE);

-  // Save identity hash.
-  MaybeObject* maybe_hash = object->GetIdentityHash(OMIT_CREATION);
-
   // Allocate fresh map.
   // TODO(rossberg): Once we optimize proxies, cache these maps.
   Map* map;
@@ -3837,10 +3834,21 @@ MaybeObject* Heap::ReinitializeJSReceiver(
   // Allocate the backing storage for the properties.
int prop_size = map->unused_property_fields() - map->inobject_properties();
   Object* properties;
-  { MaybeObject* maybe_properties = AllocateFixedArray(prop_size, TENURED);
-    if (!maybe_properties->ToObject(&properties)) return maybe_properties;
+  maybe = AllocateFixedArray(prop_size, TENURED);
+  if (!maybe->ToObject(&properties)) return maybe;
+
+  // Functions require some allocation, which might fail here.
+  SharedFunctionInfo* shared = NULL;
+  if (type == JS_FUNCTION_TYPE) {
+    String* name;
+    maybe = LookupAsciiSymbol("<freezing call trap>");
+    if (!maybe->To<String>(&name)) return maybe;
+    maybe = AllocateSharedFunctionInfo(name);
+    if (!maybe->To<SharedFunctionInfo>(&shared)) return maybe;
   }

+  // We must NOT fail after this point!
+
   // Reset the map for the object.
   object->set_map(map);
   JSObject* jsobj = JSObject::cast(object);
@@ -3851,17 +3859,9 @@ MaybeObject* Heap::ReinitializeJSReceiver(
   // Functions require some minimal initialization.
   if (type == JS_FUNCTION_TYPE) {
     map->set_function_with_prototype(true);
-    String* name;
-    maybe = LookupAsciiSymbol("<freezing call trap>");
-    if (!maybe->To<String>(&name)) return maybe;
-    SharedFunctionInfo* shared;
-    maybe = AllocateSharedFunctionInfo(name);
-    if (!maybe->To<SharedFunctionInfo>(&shared)) return maybe;
-    JSFunction* func;
-    maybe = InitializeFunction(
-        JSFunction::cast(object), shared, the_hole_value());
-    if (!maybe->To<JSFunction>(&func)) return maybe;
-    func->set_context(isolate()->context()->global_context());
+    InitializeFunction(JSFunction::cast(object), shared, the_hole_value());
+    JSFunction::cast(object)->set_context(
+        isolate()->context()->global_context());
   }

   // Put in filler if the new object is smaller than the old.
@@ -3870,13 +3870,6 @@ MaybeObject* Heap::ReinitializeJSReceiver(
         object->address() + map->instance_size(), size_difference);
   }

-  // Inherit identity, if it was present.
-  Object* hash;
-  if (maybe_hash->To<Object>(&hash) && hash->IsSmi()) {
-    maybe = jsobj->SetIdentityHash(hash, ALLOW_CREATION);
-    if (maybe->IsFailure()) return maybe;
-  }
-
   return object;
 }

Index: src/heap.h
diff --git a/src/heap.h b/src/heap.h
index 4a1e01dcaa3135aa4ebd452259c847f60a9e70ab..499c30ecab8971cf1430b87f91236ad317217b8a 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -1685,12 +1685,11 @@ class Heap {
   static void ScavengeObjectSlow(HeapObject** p, HeapObject* object);

   // Initializes a function with a shared part and prototype.
-  // Returns the function.
   // Note: this code was factored out of AllocateFunction such that
// other parts of the VM could use it. Specifically, a function that creates // instances of type JS_FUNCTION_TYPE benefit from the use of this function.
   // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT inline MaybeObject* InitializeFunction(
+  inline void InitializeFunction(
       JSFunction* function,
       SharedFunctionInfo* shared,
       Object* prototype);
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 9e62e3fe0d212c88959986c9fb262836b6ec1161..883231ca6ce6444ba661126dd200576711287b0e 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -2607,6 +2607,9 @@ void JSProxy::Fix() {
   HandleScope scope(isolate);
   Handle<JSProxy> self(this);

+  // Save identity hash.
+  MaybeObject* maybe_hash = GetIdentityHash(OMIT_CREATION);
+
   if (IsJSFunctionProxy()) {
     isolate->factory()->BecomeJSFunction(self);
     // Code will be set on the JavaScript side.
@@ -2614,6 +2617,13 @@ void JSProxy::Fix() {
     isolate->factory()->BecomeJSObject(self);
   }
   ASSERT(self->IsJSObject());
+
+  // Inherit identity, if it was present.
+  Object* hash;
+  if (maybe_hash->To<Object>(&hash) && hash->IsSmi()) {
+    Handle<JSObject> new_self(JSObject::cast(*self));
+    isolate->factory()->SetIdentityHash(new_self, hash);
+  }
 }




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

Reply via email to