Commit 2c975d6a authored by rossberg@chromium.org's avatar rossberg@chromium.org

Make 'Become' safe for retries.

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
parent d8d7d2d3
......@@ -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,
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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);
}
}
......
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