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(
|
native_context()->set_object_function_prototype_map(
|
||||||
HeapObject::cast(object_function->initial_map()->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
|
// Store the map for the %StringPrototype% after the natives has been compiled
|
||||||
// and the String function has been set up.
|
// and the String function has been set up.
|
||||||
Handle<JSFunction> string_function(native_context()->string_function());
|
Handle<JSFunction> string_function(native_context()->string_function());
|
||||||
|
@ -1618,6 +1618,8 @@ BUILTIN(ObjectAssign) {
|
|||||||
|
|
||||||
|
|
||||||
// ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
|
// 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) {
|
BUILTIN(ObjectCreate) {
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
Handle<Object> prototype = args.atOrUndefined(isolate, 1);
|
Handle<Object> prototype = args.atOrUndefined(isolate, 1);
|
||||||
@ -1633,7 +1635,26 @@ BUILTIN(ObjectCreate) {
|
|||||||
Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
|
Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
|
||||||
isolate);
|
isolate);
|
||||||
if (map->prototype() != *prototype) {
|
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.
|
// Actually allocate the object.
|
||||||
|
@ -217,6 +217,7 @@ enum BindingFlags {
|
|||||||
V(NORMALIZED_MAP_CACHE_INDEX, Object, normalized_map_cache) \
|
V(NORMALIZED_MAP_CACHE_INDEX, Object, normalized_map_cache) \
|
||||||
V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \
|
V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \
|
||||||
V(OBJECT_FUNCTION_INDEX, JSFunction, object_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(OBJECT_FUNCTION_PROTOTYPE_MAP_INDEX, Map, object_function_prototype_map) \
|
||||||
V(OPAQUE_REFERENCE_FUNCTION_INDEX, JSFunction, opaque_reference_function) \
|
V(OPAQUE_REFERENCE_FUNCTION_INDEX, JSFunction, opaque_reference_function) \
|
||||||
V(PROXY_CALLABLE_MAP_INDEX, Map, proxy_callable_map) \
|
V(PROXY_CALLABLE_MAP_INDEX, Map, proxy_callable_map) \
|
||||||
|
@ -5486,7 +5486,24 @@ ACCESSORS(AccessorInfo, data, Object, kDataOffset)
|
|||||||
|
|
||||||
ACCESSORS(Box, value, Object, kValueOffset)
|
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, prototype_users, Object, kPrototypeUsersOffset)
|
||||||
|
ACCESSORS(PrototypeInfo, object_create_map, Object, kObjectCreateMap)
|
||||||
SMI_ACCESSORS(PrototypeInfo, registry_slot, kRegistrySlotOffset)
|
SMI_ACCESSORS(PrototypeInfo, registry_slot, kRegistrySlotOffset)
|
||||||
ACCESSORS(PrototypeInfo, validity_cell, Object, kValidityCellOffset)
|
ACCESSORS(PrototypeInfo, validity_cell, Object, kValidityCellOffset)
|
||||||
SMI_ACCESSORS(PrototypeInfo, bit_field, kBitFieldOffset)
|
SMI_ACCESSORS(PrototypeInfo, bit_field, kBitFieldOffset)
|
||||||
|
@ -6304,6 +6304,13 @@ class PrototypeInfo : public Struct {
|
|||||||
// [prototype_users]: WeakFixedArray containing maps using this prototype,
|
// [prototype_users]: WeakFixedArray containing maps using this prototype,
|
||||||
// or Smi(0) if uninitialized.
|
// or Smi(0) if uninitialized.
|
||||||
DECL_ACCESSORS(prototype_users, Object)
|
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
|
// [registry_slot]: Slot in prototype's user registry where this user
|
||||||
// is stored. Returns UNREGISTERED if this prototype has not been registered.
|
// is stored. Returns UNREGISTERED if this prototype has not been registered.
|
||||||
inline int registry_slot() const;
|
inline int registry_slot() const;
|
||||||
@ -6330,13 +6337,16 @@ class PrototypeInfo : public Struct {
|
|||||||
static const int kPrototypeUsersOffset = HeapObject::kHeaderSize;
|
static const int kPrototypeUsersOffset = HeapObject::kHeaderSize;
|
||||||
static const int kRegistrySlotOffset = kPrototypeUsersOffset + kPointerSize;
|
static const int kRegistrySlotOffset = kPrototypeUsersOffset + kPointerSize;
|
||||||
static const int kValidityCellOffset = kRegistrySlotOffset + 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;
|
static const int kSize = kBitFieldOffset + kPointerSize;
|
||||||
|
|
||||||
// Bit field usage.
|
// Bit field usage.
|
||||||
static const int kShouldBeFastBit = 0;
|
static const int kShouldBeFastBit = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
DECL_ACCESSORS(object_create_map, Object)
|
||||||
|
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(PrototypeInfo);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(PrototypeInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ bytecodes: [
|
|||||||
/* 15 S> */ B(LdrUndefined), R(0),
|
/* 15 S> */ B(LdrUndefined), R(0),
|
||||||
B(CreateArrayLiteral), U8(0), U8(0), U8(3),
|
B(CreateArrayLiteral), U8(0), U8(0), U8(3),
|
||||||
B(Star), R(1),
|
B(Star), R(1),
|
||||||
B(CallJSRuntime), U8(128), R(0), U8(2),
|
B(CallJSRuntime), U8(129), R(0), U8(2),
|
||||||
/* 44 S> */ B(Return),
|
/* 44 S> */ B(Return),
|
||||||
]
|
]
|
||||||
constant pool: [
|
constant pool: [
|
||||||
|
Loading…
Reference in New Issue
Block a user