Cache Object.create maps on the passed prototype's PrototypeInfo
BUG=chromium:603144 Review-Url: https://codereview.chromium.org/2083353002 Cr-Commit-Position: refs/heads/master@{#37214}
This commit is contained in:
parent
42ac51c82e
commit
059f2fa101
@ -2994,6 +2994,14 @@ bool Genesis::InstallNatives(GlobalContextType context_type) {
|
||||
native_context()->set_object_function_prototype_map(
|
||||
HeapObject::cast(object_function->initial_map()->prototype())->map());
|
||||
|
||||
// Set up the map for Object.create(null) instances.
|
||||
Handle<Map> object_with_null_prototype_map =
|
||||
Map::CopyInitialMap(handle(object_function->initial_map(), isolate()));
|
||||
Map::SetPrototype(object_with_null_prototype_map,
|
||||
isolate()->factory()->null_value());
|
||||
native_context()->set_object_with_null_prototype_map(
|
||||
*object_with_null_prototype_map);
|
||||
|
||||
// Store the map for the %StringPrototype% after the natives has been compiled
|
||||
// and the String function has been set up.
|
||||
Handle<JSFunction> string_function(native_context()->string_function());
|
||||
|
@ -1618,6 +1618,8 @@ BUILTIN(ObjectAssign) {
|
||||
|
||||
|
||||
// ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
|
||||
// TODO(verwaest): Support the common cases with precached map directly in
|
||||
// an Object.create stub.
|
||||
BUILTIN(ObjectCreate) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> prototype = args.atOrUndefined(isolate, 1);
|
||||
@ -1633,7 +1635,26 @@ BUILTIN(ObjectCreate) {
|
||||
Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
|
||||
isolate);
|
||||
if (map->prototype() != *prototype) {
|
||||
map = Map::TransitionToPrototype(map, prototype, FAST_PROTOTYPE);
|
||||
if (prototype->IsNull(isolate)) {
|
||||
map = isolate->object_with_null_prototype_map();
|
||||
} else if (prototype->IsJSObject()) {
|
||||
Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
|
||||
if (!js_prototype->map()->is_prototype_map()) {
|
||||
JSObject::OptimizeAsPrototype(js_prototype, FAST_PROTOTYPE);
|
||||
}
|
||||
Handle<PrototypeInfo> info =
|
||||
Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
|
||||
// TODO(verwaest): Use inobject slack tracking for this map.
|
||||
if (info->HasObjectCreateMap()) {
|
||||
map = handle(info->ObjectCreateMap(), isolate);
|
||||
} else {
|
||||
map = Map::CopyInitialMap(map);
|
||||
Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
|
||||
PrototypeInfo::SetObjectCreateMap(info, map);
|
||||
}
|
||||
} else {
|
||||
map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE);
|
||||
}
|
||||
}
|
||||
|
||||
// Actually allocate the object.
|
||||
|
@ -217,6 +217,7 @@ enum BindingFlags {
|
||||
V(NORMALIZED_MAP_CACHE_INDEX, Object, normalized_map_cache) \
|
||||
V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \
|
||||
V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \
|
||||
V(OBJECT_WITH_NULL_PROTOTYPE_MAP, Map, object_with_null_prototype_map) \
|
||||
V(OBJECT_FUNCTION_PROTOTYPE_MAP_INDEX, Map, object_function_prototype_map) \
|
||||
V(OPAQUE_REFERENCE_FUNCTION_INDEX, JSFunction, opaque_reference_function) \
|
||||
V(PROXY_CALLABLE_MAP_INDEX, Map, proxy_callable_map) \
|
||||
|
@ -5486,7 +5486,24 @@ ACCESSORS(AccessorInfo, data, Object, kDataOffset)
|
||||
|
||||
ACCESSORS(Box, value, Object, kValueOffset)
|
||||
|
||||
Map* PrototypeInfo::ObjectCreateMap() {
|
||||
return Map::cast(WeakCell::cast(object_create_map())->value());
|
||||
}
|
||||
|
||||
// static
|
||||
void PrototypeInfo::SetObjectCreateMap(Handle<PrototypeInfo> info,
|
||||
Handle<Map> map) {
|
||||
Handle<WeakCell> cell = Map::WeakCellForMap(map);
|
||||
info->set_object_create_map(*cell);
|
||||
}
|
||||
|
||||
bool PrototypeInfo::HasObjectCreateMap() {
|
||||
Object* cache = object_create_map();
|
||||
return cache->IsWeakCell() && !WeakCell::cast(cache)->cleared();
|
||||
}
|
||||
|
||||
ACCESSORS(PrototypeInfo, prototype_users, Object, kPrototypeUsersOffset)
|
||||
ACCESSORS(PrototypeInfo, object_create_map, Object, kObjectCreateMap)
|
||||
SMI_ACCESSORS(PrototypeInfo, registry_slot, kRegistrySlotOffset)
|
||||
ACCESSORS(PrototypeInfo, validity_cell, Object, kValidityCellOffset)
|
||||
SMI_ACCESSORS(PrototypeInfo, bit_field, kBitFieldOffset)
|
||||
|
@ -6304,6 +6304,13 @@ class PrototypeInfo : public Struct {
|
||||
// [prototype_users]: WeakFixedArray containing maps using this prototype,
|
||||
// or Smi(0) if uninitialized.
|
||||
DECL_ACCESSORS(prototype_users, Object)
|
||||
|
||||
// [object_create_map]: A field caching the map for Object.create(prototype).
|
||||
static inline void SetObjectCreateMap(Handle<PrototypeInfo> info,
|
||||
Handle<Map> map);
|
||||
inline Map* ObjectCreateMap();
|
||||
inline bool HasObjectCreateMap();
|
||||
|
||||
// [registry_slot]: Slot in prototype's user registry where this user
|
||||
// is stored. Returns UNREGISTERED if this prototype has not been registered.
|
||||
inline int registry_slot() const;
|
||||
@ -6330,13 +6337,16 @@ class PrototypeInfo : public Struct {
|
||||
static const int kPrototypeUsersOffset = HeapObject::kHeaderSize;
|
||||
static const int kRegistrySlotOffset = kPrototypeUsersOffset + kPointerSize;
|
||||
static const int kValidityCellOffset = kRegistrySlotOffset + kPointerSize;
|
||||
static const int kBitFieldOffset = kValidityCellOffset + kPointerSize;
|
||||
static const int kObjectCreateMap = kValidityCellOffset + kPointerSize;
|
||||
static const int kBitFieldOffset = kObjectCreateMap + kPointerSize;
|
||||
static const int kSize = kBitFieldOffset + kPointerSize;
|
||||
|
||||
// Bit field usage.
|
||||
static const int kShouldBeFastBit = 0;
|
||||
|
||||
private:
|
||||
DECL_ACCESSORS(object_create_map, Object)
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(PrototypeInfo);
|
||||
};
|
||||
|
||||
|
@ -80,7 +80,7 @@ bytecodes: [
|
||||
/* 15 S> */ B(LdrUndefined), R(0),
|
||||
B(CreateArrayLiteral), U8(0), U8(0), U8(3),
|
||||
B(Star), R(1),
|
||||
B(CallJSRuntime), U8(128), R(0), U8(2),
|
||||
B(CallJSRuntime), U8(129), R(0), U8(2),
|
||||
/* 44 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
|
Loading…
Reference in New Issue
Block a user