Commit 65bea197 authored by rossberg's avatar rossberg Committed by Commit bot

[strong] cache strong object literal maps

Also, add more literal tests.

R=dslomov@chromium.org
BUG=v8:3956
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#28579}
parent e13a39dd
......@@ -6746,7 +6746,7 @@ class Internals {
static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
static const int kContextHeaderSize = 2 * kApiPointerSize;
static const int kContextEmbedderDataIndex = 78;
static const int kContextEmbedderDataIndex = 79;
static const int kFullStringRepresentationMask = 0x07;
static const int kStringEncodingMask = 0x4;
static const int kExternalTwoByteRepresentationTag = 0x02;
......
......@@ -531,6 +531,12 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
native_context()->set_initial_array_prototype(*object_function_prototype);
Accessors::FunctionSetPrototype(object_fun, object_function_prototype)
.Assert();
// Allocate initial strong object map.
Handle<Map> strong_object_map =
Map::Copy(object_function_map, "EmptyStrongObject");
strong_object_map->set_is_strong();
native_context()->set_js_object_strong_map(*strong_object_map);
}
// Allocate the empty function as the prototype for function - ES6 19.2.3
......@@ -706,7 +712,7 @@ Handle<Map> Genesis::CreateStrongFunctionMap(
map->set_function_with_prototype(is_constructor);
Map::SetPrototype(map, empty_function);
map->set_is_extensible(is_constructor);
map->set_is_strong(true);
map->set_is_strong();
return map;
}
......@@ -1020,7 +1026,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
Handle<Map> initial_strong_map =
Map::Copy(initial_map, "SetInstancePrototype");
initial_strong_map->set_is_strong(true);
initial_strong_map->set_is_strong();
CacheInitialJSArrayMaps(native_context(), initial_strong_map);
}
......
......@@ -82,6 +82,7 @@ enum BindingFlags {
V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map) \
V(SYMBOL_FUNCTION_INDEX, JSFunction, symbol_function) \
V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \
V(JS_OBJECT_STRONG_MAP_INDEX, Map, js_object_strong_map) \
V(INTERNAL_ARRAY_FUNCTION_INDEX, JSFunction, internal_array_function) \
V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \
V(JS_ARRAY_MAPS_INDEX, Object, js_array_maps) \
......@@ -153,6 +154,7 @@ enum BindingFlags {
V(OPAQUE_REFERENCE_FUNCTION_INDEX, JSFunction, opaque_reference_function) \
V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \
V(MAP_CACHE_INDEX, Object, map_cache) \
V(STRONG_MAP_CACHE_INDEX, Object, strong_map_cache) \
V(EMBEDDER_DATA_INDEX, FixedArray, embedder_data) \
V(ALLOW_CODE_GEN_FROM_STRINGS_INDEX, Object, allow_code_gen_from_strings) \
V(ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX, Object, \
......@@ -340,6 +342,7 @@ class Context: public FixedArray {
STRING_FUNCTION_PROTOTYPE_MAP_INDEX,
SYMBOL_FUNCTION_INDEX,
OBJECT_FUNCTION_INDEX,
JS_OBJECT_STRONG_MAP_INDEX,
INTERNAL_ARRAY_FUNCTION_INDEX,
ARRAY_FUNCTION_INDEX,
JS_ARRAY_MAPS_INDEX,
......@@ -427,6 +430,7 @@ class Context: public FixedArray {
ARRAY_VALUES_ITERATOR_INDEX,
SCRIPT_CONTEXT_TABLE_INDEX,
MAP_CACHE_INDEX,
STRONG_MAP_CACHE_INDEX,
TO_LENGTH_FUN_INDEX,
NATIVES_UTILS_OBJECT_INDEX,
EXTRAS_EXPORTS_OBJECT_INDEX,
......
......@@ -2344,28 +2344,44 @@ Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> context,
const int kMapCacheSize = 128;
// We do not cache maps for too many properties or when running builtin code.
// TODO(rossberg): cache strong maps properly
if (number_of_properties > kMapCacheSize || is_strong ||
if (number_of_properties > kMapCacheSize ||
isolate()->bootstrapper()->IsActive()) {
*is_result_from_cache = false;
Handle<Map> map = Map::Create(isolate(), number_of_properties);
if (is_strong) map->set_is_strong(true);
if (is_strong) map->set_is_strong();
return map;
}
*is_result_from_cache = true;
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());
// predeclared properties, or the strong map if strong.
return handle(is_strong
? context->js_object_strong_map()
: context->object_function()->initial_map(), isolate());
}
// Create a new map and add it to the cache.
Handle<Map> map = Map::Create(isolate(), number_of_properties);
int cache_index = number_of_properties - 1;
if (context->map_cache()->IsUndefined()) {
// Allocate the new map cache for the native context.
Handle<FixedArray> new_cache = NewFixedArray(kMapCacheSize, TENURED);
context->set_map_cache(*new_cache);
Handle<FixedArray> cache;
if (is_strong) {
map->set_is_strong();
if (context->strong_map_cache()->IsUndefined()) {
// Allocate the new map cache for the native context.
Handle<FixedArray> new_cache = NewFixedArray(kMapCacheSize, TENURED);
context->set_strong_map_cache(*new_cache);
}
// Check to see whether there is a matching element in the cache.
cache = handle(FixedArray::cast(context->strong_map_cache()));
} else {
if (context->map_cache()->IsUndefined()) {
// Allocate the new map cache for the native context.
Handle<FixedArray> new_cache = NewFixedArray(kMapCacheSize, TENURED);
context->set_map_cache(*new_cache);
}
// Check to see whether there is a matching element in the cache.
cache = handle(FixedArray::cast(context->map_cache()));
}
// Check to see whether there is a matching element in the cache.
Handle<FixedArray> cache(FixedArray::cast(context->map_cache()));
{
Object* result = cache->get(cache_index);
if (result->IsWeakCell()) {
......@@ -2375,8 +2391,6 @@ Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> context,
}
}
}
// Create a new map and add it to the cache.
Handle<Map> map = Map::Create(isolate(), number_of_properties);
Handle<WeakCell> cell = NewWeakCell(map);
cache->set(cache_index, *cell);
return map;
......
......@@ -4730,8 +4730,8 @@ bool Map::is_migration_target() {
}
void Map::set_is_strong(bool value) {
set_bit_field3(IsStrong::update(bit_field3(), value));
void Map::set_is_strong() {
set_bit_field3(IsStrong::update(bit_field3(), true));
}
......
......@@ -9749,6 +9749,7 @@ static bool CheckEquivalent(Map* first, Map* second) {
first->instance_type() == second->instance_type() &&
first->bit_field() == second->bit_field() &&
first->is_extensible() == second->is_extensible() &&
first->is_strong() == second->is_strong() &&
first->has_instance_call_handler() ==
second->has_instance_call_handler();
}
......@@ -10386,7 +10387,7 @@ void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
CacheInitialJSArrayMaps(native_context, new_map);
Handle<Map> new_strong_map =
Map::Copy(initial_map, "SetInstancePrototype");
new_strong_map->set_is_strong(true);
new_strong_map->set_is_strong();
CacheInitialJSArrayMaps(native_context, new_strong_map);
}
}
......
......@@ -6013,7 +6013,7 @@ class Map: public HeapObject {
return ((1 << kIsObserved) & bit_field()) != 0;
}
inline void set_is_strong(bool value);
inline void set_is_strong();
inline bool is_strong();
inline void set_is_extensible(bool value);
inline bool is_extensible();
......
......@@ -48,13 +48,13 @@ MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
// slow properties mode for now. We don't go in the map cache because
// maps with constant functions can't be shared if the functions are
// not the same (which is the common case).
// TODO(rossberg): handle strong objects with function literals
bool is_result_from_cache = false;
Handle<Map> map = has_function_literal
? Handle<Map>(context->object_function()->initial_map())
: ComputeObjectLiteralMap(context, constant_properties,
is_strong,
&is_result_from_cache);
? Handle<Map>(is_strong
? context->js_object_strong_map()
: context->object_function()->initial_map())
: ComputeObjectLiteralMap(context, constant_properties, is_strong,
&is_result_from_cache);
PretenureFlag pretenure_flag =
isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED;
......
This diff is collapsed.
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