Make 'Become' safe for retries.
authorrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 5 Oct 2011 09:41:54 +0000 (09:41 +0000)
committerrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 5 Oct 2011 09:41:54 +0000 (09:41 +0000)
R=ricow@chromium.org
BUG=
TEST=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9524 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/factory.cc
src/factory.h
src/heap.cc
src/heap.h
src/objects.cc

index 00fc6bb..252c97c 100644 (file)
@@ -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 3c45291..85f46c5 100644 (file)
@@ -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 522861d..8674ba0 100644 (file)
@@ -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,22 @@ 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;
   }
 
+  // Because of possible retries of this function after failure,
+  // we must NOT fail after this point, where we have changed the type!
+
   // Reset the map for the object.
   object->set_map(map);
   JSObject* jsobj = JSObject::cast(object);
@@ -3851,17 +3860,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 +3871,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 4a1e01d..499c30e 100644 (file)
@@ -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 105dfd1..3e280fd 100644 (file)
@@ -2606,6 +2606,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.
@@ -2613,6 +2616,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);
+  }
 }