Handlify JSObject::MigrateInstance and friends.

This relands the original change from r16899 together with a bugfix for
two unhandlified values which became stale.

R=verwaest@chromium.org
TEST=mjsunit/debug-evaluate-locals-optimized (in GC stress mode)

Review URL: https://codereview.chromium.org/24210011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16905 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2ad4ad92
......@@ -4106,7 +4106,7 @@ static bool IsFastLiteral(Handle<JSObject> boilerplate,
int* max_properties) {
if (boilerplate->map()->is_deprecated()) {
Handle<Object> result = JSObject::TryMigrateInstance(boilerplate);
if (result->IsSmi()) return false;
if (result.is_null()) return false;
}
ASSERT(max_depth >= 0 && *max_properties >= 0);
......
......@@ -285,14 +285,13 @@ bool Object::HasValidElements() {
MaybeObject* Object::AllocateNewStorageFor(Heap* heap,
Representation representation,
PretenureFlag tenure) {
Representation representation) {
if (!FLAG_track_double_fields) return this;
if (!representation.IsDouble()) return this;
if (IsUninitialized()) {
return heap->AllocateHeapNumber(0, tenure);
return heap->AllocateHeapNumber(0);
}
return heap->AllocateHeapNumber(Number(), tenure);
return heap->AllocateHeapNumber(Number());
}
......@@ -1542,19 +1541,6 @@ MaybeObject* JSObject::ResetElements() {
}
MaybeObject* JSObject::TryMigrateInstance() {
Map* new_map = map()->CurrentMapForDeprecated();
if (new_map == NULL) return Smi::FromInt(0);
Map* original_map = map();
MaybeObject* maybe_result = MigrateToMap(new_map);
JSObject* result;
if (FLAG_trace_migration && maybe_result->To(&result)) {
PrintInstanceMigration(stdout, original_map, result->map());
}
return maybe_result;
}
Handle<String> JSObject::ExpectedTransitionKey(Handle<Map> map) {
DisallowHeapAllocation no_gc;
if (!map->HasTransitionArray()) return Handle<String>::null();
......
......@@ -2270,11 +2270,6 @@ bool Map::InstancesNeedRewriting(Map* target,
}
void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), object->MigrateToMap(*new_map));
}
// To migrate an instance to a map:
// - First check whether the instance needs to be rewritten. If not, simply
// change the map.
......@@ -2290,28 +2285,27 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
// to temporarily store the inobject properties.
// * If there are properties left in the backing store, install the backing
// store.
MaybeObject* JSObject::MigrateToMap(Map* new_map) {
Heap* heap = GetHeap();
Map* old_map = map();
void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
Isolate* isolate = object->GetIsolate();
Handle<Map> old_map(object->map());
int number_of_fields = new_map->NumberOfFields();
int inobject = new_map->inobject_properties();
int unused = new_map->unused_property_fields();
// Nothing to do if no functions were converted to fields.
// Nothing to do if no functions were converted to fields and no smis were
// converted to doubles.
if (!old_map->InstancesNeedRewriting(
new_map, number_of_fields, inobject, unused)) {
set_map(new_map);
return this;
*new_map, number_of_fields, inobject, unused)) {
object->set_map(*new_map);
return;
}
int total_size = number_of_fields + unused;
int external = total_size - inobject;
FixedArray* array;
MaybeObject* maybe_array = heap->AllocateFixedArray(total_size);
if (!maybe_array->To(&array)) return maybe_array;
Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
DescriptorArray* old_descriptors = old_map->instance_descriptors();
DescriptorArray* new_descriptors = new_map->instance_descriptors();
Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
int descriptors = new_map->NumberOfOwnDescriptors();
for (int i = 0; i < descriptors; i++) {
......@@ -2324,55 +2318,51 @@ MaybeObject* JSObject::MigrateToMap(Map* new_map) {
}
ASSERT(old_details.type() == CONSTANT ||
old_details.type() == FIELD);
Object* value = old_details.type() == CONSTANT
Object* raw_value = old_details.type() == CONSTANT
? old_descriptors->GetValue(i)
: RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
: object->RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
Handle<Object> value(raw_value, isolate);
if (FLAG_track_double_fields &&
!old_details.representation().IsDouble() &&
details.representation().IsDouble()) {
if (old_details.representation().IsNone()) value = Smi::FromInt(0);
// Objects must be allocated in the old object space, since the
// overall number of HeapNumbers needed for the conversion might
// exceed the capacity of new space, and we would fail repeatedly
// trying to migrate the instance.
MaybeObject* maybe_storage =
value->AllocateNewStorageFor(heap, details.representation(), TENURED);
if (!maybe_storage->To(&value)) return maybe_storage;
if (old_details.representation().IsNone()) {
value = handle(Smi::FromInt(0), isolate);
}
value = NewStorageFor(isolate, value, details.representation());
}
ASSERT(!(FLAG_track_double_fields &&
details.representation().IsDouble() &&
value->IsSmi()));
int target_index = new_descriptors->GetFieldIndex(i) - inobject;
if (target_index < 0) target_index += total_size;
array->set(target_index, value);
array->set(target_index, *value);
}
// From here on we cannot fail anymore.
// From here on we cannot fail and we shouldn't GC anymore.
DisallowHeapAllocation no_allocation;
// Copy (real) inobject properties. If necessary, stop at number_of_fields to
// avoid overwriting |one_pointer_filler_map|.
int limit = Min(inobject, number_of_fields);
for (int i = 0; i < limit; i++) {
FastPropertyAtPut(i, array->get(external + i));
object->FastPropertyAtPut(i, array->get(external + i));
}
// Create filler object past the new instance size.
int new_instance_size = new_map->instance_size();
int instance_size_delta = old_map->instance_size() - new_instance_size;
ASSERT(instance_size_delta >= 0);
Address address = this->address() + new_instance_size;
heap->CreateFillerObjectAt(address, instance_size_delta);
Address address = object->address() + new_instance_size;
isolate->heap()->CreateFillerObjectAt(address, instance_size_delta);
// If there are properties in the new backing store, trim it to the correct
// size and install the backing store into the object.
if (external > 0) {
RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject);
set_properties(array);
RightTrimFixedArray<FROM_MUTATOR>(isolate->heap(), *array, inobject);
object->set_properties(*array);
}
set_map(new_map);
return this;
object->set_map(*new_map);
}
......@@ -3758,7 +3748,13 @@ void JSObject::MigrateInstance(Handle<JSObject> object) {
Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) {
MigrateInstance(object);
Map* new_map = object->map()->CurrentMapForDeprecated();
if (new_map == NULL) return Handle<Object>();
Handle<Map> original_map(object->map());
JSObject::MigrateToMap(object, handle(new_map));
if (FLAG_trace_migration) {
object->PrintInstanceMigration(stdout, *original_map, object->map());
}
return object;
}
......
......@@ -1440,8 +1440,7 @@ class Object : public MaybeObject {
}
inline MaybeObject* AllocateNewStorageFor(Heap* heap,
Representation representation,
PretenureFlag tenure = NOT_TENURED);
Representation representation);
// Returns true if the object is of the correct type to be used as a
// implementation of a JSObject's elements.
......@@ -2173,10 +2172,13 @@ class JSObject: public JSReceiver {
// passed map. This also extends the property backing store if necessary.
static void AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map);
// Migrates the given object to a map whose field representations are the
// lowest upper bound of all known representations for that field.
static void MigrateInstance(Handle<JSObject> instance);
// Migrates the given object only if the target map is already available,
// or returns an empty handle if such a map is not yet available.
static Handle<Object> TryMigrateInstance(Handle<JSObject> instance);
inline MUST_USE_RESULT MaybeObject* TryMigrateInstance();
// Can cause GC.
MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributesTrampoline(
......@@ -2470,8 +2472,8 @@ class JSObject: public JSReceiver {
MUST_USE_RESULT MaybeObject* TransitionElementsKind(ElementsKind to_kind);
MUST_USE_RESULT MaybeObject* UpdateAllocationSite(ElementsKind to_kind);
// TODO(mstarzinger): Both public because of ConvertAnsSetLocalProperty().
static void MigrateToMap(Handle<JSObject> object, Handle<Map> new_map);
MUST_USE_RESULT MaybeObject* MigrateToMap(Map* new_map);
static void GeneralizeFieldRepresentation(Handle<JSObject> object,
int modify_index,
Representation new_representation,
......
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