[runtime] Prepopulate map cache with initial Object map
Use the map for both objects with 0 requested properties and the number of inobject properties it has (4 currently) to share maptrees. Change-Id: Ie4859d44bed39effff864d54e7d416b13898c7d9 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3035081 Commit-Queue: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Michael Lippautz <mlippautz@chromium.org> Cr-Commit-Position: refs/heads/master@{#75757}
This commit is contained in:
parent
84d5b027a7
commit
e5c2e17de0
@ -3323,41 +3323,27 @@ Handle<JSObject> Factory::NewArgumentsObject(Handle<JSFunction> callee,
|
||||
|
||||
Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<NativeContext> context,
|
||||
int number_of_properties) {
|
||||
if (number_of_properties == 0) {
|
||||
// Reuse the initial map of the Object function if the literal has no
|
||||
// predeclared properties.
|
||||
return handle(context->object_function().initial_map(), isolate());
|
||||
}
|
||||
|
||||
// Use initial slow object proto map for too many properties.
|
||||
const int kMapCacheSize = 128;
|
||||
if (number_of_properties > kMapCacheSize) {
|
||||
if (number_of_properties >= JSObject::kMapCacheSize) {
|
||||
return handle(context->slow_object_with_object_prototype_map(), isolate());
|
||||
}
|
||||
|
||||
int cache_index = number_of_properties - 1;
|
||||
Handle<Object> maybe_cache(context->map_cache(), isolate());
|
||||
if (maybe_cache->IsUndefined(isolate())) {
|
||||
// Allocate the new map cache for the native context.
|
||||
maybe_cache = NewWeakFixedArray(kMapCacheSize, AllocationType::kOld);
|
||||
context->set_map_cache(*maybe_cache);
|
||||
} else {
|
||||
// Check to see whether there is a matching element in the cache.
|
||||
Handle<WeakFixedArray> cache = Handle<WeakFixedArray>::cast(maybe_cache);
|
||||
MaybeObject result = cache->Get(cache_index);
|
||||
HeapObject heap_object;
|
||||
if (result->GetHeapObjectIfWeak(&heap_object)) {
|
||||
Map map = Map::cast(heap_object);
|
||||
DCHECK(!map.is_dictionary_map());
|
||||
return handle(map, isolate());
|
||||
}
|
||||
Handle<WeakFixedArray> cache(WeakFixedArray::cast(context->map_cache()),
|
||||
isolate());
|
||||
|
||||
// Check to see whether there is a matching element in the cache.
|
||||
MaybeObject result = cache->Get(number_of_properties);
|
||||
HeapObject heap_object;
|
||||
if (result->GetHeapObjectIfWeak(&heap_object)) {
|
||||
Map map = Map::cast(heap_object);
|
||||
DCHECK(!map.is_dictionary_map());
|
||||
return handle(map, isolate());
|
||||
}
|
||||
|
||||
// Create a new map and add it to the cache.
|
||||
Handle<WeakFixedArray> cache = Handle<WeakFixedArray>::cast(maybe_cache);
|
||||
Handle<Map> map = Map::Create(isolate(), number_of_properties);
|
||||
DCHECK(!map->is_dictionary_map());
|
||||
cache->Set(cache_index, HeapObjectReference::Weak(*map));
|
||||
cache->Set(number_of_properties, HeapObjectReference::Weak(*map));
|
||||
return map;
|
||||
}
|
||||
|
||||
|
@ -249,7 +249,7 @@ class Genesis {
|
||||
ElementsKind elements_kind,
|
||||
InstanceType type,
|
||||
int rab_gsab_initial_map_index);
|
||||
void InitializeNormalizedMapCaches();
|
||||
void InitializeMapCaches();
|
||||
|
||||
enum ExtensionTraversalState { UNVISITED, VISITED, INSTALLED };
|
||||
|
||||
@ -5009,9 +5009,23 @@ bool Genesis::InstallExtrasBindings() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Genesis::InitializeNormalizedMapCaches() {
|
||||
Handle<NormalizedMapCache> cache = NormalizedMapCache::New(isolate());
|
||||
native_context()->set_normalized_map_cache(*cache);
|
||||
void Genesis::InitializeMapCaches() {
|
||||
{
|
||||
Handle<NormalizedMapCache> cache = NormalizedMapCache::New(isolate());
|
||||
native_context()->set_normalized_map_cache(*cache);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<WeakFixedArray> cache = factory()->NewWeakFixedArray(
|
||||
JSObject::kMapCacheSize, AllocationType::kOld);
|
||||
|
||||
DisallowGarbageCollection no_gc;
|
||||
native_context()->set_map_cache(*cache);
|
||||
Map initial = native_context()->object_function().initial_map();
|
||||
cache->Set(0, HeapObjectReference::Weak(initial), SKIP_WRITE_BARRIER);
|
||||
cache->Set(initial.GetInObjectProperties(),
|
||||
HeapObjectReference::Weak(initial), SKIP_WRITE_BARRIER);
|
||||
}
|
||||
}
|
||||
|
||||
bool Bootstrapper::InstallExtensions(Handle<Context> native_context,
|
||||
@ -5489,8 +5503,8 @@ Genesis::Genesis(
|
||||
CreateAsyncFunctionMaps(empty_function);
|
||||
Handle<JSGlobalObject> global_object =
|
||||
CreateNewGlobals(global_proxy_template, global_proxy);
|
||||
InitializeMapCaches();
|
||||
InitializeGlobal(global_object, empty_function);
|
||||
InitializeNormalizedMapCaches();
|
||||
InitializeIteratorFunctions();
|
||||
InitializeCallSiteBuiltins();
|
||||
|
||||
|
@ -793,6 +793,8 @@ class JSObject : public TorqueGeneratedJSObject<JSObject, JSReceiver> {
|
||||
|
||||
static const int kMaxInstanceSize = 255 * kTaggedSize;
|
||||
|
||||
static const int kMapCacheSize = 128;
|
||||
|
||||
// When extending the backing storage for property values, we increase
|
||||
// its size by more than the 1 entry necessary, so sequentially adding fields
|
||||
// to the same object requires fewer allocations and copies.
|
||||
|
Loading…
Reference in New Issue
Block a user