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:
cbruni 2017-01-13 04:56:03 -08:00 committed by Commit bot
parent 9eb8714262
commit 83d5b65ae0
12 changed files with 34 additions and 223 deletions

View File

@ -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

View File

@ -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);
};

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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(

View File

@ -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) \

View File

@ -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();

View File

@ -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;

View File

@ -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>();