Index: src/heap.cc |
=================================================================== |
--- src/heap.cc (revision 2578) |
+++ src/heap.cc (working copy) |
@@ -2103,6 +2103,11 @@ |
// properly initialized. |
ASSERT(map->instance_type() != JS_FUNCTION_TYPE); |
+ // Both types of globla objects should be allocated using |
+ // AllocateGloblaObject to be properly initialized. |
+ ASSERT(map->instance_type() != JS_GLOBAL_OBJECT_TYPE); |
+ ASSERT(map->instance_type() != JS_BUILTINS_OBJECT_TYPE); |
+ |
// Allocate the backing storage for the properties. |
int prop_size = map->unused_property_fields() - map->inobject_properties(); |
Object* properties = AllocateFixedArray(prop_size, pretenure); |
@@ -2143,25 +2148,63 @@ |
Object* Heap::AllocateGlobalObject(JSFunction* constructor) { |
ASSERT(constructor->has_initial_map()); |
+ Map* map = constructor->initial_map(); |
+ |
// Make sure no field properties are described in the initial map. |
// This guarantees us that normalizing the properties does not |
// require us to change property values to JSGlobalPropertyCells. |
- ASSERT(constructor->initial_map()->NextFreePropertyIndex() == 0); |
+ ASSERT(map->NextFreePropertyIndex() == 0); |
// Make sure we don't have a ton of pre-allocated slots in the |
// global objects. They will be unused once we normalize the object. |
- ASSERT(constructor->initial_map()->unused_property_fields() == 0); |
- ASSERT(constructor->initial_map()->inobject_properties() == 0); |
+ ASSERT(map->unused_property_fields() == 0); |
+ ASSERT(map->inobject_properties() == 0); |
- // Allocate the object based on the constructors initial map. |
- Object* result = AllocateJSObjectFromMap(constructor->initial_map(), TENURED); |
- if (result->IsFailure()) return result; |
+ // Initial size of the backing store to avoid resize of the storage during |
+ // bootstrapping. The size differs between the JS global object ad the |
+ // builtins object. |
+ int initial_size = map->instance_type() == JS_GLOBAL_OBJECT_TYPE ? 64 : 512; |
- // Normalize the result. |
- JSObject* global = JSObject::cast(result); |
- result = global->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); |
- if (result->IsFailure()) return result; |
+ // Allocate a dictionary object for backing storage. |
+ Object* obj = |
+ StringDictionary::Allocate( |
+ map->NumberOfDescribedProperties() * 2 + initial_size); |
+ if (obj->IsFailure()) return obj; |
+ StringDictionary* dictionary = StringDictionary::cast(obj); |
+ // The global object might be created from an object template with accessors. |
+ // Fill these accessors into the dictionary. |
+ DescriptorArray* descs = map->instance_descriptors(); |
+ for (int i = 0; i < descs->number_of_descriptors(); i++) { |
+ PropertyDetails details = descs->GetDetails(i); |
+ ASSERT(details.type() == CALLBACKS); // Only accessors are expected. |
+ PropertyDetails d = |
+ PropertyDetails(details.attributes(), CALLBACKS, details.index()); |
+ Object* value = descs->GetCallbacksObject(i); |
+ value = Heap::AllocateJSGlobalPropertyCell(value); |
+ if (value->IsFailure()) return value; |
+ |
+ Object* result = dictionary->Add(descs->GetKey(i), value, d); |
+ if (result->IsFailure()) return result; |
+ dictionary = StringDictionary::cast(result); |
+ } |
+ |
+ // Allocate the global object and initialize it with the backing store. |
+ obj = Allocate(map, OLD_POINTER_SPACE); |
+ if (obj->IsFailure()) return obj; |
+ JSObject* global = JSObject::cast(obj); |
+ InitializeJSObjectFromMap(global, dictionary, map); |
+ |
+ // Create a new map for the global object. |
+ obj = map->CopyDropDescriptors(); |
+ if (obj->IsFailure()) return obj; |
+ Map* new_map = Map::cast(obj); |
+ |
+ // Setup the global object as a normalized object. |
+ global->set_map(new_map); |
+ global->map()->set_instance_descriptors(Heap::empty_descriptor_array()); |
+ global->set_properties(dictionary); |
+ |
// Make sure result is a global object with properties in dictionary. |
ASSERT(global->IsGlobalObject()); |
ASSERT(!global->HasFastProperties()); |