Commit c60ec4e1 authored by cbruni's avatar cbruni Committed by Commit bot

[compiler] Support Object.create(null) inlining in TF

In the ideal case, this will speed up Object.create(null) by ~10x.

Drive-by-fix: Spread usage of new IsSpecialReceiverMap() and
              IsSpecialReceiverInstanceType(InstanceType) helpers.

BUG=v8:5788

Review-Url: https://codereview.chromium.org/2622723003
Cr-Commit-Position: refs/heads/master@{#42336}
parent 936f79d9
...@@ -84,6 +84,15 @@ FieldAccess AccessBuilder::ForJSObjectInObjectProperty(Handle<Map> map, ...@@ -84,6 +84,15 @@ FieldAccess AccessBuilder::ForJSObjectInObjectProperty(Handle<Map> map,
return access; return access;
} }
// static
FieldAccess AccessBuilder::ForJSObjectOffset(
int offset, WriteBarrierKind write_barrier_kind) {
FieldAccess access = {kTaggedBase, offset,
MaybeHandle<Name>(), MaybeHandle<Map>(),
Type::NonInternal(), MachineType::AnyTagged(),
write_barrier_kind};
return access;
}
// static // static
FieldAccess AccessBuilder::ForJSFunctionPrototypeOrInitialMap() { FieldAccess AccessBuilder::ForJSFunctionPrototypeOrInitialMap() {
...@@ -688,12 +697,13 @@ FieldAccess AccessBuilder::ForArgumentsCallee() { ...@@ -688,12 +697,13 @@ FieldAccess AccessBuilder::ForArgumentsCallee() {
// static // static
FieldAccess AccessBuilder::ForFixedArraySlot(size_t index) { FieldAccess AccessBuilder::ForFixedArraySlot(
size_t index, WriteBarrierKind write_barrier_kind) {
int offset = FixedArray::OffsetOfElementAt(static_cast<int>(index)); int offset = FixedArray::OffsetOfElementAt(static_cast<int>(index));
FieldAccess access = {kTaggedBase, offset, FieldAccess access = {kTaggedBase, offset,
Handle<Name>(), MaybeHandle<Map>(), Handle<Name>(), MaybeHandle<Map>(),
Type::NonInternal(), MachineType::AnyTagged(), Type::NonInternal(), MachineType::AnyTagged(),
kFullWriteBarrier}; write_barrier_kind};
return access; return access;
} }
...@@ -843,6 +853,68 @@ ElementAccess AccessBuilder::ForTypedArrayElement(ExternalArrayType type, ...@@ -843,6 +853,68 @@ ElementAccess AccessBuilder::ForTypedArrayElement(ExternalArrayType type,
return access; return access;
} }
// static
FieldAccess AccessBuilder::ForHashTableBaseNumberOfElements() {
FieldAccess access = {
kTaggedBase,
FixedArray::OffsetOfElementAt(HashTableBase::kNumberOfElementsIndex),
MaybeHandle<Name>(),
MaybeHandle<Map>(),
Type::SignedSmall(),
MachineType::TaggedSigned(),
kNoWriteBarrier};
return access;
}
// static
FieldAccess AccessBuilder::ForHashTableBaseNumberOfDeletedElement() {
FieldAccess access = {
kTaggedBase, FixedArray::OffsetOfElementAt(
HashTableBase::kNumberOfDeletedElementsIndex),
MaybeHandle<Name>(), MaybeHandle<Map>(), Type::SignedSmall(),
MachineType::TaggedSigned(), kNoWriteBarrier};
return access;
}
// static
FieldAccess AccessBuilder::ForHashTableBaseCapacity() {
FieldAccess access = {
kTaggedBase,
FixedArray::OffsetOfElementAt(HashTableBase::kCapacityIndex),
MaybeHandle<Name>(),
MaybeHandle<Map>(),
Type::SignedSmall(),
MachineType::TaggedSigned(),
kNoWriteBarrier};
return access;
}
// static
FieldAccess AccessBuilder::ForDictionaryMaxNumberKey() {
FieldAccess access = {
kTaggedBase,
FixedArray::OffsetOfElementAt(NameDictionary::kMaxNumberKeyIndex),
MaybeHandle<Name>(),
MaybeHandle<Map>(),
Type::Any(),
MachineType::AnyTagged(),
kNoWriteBarrier};
return access;
}
// static
FieldAccess AccessBuilder::ForDictionaryNextEnumerationIndex() {
FieldAccess access = {
kTaggedBase,
FixedArray::OffsetOfElementAt(NameDictionary::kNextEnumerationIndexIndex),
MaybeHandle<Name>(),
MaybeHandle<Map>(),
Type::SignedSmall(),
MachineType::TaggedSigned(),
kNoWriteBarrier};
return access;
}
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -46,6 +46,8 @@ class V8_EXPORT_PRIVATE AccessBuilder final ...@@ -46,6 +46,8 @@ class V8_EXPORT_PRIVATE AccessBuilder final
// Provides access to JSObject inobject property fields. // Provides access to JSObject inobject property fields.
static FieldAccess ForJSObjectInObjectProperty(Handle<Map> map, int index); static FieldAccess ForJSObjectInObjectProperty(Handle<Map> map, int index);
static FieldAccess ForJSObjectOffset(
int offset, WriteBarrierKind write_barrier_kind = kFullWriteBarrier);
// Provides access to JSFunction::prototype_or_initial_map() field. // Provides access to JSFunction::prototype_or_initial_map() field.
static FieldAccess ForJSFunctionPrototypeOrInitialMap(); static FieldAccess ForJSFunctionPrototypeOrInitialMap();
...@@ -221,7 +223,8 @@ class V8_EXPORT_PRIVATE AccessBuilder final ...@@ -221,7 +223,8 @@ class V8_EXPORT_PRIVATE AccessBuilder final
static FieldAccess ForArgumentsCallee(); static FieldAccess ForArgumentsCallee();
// Provides access to FixedArray slots. // Provides access to FixedArray slots.
static FieldAccess ForFixedArraySlot(size_t index); static FieldAccess ForFixedArraySlot(
size_t index, WriteBarrierKind write_barrier_kind = kFullWriteBarrier);
// Provides access to Context slots. // Provides access to Context slots.
static FieldAccess ForContextSlot(size_t index); static FieldAccess ForContextSlot(size_t index);
...@@ -241,6 +244,15 @@ class V8_EXPORT_PRIVATE AccessBuilder final ...@@ -241,6 +244,15 @@ class V8_EXPORT_PRIVATE AccessBuilder final
static ElementAccess ForTypedArrayElement(ExternalArrayType type, static ElementAccess ForTypedArrayElement(ExternalArrayType type,
bool is_external); bool is_external);
// Provides access to HashTable fields.
static FieldAccess ForHashTableBaseNumberOfElements();
static FieldAccess ForHashTableBaseNumberOfDeletedElement();
static FieldAccess ForHashTableBaseCapacity();
// Provides access to Dictionary fields.
static FieldAccess ForDictionaryMaxNumberKey();
static FieldAccess ForDictionaryNextEnumerationIndex();
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(AccessBuilder); DISALLOW_IMPLICIT_CONSTRUCTORS(AccessBuilder);
}; };
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "src/compiler/js-builtin-reducer.h" #include "src/compiler/js-builtin-reducer.h"
#include "src/base/bits.h"
#include "src/compilation-dependencies.h" #include "src/compilation-dependencies.h"
#include "src/compiler/access-builder.h" #include "src/compiler/access-builder.h"
#include "src/compiler/js-graph.h" #include "src/compiler/js-graph.h"
...@@ -1485,6 +1486,117 @@ Reduction JSBuiltinReducer::ReduceNumberParseInt(Node* node) { ...@@ -1485,6 +1486,117 @@ Reduction JSBuiltinReducer::ReduceNumberParseInt(Node* node) {
return NoChange(); return NoChange();
} }
// ES6 section #sec-object.create Object.create(proto, properties)
Reduction JSBuiltinReducer::ReduceObjectCreate(Node* node) {
// We need exactly target, receiver and value parameters.
int arg_count = node->op()->ValueInputCount();
if (arg_count != 3) return NoChange();
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* prototype = NodeProperties::GetValueInput(node, 2);
Type* prototype_type = NodeProperties::GetType(prototype);
Handle<Map> instance_map;
if (!prototype_type->IsHeapConstant()) return NoChange();
Handle<HeapObject> prototype_const =
prototype_type->AsHeapConstant()->Value();
if (!prototype_const->IsNull(isolate()) && !prototype_const->IsJSReceiver()) {
return NoChange();
}
instance_map = Map::GetObjectCreateMap(prototype_const);
Node* properties = jsgraph()->EmptyFixedArrayConstant();
if (instance_map->is_dictionary_map()) {
// Allocated an empty NameDictionary as backing store for the properties.
Handle<Map> map(isolate()->heap()->hash_table_map(), isolate());
int capacity =
NameDictionary::ComputeCapacity(NameDictionary::kInitialCapacity);
DCHECK(base::bits::IsPowerOfTwo32(capacity));
int length = NameDictionary::EntryToIndex(capacity);
int size = NameDictionary::SizeFor(length);
effect = graph()->NewNode(
common()->BeginRegion(RegionObservability::kNotObservable), effect);
Node* value = effect =
graph()->NewNode(simplified()->Allocate(NOT_TENURED),
jsgraph()->Constant(size), effect, control);
effect =
graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
value, jsgraph()->HeapConstant(map), effect, control);
// Initialize FixedArray fields.
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForFixedArrayLength()), value,
jsgraph()->SmiConstant(length), effect, control);
// Initialize HashTable fields.
effect =
graph()->NewNode(simplified()->StoreField(
AccessBuilder::ForHashTableBaseNumberOfElements()),
value, jsgraph()->SmiConstant(0), effect, control);
effect = graph()->NewNode(
simplified()->StoreField(
AccessBuilder::ForHashTableBaseNumberOfDeletedElement()),
value, jsgraph()->SmiConstant(0), effect, control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForHashTableBaseCapacity()),
value, jsgraph()->SmiConstant(capacity), effect, control);
// Initialize Dictionary fields.
Node* undefined = jsgraph()->UndefinedConstant();
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForDictionaryMaxNumberKey()),
value, undefined, effect, control);
effect = graph()->NewNode(
simplified()->StoreField(
AccessBuilder::ForDictionaryNextEnumerationIndex()),
value, jsgraph()->SmiConstant(PropertyDetails::kInitialIndex), effect,
control);
// Initialize hte Properties fields.
for (int index = NameDictionary::kNextEnumerationIndexIndex + 1;
index < length; index++) {
effect = graph()->NewNode(
simplified()->StoreField(
AccessBuilder::ForFixedArraySlot(index, kNoWriteBarrier)),
value, undefined, effect, control);
}
properties = effect =
graph()->NewNode(common()->FinishRegion(), value, effect);
}
int const instance_size = instance_map->instance_size();
if (instance_size > kMaxRegularHeapObjectSize) return NoChange();
dependencies()->AssumeInitialMapCantChange(instance_map);
// Emit code to allocate the JSObject instance for the given
// {instance_map}.
effect = graph()->NewNode(
common()->BeginRegion(RegionObservability::kNotObservable), effect);
Node* value = effect =
graph()->NewNode(simplified()->Allocate(NOT_TENURED),
jsgraph()->Constant(instance_size), effect, control);
effect =
graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()), value,
jsgraph()->HeapConstant(instance_map), effect, control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value,
properties, effect, control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value,
jsgraph()->EmptyFixedArrayConstant(), effect, control);
// Initialize Object fields.
Node* undefined = jsgraph()->UndefinedConstant();
for (int offset = JSObject::kHeaderSize; offset < instance_size;
offset += kPointerSize) {
effect = graph()->NewNode(
simplified()->StoreField(
AccessBuilder::ForJSObjectOffset(offset, kNoWriteBarrier)),
value, undefined, effect, control);
}
value = effect = graph()->NewNode(common()->FinishRegion(), value, effect);
// replace it
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
// ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits ) // ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
Reduction JSBuiltinReducer::ReduceStringFromCharCode(Node* node) { Reduction JSBuiltinReducer::ReduceStringFromCharCode(Node* node) {
JSCallReduction r(node); JSCallReduction r(node);
...@@ -1990,6 +2102,9 @@ Reduction JSBuiltinReducer::Reduce(Node* node) { ...@@ -1990,6 +2102,9 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
case kNumberParseInt: case kNumberParseInt:
reduction = ReduceNumberParseInt(node); reduction = ReduceNumberParseInt(node);
break; break;
case kObjectCreate:
reduction = ReduceObjectCreate(node);
break;
case kStringFromCharCode: case kStringFromCharCode:
reduction = ReduceStringFromCharCode(node); reduction = ReduceStringFromCharCode(node);
break; break;
......
...@@ -99,6 +99,7 @@ class V8_EXPORT_PRIVATE JSBuiltinReducer final ...@@ -99,6 +99,7 @@ class V8_EXPORT_PRIVATE JSBuiltinReducer final
Reduction ReduceNumberIsNaN(Node* node); Reduction ReduceNumberIsNaN(Node* node);
Reduction ReduceNumberIsSafeInteger(Node* node); Reduction ReduceNumberIsSafeInteger(Node* node);
Reduction ReduceNumberParseInt(Node* node); Reduction ReduceNumberParseInt(Node* node);
Reduction ReduceObjectCreate(Node* node);
Reduction ReduceStringCharAt(Node* node); Reduction ReduceStringCharAt(Node* node);
Reduction ReduceStringCharCodeAt(Node* node); Reduction ReduceStringCharCodeAt(Node* node);
Reduction ReduceStringFromCharCode(Node* node); Reduction ReduceStringFromCharCode(Node* node);
......
...@@ -73,7 +73,7 @@ void LookupIterator::Next() { ...@@ -73,7 +73,7 @@ void LookupIterator::Next() {
JSReceiver* holder = *holder_; JSReceiver* holder = *holder_;
Map* map = holder->map(); Map* map = holder->map();
if (map->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) { if (map->IsSpecialReceiverMap()) {
state_ = IsElement() ? LookupInSpecialHolder<true>(map, holder) state_ = IsElement() ? LookupInSpecialHolder<true>(map, holder)
: LookupInSpecialHolder<false>(map, holder); : LookupInSpecialHolder<false>(map, holder);
if (IsFound()) return; if (IsFound()) return;
......
...@@ -288,7 +288,7 @@ class V8_EXPORT_PRIVATE LookupIterator final BASE_EMBEDDED { ...@@ -288,7 +288,7 @@ class V8_EXPORT_PRIVATE LookupIterator final BASE_EMBEDDED {
void NextInternal(Map* map, JSReceiver* holder); void NextInternal(Map* map, JSReceiver* holder);
template <bool is_element> template <bool is_element>
inline State LookupInHolder(Map* map, JSReceiver* holder) { inline State LookupInHolder(Map* map, JSReceiver* holder) {
return map->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE return map->IsSpecialReceiverMap()
? LookupInSpecialHolder<is_element>(map, holder) ? LookupInSpecialHolder<is_element>(map, holder)
: LookupInRegularHolder<is_element>(map, holder); : LookupInRegularHolder<is_element>(map, holder);
} }
......
...@@ -2219,6 +2219,9 @@ int JSObject::GetHeaderSize(InstanceType type) { ...@@ -2219,6 +2219,9 @@ int JSObject::GetHeaderSize(InstanceType type) {
} }
} }
inline bool IsSpecialReceiverInstanceType(InstanceType instance_type) {
return instance_type <= LAST_SPECIAL_RECEIVER_TYPE;
}
int JSObject::GetInternalFieldCount(Map* map) { int JSObject::GetInternalFieldCount(Map* map) {
int instance_size = map->instance_size(); int instance_size = map->instance_size();
...@@ -4919,6 +4922,12 @@ bool Map::IsJSGlobalObjectMap() { ...@@ -4919,6 +4922,12 @@ bool Map::IsJSGlobalObjectMap() {
bool Map::IsJSTypedArrayMap() { return instance_type() == JS_TYPED_ARRAY_TYPE; } bool Map::IsJSTypedArrayMap() { return instance_type() == JS_TYPED_ARRAY_TYPE; }
bool Map::IsJSDataViewMap() { return instance_type() == JS_DATA_VIEW_TYPE; } bool Map::IsJSDataViewMap() { return instance_type() == JS_DATA_VIEW_TYPE; }
bool Map::IsSpecialReceiverMap() {
bool result = IsSpecialReceiverInstanceType(instance_type());
DCHECK_IMPLIES(!result,
!has_named_interceptor() && !is_access_check_needed());
return result;
}
bool Map::CanOmitMapChecks() { bool Map::CanOmitMapChecks() {
return is_stable() && FLAG_omit_map_checks_for_leaf_maps; return is_stable() && FLAG_omit_map_checks_for_leaf_maps;
......
...@@ -4708,6 +4708,36 @@ void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { ...@@ -4708,6 +4708,36 @@ void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
map->UpdateDescriptors(*new_descriptors, layout_descriptor); map->UpdateDescriptors(*new_descriptors, layout_descriptor);
} }
// static
Handle<Map> Map::GetObjectCreateMap(Handle<HeapObject> prototype) {
Isolate* isolate = prototype->GetIsolate();
Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
isolate);
if (map->prototype() == *prototype) return map;
if (prototype->IsNull(isolate)) {
return isolate->slow_object_with_null_prototype_map();
}
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);
}
return map;
}
return Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE);
}
template <class T> template <class T>
static int AppendUniqueCallbacks(Handle<TemplateList> callbacks, static int AppendUniqueCallbacks(Handle<TemplateList> callbacks,
Handle<typename T::Array> array, Handle<typename T::Array> array,
...@@ -8210,8 +8240,8 @@ bool Map::OnlyHasSimpleProperties() { ...@@ -8210,8 +8240,8 @@ bool Map::OnlyHasSimpleProperties() {
// Wrapped string elements aren't explicitly stored in the elements backing // Wrapped string elements aren't explicitly stored in the elements backing
// store, but are loaded indirectly from the underlying string. // store, but are loaded indirectly from the underlying string.
return !IsStringWrapperElementsKind(elements_kind()) && return !IsStringWrapperElementsKind(elements_kind()) &&
instance_type() > LAST_SPECIAL_RECEIVER_TYPE && !IsSpecialReceiverMap() && !has_hidden_prototype() &&
!has_hidden_prototype() && !is_dictionary_map(); !is_dictionary_map();
} }
MUST_USE_RESULT Maybe<bool> FastGetOwnValuesOrEntries( MUST_USE_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
......
...@@ -6283,6 +6283,8 @@ class Map: public HeapObject { ...@@ -6283,6 +6283,8 @@ class Map: public HeapObject {
Code* LookupInCodeCache(Name* name, Code::Flags code); Code* LookupInCodeCache(Name* name, Code::Flags code);
static Handle<Map> GetObjectCreateMap(Handle<HeapObject> prototype);
// Computes a hash value for this map, to be used in HashTables and such. // Computes a hash value for this map, to be used in HashTables and such.
int Hash(); int Hash();
...@@ -6307,6 +6309,8 @@ class Map: public HeapObject { ...@@ -6307,6 +6309,8 @@ class Map: public HeapObject {
inline bool IsJSTypedArrayMap(); inline bool IsJSTypedArrayMap();
inline bool IsJSDataViewMap(); inline bool IsJSDataViewMap();
inline bool IsSpecialReceiverMap();
inline bool CanOmitMapChecks(); inline bool CanOmitMapChecks();
static void AddDependentCode(Handle<Map> map, static void AddDependentCode(Handle<Map> map,
...@@ -7090,7 +7094,8 @@ class Script: public Struct { ...@@ -7090,7 +7094,8 @@ class Script: public Struct {
V(Number, isSafeInteger, NumberIsSafeInteger) \ V(Number, isSafeInteger, NumberIsSafeInteger) \
V(Number, parseFloat, NumberParseFloat) \ V(Number, parseFloat, NumberParseFloat) \
V(Number, parseInt, NumberParseInt) \ V(Number, parseInt, NumberParseInt) \
V(Number.prototype, toString, NumberToString) V(Number.prototype, toString, NumberToString) \
V(Object, create, ObjectCreate)
#define ATOMIC_FUNCTIONS_WITH_ID_LIST(V) \ #define ATOMIC_FUNCTIONS_WITH_ID_LIST(V) \
V(Atomics, load, AtomicsLoad) \ V(Atomics, load, AtomicsLoad) \
......
...@@ -496,8 +496,7 @@ RUNTIME_FUNCTION(Runtime_ArrayIncludes_Slow) { ...@@ -496,8 +496,7 @@ RUNTIME_FUNCTION(Runtime_ArrayIncludes_Slow) {
// If the receiver is not a special receiver type, and the length is a valid // If the receiver is not a special receiver type, and the length is a valid
// element index, perform fast operation tailored to specific ElementsKinds. // element index, perform fast operation tailored to specific ElementsKinds.
if (object->map()->instance_type() > LAST_SPECIAL_RECEIVER_TYPE && if (!object->map()->IsSpecialReceiverMap() && len < kMaxUInt32 &&
len < kMaxUInt32 &&
JSObject::PrototypeHasNoElements(isolate, JSObject::cast(*object))) { JSObject::PrototypeHasNoElements(isolate, JSObject::cast(*object))) {
Handle<JSObject> obj = Handle<JSObject>::cast(object); Handle<JSObject> obj = Handle<JSObject>::cast(object);
ElementsAccessor* elements = obj->GetElementsAccessor(); ElementsAccessor* elements = obj->GetElementsAccessor();
...@@ -595,8 +594,7 @@ RUNTIME_FUNCTION(Runtime_ArrayIndexOf) { ...@@ -595,8 +594,7 @@ RUNTIME_FUNCTION(Runtime_ArrayIndexOf) {
// If the receiver is not a special receiver type, and the length is a valid // If the receiver is not a special receiver type, and the length is a valid
// element index, perform fast operation tailored to specific ElementsKinds. // element index, perform fast operation tailored to specific ElementsKinds.
if (object->map()->instance_type() > LAST_SPECIAL_RECEIVER_TYPE && if (!object->map()->IsSpecialReceiverMap() && len < kMaxUInt32 &&
len < kMaxUInt32 &&
JSObject::PrototypeHasNoElements(isolate, JSObject::cast(*object))) { JSObject::PrototypeHasNoElements(isolate, JSObject::cast(*object))) {
Handle<JSObject> obj = Handle<JSObject>::cast(object); Handle<JSObject> obj = Handle<JSObject>::cast(object);
ElementsAccessor* elements = obj->GetElementsAccessor(); ElementsAccessor* elements = obj->GetElementsAccessor();
......
...@@ -222,30 +222,8 @@ RUNTIME_FUNCTION(Runtime_ObjectCreate) { ...@@ -222,30 +222,8 @@ RUNTIME_FUNCTION(Runtime_ObjectCreate) {
// function's initial map from the current native context. // function's initial map from the current native context.
// TODO(bmeurer): Use a dedicated cache for Object.create; think about // TODO(bmeurer): Use a dedicated cache for Object.create; think about
// slack tracking for Object.create. // slack tracking for Object.create.
Handle<Map> map(isolate->native_context()->object_function()->initial_map(), Handle<Map> map =
isolate); Map::GetObjectCreateMap(Handle<HeapObject>::cast(prototype));
if (map->prototype() != *prototype) {
if (prototype->IsNull(isolate)) {
map = isolate->slow_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);
}
}
bool is_dictionary_map = map->is_dictionary_map(); bool is_dictionary_map = map->is_dictionary_map();
Handle<FixedArray> object_properties; Handle<FixedArray> object_properties;
......
...@@ -401,7 +401,7 @@ Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) { ...@@ -401,7 +401,7 @@ Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
// Eliminate callable and exotic objects, which should not be serialized. // Eliminate callable and exotic objects, which should not be serialized.
InstanceType instance_type = receiver->map()->instance_type(); InstanceType instance_type = receiver->map()->instance_type();
if (receiver->IsCallable() || (instance_type <= LAST_SPECIAL_RECEIVER_TYPE && if (receiver->IsCallable() || (IsSpecialReceiverInstanceType(instance_type) &&
instance_type != JS_SPECIAL_API_OBJECT_TYPE)) { instance_type != JS_SPECIAL_API_OBJECT_TYPE)) {
ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver);
return Nothing<bool>(); return Nothing<bool>();
......
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