From 6cfc5f1ef99a327d7f88f9437ae730c6f52f97d1 Mon Sep 17 00:00:00 2001 From: "kasperl@chromium.org" Date: Wed, 1 Jul 2009 11:44:37 +0000 Subject: [PATCH] Treat the builtins object like other global objects (with cells in old space for properties) and avoid allocating tons of unused properties in new space when creating new contexts. Review URL: http://codereview.chromium.org/151146 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2319 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/stub-cache-arm.cc | 6 +++--- src/bootstrapper.cc | 13 +++---------- src/factory.cc | 6 +++--- src/factory.h | 5 ++--- src/heap.cc | 21 +++++++++++++-------- src/heap.h | 4 ++-- src/ia32/stub-cache-ia32.cc | 6 +++--- src/ic.cc | 12 ++++++------ src/objects.cc | 28 ++++++++++++++-------------- src/objects.h | 6 +++--- src/property.h | 2 +- src/runtime.cc | 2 +- src/stub-cache.cc | 6 +++--- src/stub-cache.h | 12 ++++++------ src/x64/stub-cache-x64.cc | 6 +++--- 15 files changed, 66 insertions(+), 69 deletions(-) diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc index 71f2225..44e6478 100644 --- a/src/arm/stub-cache-arm.cc +++ b/src/arm/stub-cache-arm.cc @@ -684,7 +684,7 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object, } -Object* CallStubCompiler::CompileCallGlobal(JSGlobalObject* object, +Object* CallStubCompiler::CompileCallGlobal(GlobalObject* object, JSGlobalPropertyCell* cell, JSFunction* function, String* name) { @@ -879,7 +879,7 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, } -Object* StoreStubCompiler::CompileStoreGlobal(JSGlobalObject* object, +Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, JSGlobalPropertyCell* cell, String* name) { // ----------- S t a t e ------------- @@ -1012,7 +1012,7 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, } -Object* LoadStubCompiler::CompileLoadGlobal(JSGlobalObject* object, +Object* LoadStubCompiler::CompileLoadGlobal(GlobalObject* object, JSGlobalPropertyCell* cell, String* name, bool is_dont_delete) { diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index ffd432a..f3c7c5f 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -539,7 +539,7 @@ void Genesis::CreateRoots(v8::Handle global_template, { // --- G l o b a l --- // Step 1: create a fresh inner JSGlobalObject - Handle object; + Handle object; { Handle js_global_function; Handle js_global_template; @@ -579,8 +579,7 @@ void Genesis::CreateRoots(v8::Handle global_template, } js_global_function->initial_map()->set_is_hidden_prototype(); - SetExpectedNofProperties(js_global_function, 100); - object = Factory::NewJSGlobalObject(js_global_function); + object = Factory::NewGlobalObject(js_global_function); } // Set the global context for the global object. @@ -962,12 +961,10 @@ bool Genesis::InstallNatives() { Handle name = Factory::LookupAsciiSymbol("builtins"); builtins_fun->shared()->set_instance_class_name(*name); - SetExpectedNofProperties(builtins_fun, 100); // Allocate the builtins object. Handle builtins = - Handle::cast(Factory::NewJSObject(builtins_fun, - TENURED)); + Handle::cast(Factory::NewGlobalObject(builtins_fun)); builtins->set_builtins(*builtins); builtins->set_global_context(*global_context()); builtins->set_global_receiver(*builtins); @@ -1190,10 +1187,6 @@ bool Genesis::InstallNatives() { apply->shared()->set_length(2); } - // Make sure that the builtins object has fast properties. - // If the ASSERT below fails, please increase the expected number of - // properties for the builtins object. - ASSERT(builtins->HasFastProperties()); #ifdef DEBUG builtins->Verify(); #endif diff --git a/src/factory.cc b/src/factory.cc index bc48ebf..216a07e 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -619,10 +619,10 @@ Handle Factory::NewJSObject(Handle constructor, } -Handle Factory::NewJSGlobalObject( +Handle Factory::NewGlobalObject( Handle constructor) { - CALL_HEAP_FUNCTION(Heap::AllocateJSGlobalObject(*constructor), - JSGlobalObject); + CALL_HEAP_FUNCTION(Heap::AllocateGlobalObject(*constructor), + GlobalObject); } diff --git a/src/factory.h b/src/factory.h index 40cf578..1ec9f1b 100644 --- a/src/factory.h +++ b/src/factory.h @@ -183,9 +183,8 @@ class Factory : public AllStatic { static Handle NewJSObject(Handle constructor, PretenureFlag pretenure = NOT_TENURED); - // JS global objects are pretenured. - static Handle NewJSGlobalObject( - Handle constructor); + // Global objects are pretenured. + static Handle NewGlobalObject(Handle constructor); // JS objects are pretenured when allocated by the bootstrapper and // runtime. diff --git a/src/heap.cc b/src/heap.cc index a29340c..56f1f97 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -1558,7 +1558,7 @@ Object* Heap::AllocateProxy(Address proxy, PretenureFlag pretenure) { Object* Heap::AllocateSharedFunctionInfo(Object* name) { - Object* result = Allocate(shared_function_info_map(), NEW_SPACE); + Object* result = Allocate(shared_function_info_map(), OLD_POINTER_SPACE); if (result->IsFailure()) return result; SharedFunctionInfo* share = SharedFunctionInfo::cast(result); @@ -2050,7 +2050,7 @@ Object* Heap::AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure) { // Allocate the backing storage for the properties. int prop_size = map->unused_property_fields() - map->inobject_properties(); - Object* properties = AllocateFixedArray(prop_size); + Object* properties = AllocateFixedArray(prop_size, pretenure); if (properties->IsFailure()) return properties; // Allocate the JSObject. @@ -2080,19 +2080,24 @@ Object* Heap::AllocateJSObject(JSFunction* constructor, // Allocate the object based on the constructors initial map. Object* result = AllocateJSObjectFromMap(constructor->initial_map(), pretenure); - // Make sure result is NOT a JS global object if valid. - ASSERT(result->IsFailure() || !result->IsJSGlobalObject()); + // Make sure result is NOT a global object if valid. + ASSERT(result->IsFailure() || !result->IsGlobalObject()); return result; } -Object* Heap::AllocateJSGlobalObject(JSFunction* constructor) { +Object* Heap::AllocateGlobalObject(JSFunction* constructor) { ASSERT(constructor->has_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); + // 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); + // Allocate the object based on the constructors initial map. Object* result = AllocateJSObjectFromMap(constructor->initial_map(), TENURED); if (result->IsFailure()) return result; @@ -2102,8 +2107,8 @@ Object* Heap::AllocateJSGlobalObject(JSFunction* constructor) { result = global->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); if (result->IsFailure()) return result; - // Make sure result is a JS global object with properties in dictionary. - ASSERT(global->IsJSGlobalObject()); + // Make sure result is a global object with properties in dictionary. + ASSERT(global->IsGlobalObject()); ASSERT(!global->HasFastProperties()); return global; } @@ -2182,7 +2187,7 @@ Object* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor, // Allocate the backing storage for the properties. int prop_size = map->unused_property_fields() - map->inobject_properties(); - Object* properties = AllocateFixedArray(prop_size); + Object* properties = AllocateFixedArray(prop_size, TENURED); if (properties->IsFailure()) return properties; // Reset the map for the object. diff --git a/src/heap.h b/src/heap.h index 3667348..77cea1b 100644 --- a/src/heap.h +++ b/src/heap.h @@ -289,11 +289,11 @@ class Heap : public AllStatic { static Object* AllocateJSObject(JSFunction* constructor, PretenureFlag pretenure = NOT_TENURED); - // Allocates and initializes a new JS global object based on a constructor. + // Allocates and initializes a new global object based on a constructor. // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // Please note this does not perform a garbage collection. - static Object* AllocateJSGlobalObject(JSFunction* constructor); + static Object* AllocateGlobalObject(JSFunction* constructor); // Returns a deep copy of the JavaScript object. // Properties and elements are copied too. diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc index 83beb65..6f84edc 100644 --- a/src/ia32/stub-cache-ia32.cc +++ b/src/ia32/stub-cache-ia32.cc @@ -715,7 +715,7 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object, } -Object* CallStubCompiler::CompileCallGlobal(JSGlobalObject* object, +Object* CallStubCompiler::CompileCallGlobal(GlobalObject* object, JSGlobalPropertyCell* cell, JSFunction* function, String* name) { @@ -911,7 +911,7 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, } -Object* StoreStubCompiler::CompileStoreGlobal(JSGlobalObject* object, +Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, JSGlobalPropertyCell* cell, String* name) { // ----------- S t a t e ------------- @@ -1092,7 +1092,7 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, } -Object* LoadStubCompiler::CompileLoadGlobal(JSGlobalObject* object, +Object* LoadStubCompiler::CompileLoadGlobal(GlobalObject* object, JSGlobalPropertyCell* cell, String* name, bool is_dont_delete) { diff --git a/src/ic.cc b/src/ic.cc index e062dd9..932f325 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -419,11 +419,11 @@ void CallIC::UpdateCaches(LookupResult* lookup, } case NORMAL: { if (!object->IsJSObject()) return; - if (object->IsJSGlobalObject()) { + if (object->IsGlobalObject()) { // The stub generated for the global object picks the value directly // from the property cell. So the property must be directly on the // global object. - Handle global = Handle::cast(object); + Handle global = Handle::cast(object); if (lookup->holder() != *global) return; JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); @@ -624,11 +624,11 @@ void LoadIC::UpdateCaches(LookupResult* lookup, break; } case NORMAL: { - if (object->IsJSGlobalObject()) { + if (object->IsGlobalObject()) { // The stub generated for the global object picks the value directly // from the property cell. So the property must be directly on the // global object. - Handle global = Handle::cast(object); + Handle global = Handle::cast(object); if (lookup->holder() != *global) return; JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); @@ -976,13 +976,13 @@ void StoreIC::UpdateCaches(LookupResult* lookup, break; } case NORMAL: { - if (!receiver->IsJSGlobalObject()) { + if (!receiver->IsGlobalObject()) { return; } // The stub generated for the global object picks the value directly // from the property cell. So the property must be directly on the // global object. - Handle global = Handle::cast(receiver); + Handle global = Handle::cast(receiver); JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); code = StubCache::ComputeStoreGlobal(*name, *global, cell); diff --git a/src/objects.cc b/src/objects.cc index 470333d..a967e7b 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -402,7 +402,7 @@ Object* JSObject::DeleteLazyProperty(LookupResult* result, Object* JSObject::GetNormalizedProperty(LookupResult* result) { ASSERT(!HasFastProperties()); Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); - if (IsJSGlobalObject()) { + if (IsGlobalObject()) { value = JSGlobalPropertyCell::cast(value)->value(); } ASSERT(!value->IsJSGlobalPropertyCell()); @@ -412,7 +412,7 @@ Object* JSObject::GetNormalizedProperty(LookupResult* result) { Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) { ASSERT(!HasFastProperties()); - if (IsJSGlobalObject()) { + if (IsGlobalObject()) { JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast( property_dictionary()->ValueAt(result->GetDictionaryEntry())); @@ -431,7 +431,7 @@ Object* JSObject::SetNormalizedProperty(String* name, int entry = property_dictionary()->FindStringEntry(name); if (entry == Dictionary::kNotFound) { Object* store_value = value; - if (IsJSGlobalObject()) { + if (IsGlobalObject()) { store_value = Heap::AllocateJSGlobalPropertyCell(value); if (store_value->IsFailure()) return store_value; } @@ -445,7 +445,7 @@ Object* JSObject::SetNormalizedProperty(String* name, details = PropertyDetails(details.attributes(), details.type(), property_dictionary()->DetailsAt(entry).index()); - if (IsJSGlobalObject()) { + if (IsGlobalObject()) { JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry)); cell->set_value(value); @@ -464,7 +464,7 @@ Object* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { int entry = dictionary->FindStringEntry(name); if (entry != Dictionary::kNotFound) { // If we have a global object set the cell to the hole. - if (IsJSGlobalObject()) { + if (IsGlobalObject()) { PropertyDetails details = dictionary->DetailsAt(entry); if (details.IsDontDelete() && mode != FORCE_DELETION) { return Heap::false_value(); @@ -1342,7 +1342,7 @@ Object* JSObject::AddSlowProperty(String* name, ASSERT(!HasFastProperties()); Dictionary* dict = property_dictionary(); Object* store_value = value; - if (IsJSGlobalObject()) { + if (IsGlobalObject()) { // In case name is an orphaned property reuse the cell. int entry = dict->FindStringEntry(name); if (entry != Dictionary::kNotFound) { @@ -1703,7 +1703,7 @@ void JSObject::LocalLookupRealNamedProperty(String* name, // Make sure to disallow caching for uninitialized constants // found in the dictionary-mode objects. Object* value = property_dictionary()->ValueAt(entry); - if (IsJSGlobalObject()) { + if (IsGlobalObject()) { PropertyDetails d = property_dictionary()->DetailsAt(entry); if (d.IsDeleted()) { result->NotFound(); @@ -2114,7 +2114,7 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) { PropertyDetails d = PropertyDetails(details.attributes(), NORMAL, details.index()); Object* value = r.GetConstantFunction(); - if (IsJSGlobalObject()) { + if (IsGlobalObject()) { value = Heap::AllocateJSGlobalPropertyCell(value); if (value->IsFailure()) return value; } @@ -2127,7 +2127,7 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) { PropertyDetails d = PropertyDetails(details.attributes(), NORMAL, details.index()); Object* value = FastPropertyAt(r.GetFieldIndex()); - if (IsJSGlobalObject()) { + if (IsGlobalObject()) { value = Heap::AllocateJSGlobalPropertyCell(value); if (value->IsFailure()) return value; } @@ -2140,7 +2140,7 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) { PropertyDetails d = PropertyDetails(details.attributes(), CALLBACKS, details.index()); Object* value = r.GetCallbacksObject(); - if (IsJSGlobalObject()) { + if (IsGlobalObject()) { value = Heap::AllocateJSGlobalPropertyCell(value); if (value->IsFailure()) return value; } @@ -2203,9 +2203,9 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) { Object* JSObject::TransformToFastProperties(int unused_property_fields) { if (HasFastProperties()) return this; - ASSERT(!IsJSGlobalObject()); + ASSERT(!IsGlobalObject()); return property_dictionary()-> - TransformPropertiesToFastFor(this, unused_property_fields); + TransformPropertiesToFastFor(this, unused_property_fields); } @@ -2740,7 +2740,7 @@ Object* JSObject::DefineGetterSetter(String* name, // For the global object allocate a new map to invalidate the global inline // caches which have a global property cell reference directly in the code. - if (IsJSGlobalObject()) { + if (IsGlobalObject()) { Object* new_map = map()->CopyDropDescriptors(); if (new_map->IsFailure()) return new_map; set_map(Map::cast(new_map)); @@ -6739,7 +6739,7 @@ Object* JSObject::PrepareElementsForSort(uint32_t limit) { } -Object* JSGlobalObject::GetPropertyCell(LookupResult* result) { +Object* GlobalObject::GetPropertyCell(LookupResult* result) { ASSERT(!HasFastProperties()); Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); ASSERT(value->IsJSGlobalPropertyCell()); diff --git a/src/objects.h b/src/objects.h index 775b6c7..4ebe6a1 100644 --- a/src/objects.h +++ b/src/objects.h @@ -3059,6 +3059,9 @@ class GlobalObject: public JSObject { // [global receiver]: the global receiver object of the context DECL_ACCESSORS(global_receiver, JSObject) + // Retrieve the property cell used to store a property. + Object* GetPropertyCell(LookupResult* result); + // Casting. static inline GlobalObject* cast(Object* obj); @@ -3079,9 +3082,6 @@ class GlobalObject: public JSObject { class JSGlobalObject: public GlobalObject { public: - // Retrieve the property cell used to store a property. - Object* GetPropertyCell(LookupResult* result); - // Casting. static inline JSGlobalObject* cast(Object* obj); diff --git a/src/property.h b/src/property.h index 851bae2..69e5640 100644 --- a/src/property.h +++ b/src/property.h @@ -260,7 +260,7 @@ class LookupResult BASE_EMBEDDED { case NORMAL: { Object* value; value = holder()->property_dictionary()->ValueAt(GetDictionaryEntry()); - if (holder()->IsJSGlobalObject()) { + if (holder()->IsGlobalObject()) { value = JSGlobalPropertyCell::cast(value)->value(); } return value; diff --git a/src/runtime.cc b/src/runtime.cc index 28254f7..fa05943 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -2609,7 +2609,7 @@ static Object* Runtime_KeyedGetProperty(Arguments args) { if ((entry != Dictionary::kNotFound) && (dictionary->DetailsAt(entry).type() == NORMAL)) { Object* value = dictionary->ValueAt(entry); - if (receiver->IsJSGlobalObject()) { + if (receiver->IsGlobalObject()) { value = JSGlobalPropertyCell::cast(value)->value(); } return value; diff --git a/src/stub-cache.cc b/src/stub-cache.cc index 1999d13..f7ba9f3 100644 --- a/src/stub-cache.cc +++ b/src/stub-cache.cc @@ -173,7 +173,7 @@ Object* StubCache::ComputeLoadNormal(String* name, JSObject* receiver) { Object* StubCache::ComputeLoadGlobal(String* name, - JSGlobalObject* receiver, + GlobalObject* receiver, JSGlobalPropertyCell* cell, bool is_dont_delete) { Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); @@ -336,7 +336,7 @@ Object* StubCache::ComputeStoreField(String* name, Object* StubCache::ComputeStoreGlobal(String* name, - JSGlobalObject* receiver, + GlobalObject* receiver, JSGlobalPropertyCell* cell) { Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL); Object* code = receiver->map()->FindInCodeCache(name, flags); @@ -537,7 +537,7 @@ Object* StubCache::ComputeCallNormal(int argc, Object* StubCache::ComputeCallGlobal(int argc, InLoopFlag in_loop, String* name, - JSGlobalObject* receiver, + GlobalObject* receiver, JSGlobalPropertyCell* cell, JSFunction* function) { Code::Flags flags = diff --git a/src/stub-cache.h b/src/stub-cache.h index 577e04b..fff5613 100644 --- a/src/stub-cache.h +++ b/src/stub-cache.h @@ -79,7 +79,7 @@ class StubCache : public AllStatic { static Object* ComputeLoadGlobal(String* name, - JSGlobalObject* receiver, + GlobalObject* receiver, JSGlobalPropertyCell* cell, bool is_dont_delete); @@ -119,7 +119,7 @@ class StubCache : public AllStatic { Map* transition = NULL); static Object* ComputeStoreGlobal(String* name, - JSGlobalObject* receiver, + GlobalObject* receiver, JSGlobalPropertyCell* cell); static Object* ComputeStoreCallback(String* name, @@ -164,7 +164,7 @@ class StubCache : public AllStatic { static Object* ComputeCallGlobal(int argc, InLoopFlag in_loop, String* name, - JSGlobalObject* receiver, + GlobalObject* receiver, JSGlobalPropertyCell* cell, JSFunction* function); @@ -433,7 +433,7 @@ class LoadStubCompiler: public StubCompiler { JSObject* holder, String* name); - Object* CompileLoadGlobal(JSGlobalObject* object, + Object* CompileLoadGlobal(GlobalObject* object, JSGlobalPropertyCell* holder, String* name, bool is_dont_delete); @@ -479,7 +479,7 @@ class StoreStubCompiler: public StubCompiler { AccessorInfo* callbacks, String* name); Object* CompileStoreInterceptor(JSObject* object, String* name); - Object* CompileStoreGlobal(JSGlobalObject* object, + Object* CompileStoreGlobal(GlobalObject* object, JSGlobalPropertyCell* holder, String* name); @@ -517,7 +517,7 @@ class CallStubCompiler: public StubCompiler { Object* CompileCallInterceptor(Object* object, JSObject* holder, String* name); - Object* CompileCallGlobal(JSGlobalObject* object, + Object* CompileCallGlobal(GlobalObject* object, JSGlobalPropertyCell* cell, JSFunction* function, String* name); diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc index f2e0e19..1a24694 100644 --- a/src/x64/stub-cache-x64.cc +++ b/src/x64/stub-cache-x64.cc @@ -65,7 +65,7 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* a, -Object* CallStubCompiler::CompileCallGlobal(JSGlobalObject* object, +Object* CallStubCompiler::CompileCallGlobal(GlobalObject* object, JSGlobalPropertyCell* cell, JSFunction* function, String* name) { @@ -109,7 +109,7 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* a, } -Object* LoadStubCompiler::CompileLoadGlobal(JSGlobalObject* object, +Object* LoadStubCompiler::CompileLoadGlobal(GlobalObject* object, JSGlobalPropertyCell* cell, String* name, bool is_dont_delete) { @@ -141,7 +141,7 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* a, String* b) { } -Object* StoreStubCompiler::CompileStoreGlobal(JSGlobalObject* object, +Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, JSGlobalPropertyCell* cell, String* name) { UNIMPLEMENTED(); -- 2.7.4