Revert of [compiler] Support Object.create(null) inlining in TF (patchset #5 id:80001 of https://codereview.chromium.org/2622723003/ )
Reason for revert:
Breaks buildbot: https://build.chromium.org/p/client.v8/builders/V8%20Linux64%20-%20avx2/builds/13399/steps/Benchmarks/logs/stdio
Original issue's description:
> [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@{#42321}
> Committed: ff7063c7d5
TBR=jarin@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:5788
Review-Url: https://codereview.chromium.org/2636493003
Cr-Commit-Position: refs/heads/master@{#42326}
This commit is contained in:
parent
9eb8714262
commit
83d5b65ae0
@ -843,68 +843,6 @@ ElementAccess AccessBuilder::ForTypedArrayElement(ExternalArrayType type,
|
||||
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::ForNextEnumerationIndex() {
|
||||
FieldAccess access = {
|
||||
kTaggedBase,
|
||||
FixedArray::OffsetOfElementAt(NameDictionary::kNextEnumerationIndexIndex),
|
||||
MaybeHandle<Name>(),
|
||||
MaybeHandle<Map>(),
|
||||
Type::SignedSmall(),
|
||||
MachineType::TaggedSigned(),
|
||||
kNoWriteBarrier};
|
||||
return access;
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -241,15 +241,6 @@ class V8_EXPORT_PRIVATE AccessBuilder final
|
||||
static ElementAccess ForTypedArrayElement(ExternalArrayType type,
|
||||
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 ForNextEnumerationIndex();
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(AccessBuilder);
|
||||
};
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include "src/compiler/js-builtin-reducer.h"
|
||||
|
||||
#include "src/base/bits.h"
|
||||
#include "src/compilation-dependencies.h"
|
||||
#include "src/compiler/access-builder.h"
|
||||
#include "src/compiler/js-graph.h"
|
||||
@ -1486,99 +1485,6 @@ Reduction JSBuiltinReducer::ReduceNumberParseInt(Node* node) {
|
||||
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.
|
||||
effect = graph()->NewNode(
|
||||
simplified()->StoreField(AccessBuilder::ForDictionaryMaxNumberKey()),
|
||||
value, jsgraph()->UndefinedConstant(), effect, control);
|
||||
effect = graph()->NewNode(
|
||||
simplified()->StoreField(AccessBuilder::ForNextEnumerationIndex()),
|
||||
value, jsgraph()->SmiConstant(PropertyDetails::kInitialIndex), effect,
|
||||
control);
|
||||
|
||||
properties = effect =
|
||||
graph()->NewNode(common()->FinishRegion(), value, effect);
|
||||
}
|
||||
|
||||
int const instance_size = instance_map->instance_size();
|
||||
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);
|
||||
|
||||
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 )
|
||||
Reduction JSBuiltinReducer::ReduceStringFromCharCode(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
@ -2084,9 +1990,6 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
|
||||
case kNumberParseInt:
|
||||
reduction = ReduceNumberParseInt(node);
|
||||
break;
|
||||
case kObjectCreate:
|
||||
reduction = ReduceObjectCreate(node);
|
||||
break;
|
||||
case kStringFromCharCode:
|
||||
reduction = ReduceStringFromCharCode(node);
|
||||
break;
|
||||
|
@ -99,7 +99,6 @@ class V8_EXPORT_PRIVATE JSBuiltinReducer final
|
||||
Reduction ReduceNumberIsNaN(Node* node);
|
||||
Reduction ReduceNumberIsSafeInteger(Node* node);
|
||||
Reduction ReduceNumberParseInt(Node* node);
|
||||
Reduction ReduceObjectCreate(Node* node);
|
||||
Reduction ReduceStringCharAt(Node* node);
|
||||
Reduction ReduceStringCharCodeAt(Node* node);
|
||||
Reduction ReduceStringFromCharCode(Node* node);
|
||||
|
@ -73,7 +73,7 @@ void LookupIterator::Next() {
|
||||
JSReceiver* holder = *holder_;
|
||||
Map* map = holder->map();
|
||||
|
||||
if (map->IsSpecialReceiverMap()) {
|
||||
if (map->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) {
|
||||
state_ = IsElement() ? LookupInSpecialHolder<true>(map, holder)
|
||||
: LookupInSpecialHolder<false>(map, holder);
|
||||
if (IsFound()) return;
|
||||
|
@ -288,7 +288,7 @@ class V8_EXPORT_PRIVATE LookupIterator final BASE_EMBEDDED {
|
||||
void NextInternal(Map* map, JSReceiver* holder);
|
||||
template <bool is_element>
|
||||
inline State LookupInHolder(Map* map, JSReceiver* holder) {
|
||||
return map->IsSpecialReceiverMap()
|
||||
return map->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE
|
||||
? LookupInSpecialHolder<is_element>(map, holder)
|
||||
: LookupInRegularHolder<is_element>(map, holder);
|
||||
}
|
||||
|
@ -2219,9 +2219,6 @@ int JSObject::GetHeaderSize(InstanceType type) {
|
||||
}
|
||||
}
|
||||
|
||||
inline bool IsSpecialReceiverInstanceType(InstanceType instance_type) {
|
||||
return instance_type <= LAST_SPECIAL_RECEIVER_TYPE;
|
||||
}
|
||||
|
||||
int JSObject::GetInternalFieldCount(Map* map) {
|
||||
int instance_size = map->instance_size();
|
||||
@ -4949,12 +4946,6 @@ bool Map::IsJSGlobalObjectMap() {
|
||||
bool Map::IsJSTypedArrayMap() { return instance_type() == JS_TYPED_ARRAY_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() {
|
||||
return is_stable() && FLAG_omit_map_checks_for_leaf_maps;
|
||||
|
@ -4724,36 +4724,6 @@ void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
|
||||
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>
|
||||
static int AppendUniqueCallbacks(Handle<TemplateList> callbacks,
|
||||
Handle<typename T::Array> array,
|
||||
@ -8256,8 +8226,8 @@ bool Map::OnlyHasSimpleProperties() {
|
||||
// Wrapped string elements aren't explicitly stored in the elements backing
|
||||
// store, but are loaded indirectly from the underlying string.
|
||||
return !IsStringWrapperElementsKind(elements_kind()) &&
|
||||
!IsSpecialReceiverMap() && !has_hidden_prototype() &&
|
||||
!is_dictionary_map();
|
||||
instance_type() > LAST_SPECIAL_RECEIVER_TYPE &&
|
||||
!has_hidden_prototype() && !is_dictionary_map();
|
||||
}
|
||||
|
||||
MUST_USE_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
|
||||
|
@ -6287,8 +6287,6 @@ class Map: public HeapObject {
|
||||
|
||||
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.
|
||||
int Hash();
|
||||
|
||||
@ -6313,8 +6311,6 @@ class Map: public HeapObject {
|
||||
inline bool IsJSTypedArrayMap();
|
||||
inline bool IsJSDataViewMap();
|
||||
|
||||
inline bool IsSpecialReceiverMap();
|
||||
|
||||
inline bool CanOmitMapChecks();
|
||||
|
||||
static void AddDependentCode(Handle<Map> map,
|
||||
@ -7098,8 +7094,7 @@ class Script: public Struct {
|
||||
V(Number, isSafeInteger, NumberIsSafeInteger) \
|
||||
V(Number, parseFloat, NumberParseFloat) \
|
||||
V(Number, parseInt, NumberParseInt) \
|
||||
V(Number.prototype, toString, NumberToString) \
|
||||
V(Object, create, ObjectCreate)
|
||||
V(Number.prototype, toString, NumberToString)
|
||||
|
||||
#define ATOMIC_FUNCTIONS_WITH_ID_LIST(V) \
|
||||
V(Atomics, load, AtomicsLoad) \
|
||||
|
@ -496,7 +496,8 @@ RUNTIME_FUNCTION(Runtime_ArrayIncludes_Slow) {
|
||||
|
||||
// If the receiver is not a special receiver type, and the length is a valid
|
||||
// element index, perform fast operation tailored to specific ElementsKinds.
|
||||
if (!object->map()->IsSpecialReceiverMap() && len < kMaxUInt32 &&
|
||||
if (object->map()->instance_type() > LAST_SPECIAL_RECEIVER_TYPE &&
|
||||
len < kMaxUInt32 &&
|
||||
JSObject::PrototypeHasNoElements(isolate, JSObject::cast(*object))) {
|
||||
Handle<JSObject> obj = Handle<JSObject>::cast(object);
|
||||
ElementsAccessor* elements = obj->GetElementsAccessor();
|
||||
@ -594,7 +595,8 @@ RUNTIME_FUNCTION(Runtime_ArrayIndexOf) {
|
||||
|
||||
// If the receiver is not a special receiver type, and the length is a valid
|
||||
// element index, perform fast operation tailored to specific ElementsKinds.
|
||||
if (!object->map()->IsSpecialReceiverMap() && len < kMaxUInt32 &&
|
||||
if (object->map()->instance_type() > LAST_SPECIAL_RECEIVER_TYPE &&
|
||||
len < kMaxUInt32 &&
|
||||
JSObject::PrototypeHasNoElements(isolate, JSObject::cast(*object))) {
|
||||
Handle<JSObject> obj = Handle<JSObject>::cast(object);
|
||||
ElementsAccessor* elements = obj->GetElementsAccessor();
|
||||
|
@ -222,8 +222,30 @@ RUNTIME_FUNCTION(Runtime_ObjectCreate) {
|
||||
// function's initial map from the current native context.
|
||||
// TODO(bmeurer): Use a dedicated cache for Object.create; think about
|
||||
// slack tracking for Object.create.
|
||||
Handle<Map> map =
|
||||
Map::GetObjectCreateMap(Handle<HeapObject>::cast(prototype));
|
||||
Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
|
||||
isolate);
|
||||
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();
|
||||
Handle<FixedArray> object_properties;
|
||||
|
@ -401,7 +401,7 @@ Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
|
||||
|
||||
// Eliminate callable and exotic objects, which should not be serialized.
|
||||
InstanceType instance_type = receiver->map()->instance_type();
|
||||
if (receiver->IsCallable() || (IsSpecialReceiverInstanceType(instance_type) &&
|
||||
if (receiver->IsCallable() || (instance_type <= LAST_SPECIAL_RECEIVER_TYPE &&
|
||||
instance_type != JS_SPECIAL_API_OBJECT_TYPE)) {
|
||||
ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver);
|
||||
return Nothing<bool>();
|
||||
|
Loading…
Reference in New Issue
Block a user