Revert "[runtime] Store hash code in length field"

This reverts commit decf5750c6.

Reason for revert: broken layout tests

Original change's description:
> [runtime] Store hash code in length field
> 
> Store the hash code in 21 bits of the length field.
> 
> Change the GetIdentityHash API to be unhandlified, since there's no
> property lookup anymore.
> 
> Update js/ and test/ to match new API and expections.
> 
> Bug: 
> Change-Id: I8dc75de4021f59e79b45f3f38ec997c3b3687b24
> Reviewed-on: https://chromium-review.googlesource.com/589688
> Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#47259}

TBR=ulan@chromium.org,jkummerow@chromium.org,mstarzinger@chromium.org,cbruni@chromium.org,gsathya@chromium.org

Change-Id: I32db9c20a51b2401464924cafea502628a0d0b92
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/609322
Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org>
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47260}
This commit is contained in:
Sathya Gunasekaran 2017-08-09 22:04:09 +00:00 committed by Commit Bot
parent decf5750c6
commit 35f149e1d8
27 changed files with 226 additions and 363 deletions

View File

@ -623,14 +623,14 @@ Node* ConstructorBuiltinsAssembler::EmitFastCloneShallowObject(
{
Comment("Copy dictionary properties");
var_properties.Bind(
CopyNameDictionary(LoadSlowProperties(boilerplate), call_runtime));
CopyNameDictionary(LoadProperties(boilerplate), call_runtime));
// Slow objects have no in-object properties.
Goto(&done);
}
BIND(&if_fast);
{
// TODO(cbruni): support copying out-of-object properties.
Node* boilerplate_properties = LoadFastProperties(boilerplate);
Node* boilerplate_properties = LoadProperties(boilerplate);
GotoIfNot(IsEmptyFixedArray(boilerplate_properties), call_runtime);
var_properties.Bind(EmptyFixedArrayConstant());
Goto(&done);

View File

@ -148,7 +148,7 @@ void ForInBuiltinsAssembler::CheckEnumCache(Node* receiver, Label* use_cache,
{
// Avoid runtime-call for empty dictionary receivers.
GotoIfNot(IsDictionaryMap(map), use_runtime);
Node* properties = LoadSlowProperties(receiver);
Node* properties = LoadProperties(receiver);
Node* length = LoadFixedArrayElement(
properties, NameDictionary::kNumberOfElementsIndex);
GotoIfNot(WordEqual(length, SmiConstant(0)), use_runtime);

View File

@ -460,7 +460,7 @@ TF_BUILTIN(DeleteProperty, DeletePropertyBaseAssembler) {
BIND(&dictionary);
{
Node* properties = LoadSlowProperties(receiver);
Node* properties = LoadProperties(receiver);
DeleteDictionaryProperty(receiver, properties, unique, context,
&dont_delete, &if_notfound);
}

View File

@ -78,7 +78,7 @@ class ProxiesCodeStubAssembler : public CodeStubAssembler {
Node* proxy = Allocate(JSProxy::kSize);
StoreMapNoWriteBarrier(proxy, map.value());
StoreObjectFieldRoot(proxy, JSProxy::kPropertiesOrHashOffset,
Heap::kEmptyPropertyDictionaryRootIndex);
Heap::kEmptyPropertiesDictionaryRootIndex);
StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kTargetOffset, target);
StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kHandlerOffset, handler);
StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kHashOffset,

View File

@ -1152,18 +1152,9 @@ Node* CodeStubAssembler::TaggedDoesntHaveInstanceType(Node* any_tagged,
MachineRepresentation::kBit);
}
TNode<HeapObject> CodeStubAssembler::LoadFastProperties(
TNode<HeapObject> CodeStubAssembler::LoadProperties(
SloppyTNode<JSObject> object) {
Node* properties = LoadObjectField(object, JSObject::kPropertiesOrHashOffset);
return SelectTaggedConstant<HeapObject>(
TaggedIsSmi(properties), EmptyFixedArrayConstant(), properties);
}
TNode<HeapObject> CodeStubAssembler::LoadSlowProperties(
SloppyTNode<JSObject> object) {
Node* properties = LoadObjectField(object, JSObject::kPropertiesOrHashOffset);
return SelectTaggedConstant<HeapObject>(
TaggedIsSmi(properties), EmptyPropertyDictionaryConstant(), properties);
return CAST(LoadObjectField(object, JSObject::kPropertiesOrHashOffset));
}
TNode<FixedArrayBase> CodeStubAssembler::LoadElements(
@ -2257,9 +2248,6 @@ Node* CodeStubAssembler::AllocateNameDictionaryWithCapacity(Node* capacity) {
StoreFixedArrayElement(result, NameDictionary::kNextEnumerationIndexIndex,
SmiConstant(PropertyDetails::kInitialIndex),
SKIP_WRITE_BARRIER);
StoreFixedArrayElement(result, NameDictionary::kObjectHashIndex,
SmiConstant(PropertyArray::kNoHashSentinel),
SKIP_WRITE_BARRIER);
// Initialize NameDictionary elements.
Node* result_word = BitcastTaggedToWord(result);
@ -2500,6 +2488,18 @@ void CodeStubAssembler::InitializePropertyArrayLength(Node* property_array,
MachineRepresentation::kTaggedSigned);
}
Node* CodeStubAssembler::LoadPropertyArrayLength(Node* property_array) {
// TODO(gsathya): Remove the IsEmptyFixedArray check once we have
// proper handling for the Smi case.
CSA_SLOW_ASSERT(this, Word32Or(IsEmptyFixedArray(property_array),
IsPropertyArray(property_array)));
Node* const value =
LoadObjectField(property_array, PropertyArray::kLengthOffset,
MachineType::TaggedSigned());
Node* const length = SmiAnd(value, SmiConstant(PropertyArray::kLengthMask));
return length;
}
Node* CodeStubAssembler::AllocatePropertyArray(Node* capacity_node,
ParameterMode mode,
AllocationFlags flags) {
@ -5733,7 +5733,7 @@ void CodeStubAssembler::TryLookupProperty(
}
BIND(&if_isslowmap);
{
Node* dictionary = LoadSlowProperties(object);
Node* dictionary = LoadProperties(object);
var_meta_storage->Bind(dictionary);
NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found_dict,
@ -5750,7 +5750,7 @@ void CodeStubAssembler::TryLookupProperty(
int mask = 1 << Map::kHasNamedInterceptor | 1 << Map::kIsAccessCheckNeeded;
GotoIf(IsSetWord32(bit_field, mask), if_bailout);
Node* dictionary = LoadSlowProperties(object);
Node* dictionary = LoadProperties(object);
var_meta_storage->Bind(dictionary);
NameDictionaryLookup<GlobalDictionary>(
@ -5857,7 +5857,7 @@ void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map,
BIND(&if_backing_store);
{
Comment("if_backing_store");
Node* properties = LoadFastProperties(object);
Node* properties = LoadProperties(object);
field_index = IntPtrSub(field_index, inobject_properties);
Node* value = LoadFixedArrayElement(properties, field_index);

View File

@ -28,8 +28,6 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
V(AllocationSiteMap, allocation_site_map, AllocationSiteMap) \
V(BooleanMap, boolean_map, BooleanMap) \
V(CodeMap, code_map, CodeMap) \
V(EmptyPropertyDictionary, empty_property_dictionary, \
EmptyPropertyDictionary) \
V(EmptyFixedArray, empty_fixed_array, EmptyFixedArray) \
V(empty_string, empty_string, EmptyString) \
V(EmptyWeakCell, empty_weak_cell, EmptyWeakCell) \
@ -444,8 +442,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* DoesntHaveInstanceType(Node* object, InstanceType type);
Node* TaggedDoesntHaveInstanceType(Node* any_tagged, InstanceType type);
// Load the properties backing store of a JSObject.
TNode<HeapObject> LoadSlowProperties(SloppyTNode<JSObject> object);
TNode<HeapObject> LoadFastProperties(SloppyTNode<JSObject> object);
TNode<HeapObject> LoadProperties(SloppyTNode<JSObject> object);
// Load the elements backing store of a JSObject.
TNode<FixedArrayBase> LoadElements(SloppyTNode<JSObject> object);
// Load the length of a JSArray instance.

View File

@ -54,10 +54,10 @@ FieldAccess AccessBuilder::ForHeapNumberValue() {
// static
FieldAccess AccessBuilder::ForJSObjectPropertiesOrHash() {
FieldAccess AccessBuilder::ForJSObjectProperties() {
FieldAccess access = {kTaggedBase, JSObject::kPropertiesOrHashOffset,
MaybeHandle<Name>(), MaybeHandle<Map>(),
Type::Any(), MachineType::AnyTagged(),
Type::Internal(), MachineType::TaggedPointer(),
kPointerWriteBarrier};
return access;
}
@ -477,11 +477,14 @@ FieldAccess AccessBuilder::ForFixedArrayLength() {
}
// static
// TODO(gsathya): Rename this to PropertyArrayLengthAndHash.
FieldAccess AccessBuilder::ForPropertyArrayLength() {
FieldAccess access = {kTaggedBase, PropertyArray::kLengthOffset,
MaybeHandle<Name>(), MaybeHandle<Map>(),
Type::SignedSmall(), MachineType::TaggedSigned(),
// TODO(gsathya): Update the value range once we add the hash code.
FieldAccess access = {kTaggedBase,
PropertyArray::kLengthOffset,
MaybeHandle<Name>(),
MaybeHandle<Map>(),
TypeCache::Get().kPropertyArrayLengthType,
MachineType::TaggedSigned(),
kNoWriteBarrier};
return access;
}
@ -1112,19 +1115,6 @@ FieldAccess AccessBuilder::ForDictionaryNextEnumerationIndex() {
return access;
}
// static
FieldAccess AccessBuilder::ForDictionaryObjectHashIndex() {
FieldAccess access = {
kTaggedBase,
FixedArray::OffsetOfElementAt(NameDictionary::kObjectHashIndex),
MaybeHandle<Name>(),
MaybeHandle<Map>(),
Type::SignedSmall(),
MachineType::TaggedSigned(),
kNoWriteBarrier};
return access;
}
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -39,7 +39,7 @@ class V8_EXPORT_PRIVATE AccessBuilder final
static FieldAccess ForHeapNumberValue();
// Provides access to JSObject::properties() field.
static FieldAccess ForJSObjectPropertiesOrHash();
static FieldAccess ForJSObjectProperties();
// Provides access to JSObject::elements() field.
static FieldAccess ForJSObjectElements();
@ -303,7 +303,6 @@ class V8_EXPORT_PRIVATE AccessBuilder final
// Provides access to Dictionary fields.
static FieldAccess ForDictionaryMaxNumberKey();
static FieldAccess ForDictionaryNextEnumerationIndex();
static FieldAccess ForDictionaryObjectHashIndex();
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(AccessBuilder);

View File

@ -303,8 +303,8 @@ Reduction JSBuiltinReducer::ReduceArrayIterator(Handle<Map> receiver_map,
effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
value, jsgraph()->Constant(map), effect, control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForJSObjectPropertiesOrHash()),
value, jsgraph()->EmptyFixedArrayConstant(), effect, control);
simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value,
jsgraph()->EmptyFixedArrayConstant(), effect, control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value,
jsgraph()->EmptyFixedArrayConstant(), effect, control);
@ -1250,8 +1250,8 @@ Reduction JSBuiltinReducer::ReduceCollectionIterator(
simplified()->StoreField(AccessBuilder::ForMap()), value,
jsgraph()->Constant(collection_iterator_map), effect, control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForJSObjectPropertiesOrHash()),
value, jsgraph()->EmptyFixedArrayConstant(), effect, control);
simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value,
jsgraph()->EmptyFixedArrayConstant(), effect, control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value,
jsgraph()->EmptyFixedArrayConstant(), effect, control);
@ -1668,8 +1668,8 @@ Reduction JSBuiltinReducer::ReduceFunctionBind(Node* node) {
effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
value, jsgraph()->Constant(map), effect, control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForJSObjectPropertiesOrHash()),
value, jsgraph()->EmptyFixedArrayConstant(), effect, control);
simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value,
jsgraph()->EmptyFixedArrayConstant(), effect, control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value,
jsgraph()->EmptyFixedArrayConstant(), effect, control);
@ -2345,15 +2345,9 @@ Reduction JSBuiltinReducer::ReduceObjectCreate(Node* node) {
AccessBuilder::ForDictionaryNextEnumerationIndex()),
value, jsgraph()->SmiConstant(PropertyDetails::kInitialIndex), effect,
control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForDictionaryObjectHashIndex()),
value, jsgraph()->SmiConstant(PropertyArray::kNoHashSentinel), effect,
control);
// Initialize the Properties fields.
STATIC_ASSERT(NameDictionary::kElementsStartIndex ==
NameDictionary::kObjectHashIndex + 1);
for (int index = NameDictionary::kElementsStartIndex; index < length;
index++) {
for (int index = NameDictionary::kNextEnumerationIndexIndex + 1;
index < length; index++) {
effect = graph()->NewNode(
simplified()->StoreField(
AccessBuilder::ForFixedArraySlot(index, kNoWriteBarrier)),
@ -2378,8 +2372,8 @@ Reduction JSBuiltinReducer::ReduceObjectCreate(Node* node) {
graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()), value,
jsgraph()->HeapConstant(instance_map), effect, control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForJSObjectPropertiesOrHash()),
value, properties, effect, control);
simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value,
properties, effect, control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value,
jsgraph()->EmptyFixedArrayConstant(), effect, control);
@ -2622,8 +2616,8 @@ Reduction JSBuiltinReducer::ReduceStringIterator(Node* node) {
effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
value, map, effect, control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForJSObjectPropertiesOrHash()),
value, jsgraph()->EmptyFixedArrayConstant(), effect, control);
simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value,
jsgraph()->EmptyFixedArrayConstant(), effect, control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value,
jsgraph()->EmptyFixedArrayConstant(), effect, control);

View File

@ -276,7 +276,7 @@ Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
AllocationBuilder a(jsgraph(), effect, control);
a.Allocate(instance_size);
a.Store(AccessBuilder::ForMap(), initial_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
a.Store(AccessBuilder::ForJSObjectProperties(),
jsgraph()->EmptyFixedArrayConstant());
a.Store(AccessBuilder::ForJSObjectElements(),
jsgraph()->EmptyFixedArrayConstant());
@ -333,7 +333,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kPointerSize);
a.Allocate(JSSloppyArgumentsObject::kSize);
a.Store(AccessBuilder::ForMap(), arguments_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
a.Store(AccessBuilder::ForJSObjectElements(), elements);
a.Store(AccessBuilder::ForArgumentsLength(), arguments_length);
a.Store(AccessBuilder::ForArgumentsCallee(), callee);
@ -379,7 +379,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
a.Allocate(JSStrictArgumentsObject::kSize);
a.Store(AccessBuilder::ForMap(), arguments_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
a.Store(AccessBuilder::ForJSObjectElements(), elements);
a.Store(AccessBuilder::ForArgumentsLength(), arguments_length);
RelaxControls(node);
@ -424,7 +424,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
a.Allocate(JSArray::kSize);
a.Store(AccessBuilder::ForMap(), jsarray_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
a.Store(AccessBuilder::ForJSObjectElements(), elements);
a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS),
rest_length);
@ -479,7 +479,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kPointerSize);
a.Allocate(JSSloppyArgumentsObject::kSize);
a.Store(AccessBuilder::ForMap(), arguments_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
a.Store(AccessBuilder::ForJSObjectElements(), elements);
a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
a.Store(AccessBuilder::ForArgumentsCallee(), callee);
@ -508,7 +508,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
a.Allocate(JSStrictArgumentsObject::kSize);
a.Store(AccessBuilder::ForMap(), arguments_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
a.Store(AccessBuilder::ForJSObjectElements(), elements);
a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
RelaxControls(node);
@ -543,7 +543,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
a.Allocate(JSArray::kSize);
a.Store(AccessBuilder::ForMap(), jsarray_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
a.Store(AccessBuilder::ForJSObjectElements(), elements);
a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS),
jsgraph()->Constant(length));
@ -593,7 +593,7 @@ Reduction JSCreateLowering::ReduceJSCreateGeneratorObject(Node* node) {
Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
Node* undefined = jsgraph()->UndefinedConstant();
a.Store(AccessBuilder::ForMap(), initial_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), empty_fixed_array);
a.Store(AccessBuilder::ForJSObjectProperties(), empty_fixed_array);
a.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array);
a.Store(AccessBuilder::ForJSGeneratorObjectContext(), context);
a.Store(AccessBuilder::ForJSGeneratorObjectFunction(), closure);
@ -660,7 +660,7 @@ Reduction JSCreateLowering::ReduceNewArray(Node* node, Node* length,
AllocationBuilder a(jsgraph(), effect, control);
a.Allocate(JSArray::kSize, pretenure);
a.Store(AccessBuilder::ForMap(), js_array_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
a.Store(AccessBuilder::ForJSObjectElements(), elements);
a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
RelaxControls(node);
@ -719,7 +719,7 @@ Reduction JSCreateLowering::ReduceNewArray(Node* node,
AllocationBuilder a(jsgraph(), effect, control);
a.Allocate(JSArray::kSize, pretenure);
a.Store(AccessBuilder::ForMap(), js_array_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
a.Store(AccessBuilder::ForJSObjectElements(), elements);
a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
RelaxControls(node);
@ -851,7 +851,7 @@ Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) {
AllocationBuilder a(jsgraph(), effect, graph()->start());
a.Allocate(JSIteratorResult::kSize);
a.Store(AccessBuilder::ForMap(), iterator_result_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
a.Store(AccessBuilder::ForJSObjectProperties(),
jsgraph()->EmptyFixedArrayConstant());
a.Store(AccessBuilder::ForJSObjectElements(),
jsgraph()->EmptyFixedArrayConstant());
@ -884,7 +884,7 @@ Reduction JSCreateLowering::ReduceJSCreateKeyValueArray(Node* node) {
AllocationBuilder a(jsgraph(), elements, graph()->start());
a.Allocate(JSArray::kSize);
a.Store(AccessBuilder::ForMap(), array_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
a.Store(AccessBuilder::ForJSObjectElements(), elements);
a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS), length);
STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
@ -1349,7 +1349,7 @@ Node* JSCreateLowering::AllocateFastLiteral(
builder.Allocate(boilerplate_map->instance_size(), pretenure,
Type::For(boilerplate_map));
builder.Store(AccessBuilder::ForMap(), boilerplate_map);
builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
builder.Store(AccessBuilder::ForJSObjectProperties(), properties);
builder.Store(AccessBuilder::ForJSObjectElements(), elements);
if (boilerplate_map->IsJSArrayMap()) {
Handle<JSArray> boilerplate_array = Handle<JSArray>::cast(boilerplate);
@ -1455,7 +1455,7 @@ Node* JSCreateLowering::AllocateLiteralRegExp(Node* effect, Node* control,
AllocationBuilder builder(jsgraph(), effect, control);
builder.Allocate(size, pretenure, Type::For(boilerplate_map));
builder.Store(AccessBuilder::ForMap(), boilerplate_map);
builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
builder.Store(AccessBuilder::ForJSObjectProperties(),
handle(boilerplate->raw_properties_or_hash(), isolate()));
builder.Store(AccessBuilder::ForJSObjectElements(),
handle(boilerplate->elements(), isolate()));

View File

@ -1654,7 +1654,7 @@ JSNativeContextSpecialization::BuildPropertyStore(
Node* storage = receiver;
if (!field_index.is_inobject()) {
storage = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSObjectPropertiesOrHash()),
simplified()->LoadField(AccessBuilder::ForJSObjectProperties()),
storage, effect, control);
}
FieldAccess field_access = {
@ -1800,7 +1800,7 @@ JSNativeContextSpecialization::BuildPropertyStore(
storage, value, effect, control);
// Atomically switch to the new properties below.
field_access = AccessBuilder::ForJSObjectPropertiesOrHash();
field_access = AccessBuilder::ForJSObjectProperties();
value = storage;
storage = receiver;
}
@ -2242,17 +2242,8 @@ Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore(
values.push_back(jsgraph()->UndefinedConstant());
}
// Allocate and initialize the new properties.
Node* new_length_and_hash = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForPropertyArrayLength()),
properties, effect, control);
effect = graph()->NewNode(
common()->BeginRegion(RegionObservability::kNotObservable), effect);
new_length_and_hash =
graph()->NewNode(simplified()->NumberBitwiseAnd(), new_length_and_hash,
jsgraph()->Constant(JSReceiver::kHashMask));
new_length_and_hash =
graph()->NewNode(simplified()->NumberBitwiseOr(), new_length_and_hash,
jsgraph()->Constant(new_length));
Node* new_properties = effect = graph()->NewNode(
simplified()->Allocate(Type::OtherInternal(), NOT_TENURED),
jsgraph()->Constant(PropertyArray::SizeFor(new_length)), effect, control);
@ -2261,12 +2252,13 @@ Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore(
jsgraph()->PropertyArrayMapConstant(), effect, control);
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForPropertyArrayLength()),
new_properties, new_length_and_hash, effect, control);
new_properties, jsgraph()->Constant(new_length), effect, control);
for (int i = 0; i < new_length; ++i) {
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)),
new_properties, values[i], effect, control);
}
// TODO(gsathya): Update hash code here.
return graph()->NewNode(common()->FinishRegion(), new_properties, effect);
}

View File

@ -224,7 +224,7 @@ Node* PropertyAccessBuilder::BuildLoadDataField(
Node* storage = receiver;
if (!field_index.is_inobject()) {
storage = *effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSObjectPropertiesOrHash()),
simplified()->LoadField(AccessBuilder::ForJSObjectProperties()),
storage, *effect, *control);
}
FieldAccess field_access = {

View File

@ -83,6 +83,11 @@ class TypeCache final {
// [0, FixedArray::kMaxLength].
Type* const kFixedArrayLengthType = CreateRange(0.0, FixedArray::kMaxLength);
// The PropertyArray::length property always containts a smi in the range
// [0, PropertyArray::kMaxLength].
Type* const kPropertyArrayLengthType =
CreateRange(0.0, PropertyArray::kMaxLength);
// The FixedDoubleArray::length property always containts a smi in the range
// [0, FixedDoubleArray::kMaxLength].
Type* const kFixedDoubleArrayLengthType =

View File

@ -221,6 +221,7 @@
V(error_script_symbol) \
V(error_start_pos_symbol) \
V(frozen_symbol) \
V(hash_code_symbol) \
V(home_object_symbol) \
V(intl_initialized_marker_symbol) \
V(intl_pattern_symbol) \

View File

@ -194,7 +194,7 @@ using v8::MemoryPressureLevel;
V(FixedArray, string_split_cache, StringSplitCache) \
V(FixedArray, regexp_multiple_cache, RegExpMultipleCache) \
/* Lists and dictionaries */ \
V(NameDictionary, empty_property_dictionary, EmptyPropertyDictionary) \
V(NameDictionary, empty_property_dictionary, EmptyPropertiesDictionary) \
V(NameDictionary, public_symbol_table, PublicSymbolTable) \
V(NameDictionary, api_symbol_table, ApiSymbolTable) \
V(NameDictionary, api_private_symbol_table, ApiPrivateSymbolTable) \

View File

@ -195,7 +195,7 @@ void AccessorAssembler::HandleLoadField(Node* holder, Node* handler_word,
BIND(&out_of_object);
{
Label is_double(this);
Node* properties = LoadFastProperties(holder);
Node* properties = LoadProperties(holder);
Node* value = LoadObjectField(properties, offset);
GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double);
exit_point->Return(value);
@ -322,7 +322,7 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
BIND(&normal);
{
Comment("load_normal");
Node* properties = LoadSlowProperties(holder);
Node* properties = LoadProperties(holder);
VARIABLE(var_name_index, MachineType::PointerRepresentation());
Label found(this, &var_name_index);
NameDictionaryLookup<NameDictionary>(properties, p->name, &found,
@ -423,7 +423,7 @@ void AccessorAssembler::HandleLoadICProtoHandlerCase(
{
CSA_ASSERT(this, Word32BinaryNot(
HasInstanceType(p->receiver, JS_GLOBAL_OBJECT_TYPE)));
Node* properties = LoadSlowProperties(p->receiver);
Node* properties = LoadProperties(p->receiver);
VARIABLE(var_name_index, MachineType::PointerRepresentation());
Label found(this, &var_name_index);
NameDictionaryLookup<NameDictionary>(properties, p->name, &found,
@ -593,7 +593,7 @@ void AccessorAssembler::HandleStoreICHandlerCase(
WordEqual(handler_word, IntPtrConstant(StoreHandler::kStoreNormal)),
&if_fast_smi);
Node* properties = LoadSlowProperties(holder);
Node* properties = LoadProperties(holder);
VARIABLE(var_name_index, MachineType::PointerRepresentation());
Label dictionary_found(this, &var_name_index);
@ -841,7 +841,7 @@ void AccessorAssembler::HandleStoreICProtoHandler(
BIND(&if_store_normal);
{
Node* properties = LoadSlowProperties(p->receiver);
Node* properties = LoadProperties(p->receiver);
VARIABLE(var_name_index, MachineType::PointerRepresentation());
Label found(this, &var_name_index), not_found(this);
@ -1050,14 +1050,8 @@ void AccessorAssembler::ExtendPropertiesBackingStore(Node* object,
ParameterMode mode = OptimalParameterMode();
// TODO(gsathya): Clean up the type conversions by creating smarter
// helpers that do the correct op based on the mode.
Node* properties = LoadFastProperties(object);
Node* length_and_hash_int32 =
LoadAndUntagToWord32ObjectField(properties, PropertyArray::kLengthOffset);
Node* length_intptr = ChangeInt32ToIntPtr(Word32And(
length_and_hash_int32, Int32Constant(PropertyArray::kLengthMask)));
Node* length = WordToParameter(length_intptr, mode);
Node* properties = LoadProperties(object);
Node* length = TaggedToParameter(LoadPropertyArrayLength(properties), mode);
// Previous property deletion could have left behind unused backing store
// capacity even for a map that think it doesn't have any unused fields.
@ -1091,16 +1085,7 @@ void AccessorAssembler::ExtendPropertiesBackingStore(Node* object,
CopyPropertyArrayValues(properties, new_properties, length,
SKIP_WRITE_BARRIER, mode);
// TODO(gsathya): Clean up the type conversions by creating smarter
// helpers that do the correct op based on the mode.
Node* masked_hash_int32 =
Word32And(length_and_hash_int32, Int32Constant(JSReceiver::kHashMask));
Node* new_capacity_int32 =
TruncateWordToWord32(ParameterToWord(new_capacity, mode));
Node* new_length_and_hash_int32 =
Word32Or(masked_hash_int32, new_capacity_int32);
StoreObjectField(new_properties, PropertyArray::kLengthOffset,
SmiFromWord32(new_length_and_hash_int32));
// TODO(gsathya): Update hash code here.
StoreObjectField(object, JSObject::kPropertiesOrHashOffset, new_properties);
Comment("] Extend storage");
Goto(&done);
@ -1116,7 +1101,7 @@ void AccessorAssembler::StoreNamedField(Node* handler_word, Node* object,
bool store_value_as_double = representation.IsDouble();
Node* property_storage = object;
if (!is_inobject) {
property_storage = LoadFastProperties(object);
property_storage = LoadProperties(object);
}
Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word);
@ -1417,7 +1402,7 @@ void AccessorAssembler::CheckPrototype(Node* prototype_cell, Node* name,
void AccessorAssembler::NameDictionaryNegativeLookup(Node* object, Node* name,
Label* miss) {
CSA_ASSERT(this, IsDictionaryMap(LoadMap(object)));
Node* properties = LoadSlowProperties(object);
Node* properties = LoadProperties(object);
// Ensure the property does not exist in a dictionary-mode object.
VARIABLE(var_name_index, MachineType::PointerRepresentation());
Label done(this);
@ -1550,7 +1535,7 @@ void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map,
VARIABLE(var_name_index, MachineType::PointerRepresentation());
Label dictionary_found(this, &var_name_index);
Node* properties = LoadSlowProperties(receiver);
Node* properties = LoadProperties(receiver);
NameDictionaryLookup<NameDictionary>(properties, p->name, &dictionary_found,
&var_name_index,
&lookup_prototype_chain);

View File

@ -784,7 +784,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
BIND(&data_property);
{
CheckForAssociatedProtector(p->name, slow);
Node* properties = LoadFastProperties(receiver);
Node* properties = LoadProperties(receiver);
OverwriteExistingFastProperty(receiver, receiver_map, properties,
descriptors, name_index, details,
p->value, slow);
@ -854,7 +854,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
VARIABLE(var_name_index, MachineType::PointerRepresentation());
Label dictionary_found(this, &var_name_index), not_found(this);
Node* properties = LoadSlowProperties(receiver);
Node* properties = LoadProperties(receiver);
NameDictionaryLookup<NameDictionary>(properties, p->name, &dictionary_found,
&var_name_index, &not_found);
BIND(&dictionary_found);

View File

@ -11,6 +11,7 @@
// -------------------------------------------------------------------
// Imports
var hashCodeSymbol = utils.ImportNow("hash_code_symbol");
var GlobalWeakMap = global.WeakMap;
var GlobalWeakSet = global.WeakSet;
var MathRandom = global.Math.random;
@ -19,7 +20,8 @@ var MathRandom = global.Math.random;
function GetExistingHash(key) {
if (IS_RECEIVER(key) && !IS_PROXY(key) && !IS_GLOBAL(key)) {
return %GetExistingHash(key);
var hash = GET_PRIVATE(key, hashCodeSymbol);
return hash;
}
return %GenericHash(key);
}
@ -27,7 +29,13 @@ function GetExistingHash(key) {
function GetHash(key) {
return %GenericHash(key);
var hash = GetExistingHash(key);
if (IS_UNDEFINED(hash)) {
hash = (MathRandom() * 0x40000000) | 0;
if (hash === 0) hash = 1;
SET_PRIVATE(key, hashCodeSymbol, hash);
}
return hash;
}
%SetForceInlineFlag(GetHash);

View File

@ -2681,9 +2681,9 @@ SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
int PropertyArray::length() const {
Object* value_obj = READ_FIELD(this, kLengthOffset);
int value = Smi::ToInt(value_obj);
return value & kLengthMask;
Object* value = READ_FIELD(this, kLengthOffset);
int len = Smi::ToInt(value);
return len & kLengthMask;
}
void PropertyArray::initialize_length(int len) {
@ -2693,23 +2693,9 @@ void PropertyArray::initialize_length(int len) {
}
int PropertyArray::synchronized_length() const {
Object* value_obj = ACQUIRE_READ_FIELD(this, kLengthOffset);
int value = Smi::ToInt(value_obj);
return value & kLengthMask;
}
int PropertyArray::Hash() const {
Object* value_obj = READ_FIELD(this, kLengthOffset);
int value = Smi::ToInt(value_obj);
int hash = value & kHashMask;
return hash;
}
void PropertyArray::SetHash(int masked_hash) {
Object* value_obj = READ_FIELD(this, kLengthOffset);
int value = Smi::ToInt(value_obj);
value |= masked_hash;
WRITE_FIELD(this, kLengthOffset, Smi::FromInt(value));
Object* value = ACQUIRE_READ_FIELD(this, kLengthOffset);
int len = Smi::ToInt(value);
return len & kLengthMask;
}
SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
@ -5473,7 +5459,7 @@ bool JSObject::HasIndexedInterceptor() {
void JSGlobalObject::set_global_dictionary(GlobalDictionary* dictionary) {
DCHECK(IsJSGlobalObject());
set_raw_properties_or_hash(dictionary);
return SetProperties(dictionary);
}
GlobalDictionary* JSGlobalObject::global_dictionary() {
@ -5602,13 +5588,7 @@ bool JSReceiver::HasFastProperties() const {
NameDictionary* JSReceiver::property_dictionary() const {
DCHECK(!IsJSGlobalObject());
DCHECK(!HasFastProperties());
Object* prop = raw_properties_or_hash();
if (prop->IsSmi()) {
return GetHeap()->empty_property_dictionary();
}
return NameDictionary::cast(prop);
return NameDictionary::cast(raw_properties_or_hash());
}
// TODO(gsathya): Pass isolate directly to this function and access
@ -5624,6 +5604,11 @@ PropertyArray* JSReceiver::property_array() const {
return PropertyArray::cast(prop);
}
void JSReceiver::SetProperties(HeapObject* properties) {
// TODO(gsathya): Update the hash code here.
set_raw_properties_or_hash(properties);
}
Maybe<bool> JSReceiver::HasProperty(Handle<JSReceiver> object,
Handle<Name> name) {
LookupIterator it = LookupIterator::PropertyOrElement(object->GetIsolate(),
@ -5716,10 +5701,12 @@ Smi* JSReceiver::GetOrCreateIdentityHash(Isolate* isolate,
isolate, Handle<JSObject>::cast(object));
}
Object* JSReceiver::GetIdentityHash(Isolate* isolate, JSReceiver* receiver) {
Object* JSReceiver::GetIdentityHash(Isolate* isolate,
Handle<JSReceiver> receiver) {
return receiver->IsJSProxy()
? JSProxy::GetIdentityHash(JSProxy::cast(receiver))
: JSObject::GetIdentityHash(isolate, JSObject::cast(receiver));
? JSProxy::GetIdentityHash(Handle<JSProxy>::cast(receiver))
: JSObject::GetIdentityHash(isolate,
Handle<JSObject>::cast(receiver));
}

View File

@ -2322,7 +2322,7 @@ Object* Object::GetHash() {
DCHECK(IsJSReceiver());
JSReceiver* receiver = JSReceiver::cast(this);
Isolate* isolate = receiver->GetIsolate();
return JSReceiver::GetIdentityHash(isolate, receiver);
return JSReceiver::GetIdentityHash(isolate, handle(receiver, isolate));
}
Smi* Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
@ -6257,74 +6257,6 @@ Handle<SeededNumberDictionary> JSObject::NormalizeElements(
return dictionary;
}
namespace {
Object* SetHashAndUpdateProperties(HeapObject* properties, int masked_hash) {
DCHECK_NE(PropertyArray::kNoHashSentinel, masked_hash);
DCHECK_EQ(masked_hash & JSReceiver::kHashMask, masked_hash);
if (properties == properties->GetHeap()->empty_fixed_array() ||
properties == properties->GetHeap()->empty_property_dictionary()) {
return Smi::FromInt(masked_hash);
}
if (properties->IsPropertyArray()) {
PropertyArray::cast(properties)->SetHash(masked_hash);
return properties;
}
DCHECK(properties->IsDictionary());
NameDictionary::cast(properties)->SetHash(masked_hash);
return properties;
}
int GetIdentityHashHelper(Isolate* isolate, JSReceiver* object) {
Object* properties = object->raw_properties_or_hash();
if (properties->IsSmi()) {
return Smi::ToInt(properties);
}
if (properties->IsPropertyArray()) {
return PropertyArray::cast(properties)->Hash();
}
if (properties->IsDictionary()) {
return NameDictionary::cast(properties)->Hash();
}
#ifdef DEBUG
FixedArray* empty_fixed_array = isolate->heap()->empty_fixed_array();
FixedArray* empty_property_dictionary =
isolate->heap()->empty_property_dictionary();
DCHECK(properties == empty_fixed_array ||
properties == empty_property_dictionary);
#endif
return PropertyArray::kNoHashSentinel;
}
} // namespace
void JSReceiver::SetIdentityHash(int masked_hash) {
DCHECK_NE(PropertyArray::kNoHashSentinel, masked_hash);
DCHECK_EQ(masked_hash & JSReceiver::kHashMask, masked_hash);
HeapObject* existing_properties = HeapObject::cast(raw_properties_or_hash());
Object* new_properties =
SetHashAndUpdateProperties(existing_properties, masked_hash);
set_raw_properties_or_hash(new_properties);
}
void JSReceiver::SetProperties(HeapObject* properties) {
Isolate* isolate = properties->GetIsolate();
int hash = GetIdentityHashHelper(isolate, this);
Object* new_properties = properties;
if (hash != PropertyArray::kNoHashSentinel) {
new_properties = SetHashAndUpdateProperties(properties, hash);
}
set_raw_properties_or_hash(new_properties);
}
template <typename ProxyType>
static Smi* GetOrCreateIdentityHashHelper(Isolate* isolate,
@ -6338,17 +6270,12 @@ static Smi* GetOrCreateIdentityHashHelper(Isolate* isolate,
}
// static
Object* JSObject::GetIdentityHash(Isolate* isolate, JSObject* object) {
Object* JSObject::GetIdentityHash(Isolate* isolate, Handle<JSObject> object) {
if (object->IsJSGlobalProxy()) {
return JSGlobalProxy::cast(object)->hash();
return JSGlobalProxy::cast(*object)->hash();
}
int hash = GetIdentityHashHelper(isolate, object);
if (hash == PropertyArray::kNoHashSentinel) {
return isolate->heap()->undefined_value();
}
return Smi::FromInt(hash);
Handle<Name> hash_code_symbol = isolate->factory()->hash_code_symbol();
return *JSReceiver::GetDataProperty(object, hash_code_symbol);
}
// static
@ -6359,23 +6286,25 @@ Smi* JSObject::GetOrCreateIdentityHash(Isolate* isolate,
Handle<JSGlobalProxy>::cast(object));
}
Object* hash_obj = JSObject::GetIdentityHash(isolate, *object);
if (hash_obj != isolate->heap()->undefined_value()) {
return Smi::cast(hash_obj);
Handle<Name> hash_code_symbol = isolate->factory()->hash_code_symbol();
LookupIterator it(object, hash_code_symbol, object, LookupIterator::OWN);
if (it.IsFound()) {
DCHECK_EQ(LookupIterator::DATA, it.state());
Object* maybe_hash = *it.GetDataValue();
if (maybe_hash->IsSmi()) return Smi::cast(maybe_hash);
}
int hash;
do {
hash = isolate->GenerateIdentityHash(Smi::kMaxValue);
} while (hash == PropertyArray::kNoHashSentinel);
int masked_hash = hash & JSReceiver::kHashMask;
object->SetIdentityHash(masked_hash);
return Smi::FromInt(masked_hash);
Smi* hash = Smi::FromInt(isolate->GenerateIdentityHash(Smi::kMaxValue));
CHECK(AddDataProperty(&it, handle(hash, isolate), NONE, THROW_ON_ERROR,
CERTAINLY_NOT_STORE_FROM_KEYED)
.IsJust());
return hash;
}
// static
Object* JSProxy::GetIdentityHash(JSProxy* proxy) { return proxy->hash(); }
Object* JSProxy::GetIdentityHash(Handle<JSProxy> proxy) {
return proxy->hash();
}
Smi* JSProxy::GetOrCreateIdentityHash(Isolate* isolate, Handle<JSProxy> proxy) {
return GetOrCreateIdentityHashHelper(isolate, proxy);
@ -17405,6 +17334,7 @@ Handle<ObjectHashSet> ObjectHashSet::Add(Handle<ObjectHashSet> set,
Handle<Object> key) {
Isolate* isolate = set->GetIsolate();
int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
if (!set->Has(isolate, key, hash)) {
set = EnsureCapacity(set, 1);
int entry = set->FindInsertionEntry(hash);
@ -17723,7 +17653,6 @@ Handle<Derived> BaseNameDictionary<Derived, Shape>::New(
DCHECK_LE(0, at_least_space_for);
Handle<Derived> dict = Dictionary<Derived, Shape>::New(
isolate, at_least_space_for, pretenure, capacity_option);
dict->SetHash(PropertyArray::kNoHashSentinel);
dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
return dict;
}

View File

@ -1945,62 +1945,6 @@ enum class KeyCollectionMode {
enum class AllocationSiteUpdateMode { kUpdate, kCheckOnly };
class PropertyArray : public HeapObject {
public:
// [length]: length of the array.
inline int length() const;
// Get the length using acquire loads.
inline int synchronized_length() const;
// This is only used on a newly allocated PropertyArray which
// doesn't have an existing hash.
inline void initialize_length(int length);
inline void SetHash(int hash);
inline int Hash() const;
inline Object* get(int index) const;
inline void set(int index, Object* value);
// Setter with explicit barrier mode.
inline void set(int index, Object* value, WriteBarrierMode mode);
// Gives access to raw memory which stores the array's data.
inline Object** data_start();
// Garbage collection support.
static constexpr int SizeFor(int length) {
return kHeaderSize + length * kPointerSize;
}
DECL_CAST(PropertyArray)
DECL_PRINTER(PropertyArray)
DECL_VERIFIER(PropertyArray)
// Layout description.
// TODO(gsathya): Rename kLengthOffset to kLengthAndHashOffset.
static const int kLengthOffset = HeapObject::kHeaderSize;
static const int kHeaderSize = kLengthOffset + kPointerSize;
// Garbage collection support.
typedef FlexibleBodyDescriptor<kHeaderSize> BodyDescriptor;
// No weak fields.
typedef BodyDescriptor BodyDescriptorWeak;
static const int kLengthMask = 0x3ff;
static const int kHashMask = 0x7ffffc00;
STATIC_ASSERT(kLengthMask + kHashMask == 0x7fffffff);
static const int kMaxLength = kLengthMask;
STATIC_ASSERT(kMaxLength > kMaxNumberOfDescriptors);
static const int kNoHashSentinel = 0;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PropertyArray);
};
// JSReceiver includes types on which properties can be defined, i.e.,
// JSObject and JSProxy.
class JSReceiver: public HeapObject {
@ -2017,13 +1961,12 @@ class JSReceiver: public HeapObject {
// Gets slow properties for non-global objects.
inline NameDictionary* property_dictionary() const;
void SetProperties(HeapObject* properties);
inline void SetProperties(HeapObject* properties);
// There are five possible values for the properties offset.
// 1) EmptyFixedArray/EmptyPropertyDictionary - This is the standard
// placeholder.
// There are four possible value for the properties offset.
// 1) EmptyFixedArray -- This is the standard placeholder.
//
// 2) Smi - This is the hash code of the object.
// 2) TODO(gsathya): Smi -- This is the hash code of the object.
//
// 3) PropertyArray - This is similar to a FixedArray but stores
// the hash code of the object in its length field. This is a fast
@ -2031,9 +1974,6 @@ class JSReceiver: public HeapObject {
//
// 4) NameDictionary - This is the dictionary-mode backing store.
//
// 4) GlobalDictionary - This is the backing store for the
// GlobalObject.
//
// This is used only in the deoptimizer and heap. Please use the
// above typed getters and setters to access the properties.
DECL_ACCESSORS(raw_properties_or_hash, Object)
@ -2200,17 +2140,14 @@ class JSReceiver: public HeapObject {
// Retrieves a permanent object identity hash code. The undefined value might
// be returned in case no hash was created yet.
static inline Object* GetIdentityHash(Isolate* isolate, JSReceiver* object);
static inline Object* GetIdentityHash(Isolate* isolate,
Handle<JSReceiver> object);
// Retrieves a permanent object identity hash code. May create and store a
// hash code if needed and none exists.
inline static Smi* GetOrCreateIdentityHash(Isolate* isolate,
Handle<JSReceiver> object);
// Stores the hash code. The hash passed in must be masked with
// JSReceiver::kHashMask.
void SetIdentityHash(int masked_hash);
// ES6 [[OwnPropertyKeys]] (modulo return type)
MUST_USE_RESULT static inline MaybeHandle<FixedArray> OwnPropertyKeys(
Handle<JSReceiver> object);
@ -2221,8 +2158,6 @@ class JSReceiver: public HeapObject {
MUST_USE_RESULT static MaybeHandle<FixedArray> GetOwnEntries(
Handle<JSReceiver> object, PropertyFilter filter);
static const int kHashMask = PropertyArray::kHashMask;
// Layout description.
static const int kPropertiesOrHashOffset = HeapObject::kHeaderSize;
static const int kHeaderSize = HeapObject::kHeaderSize + kPointerSize;
@ -2728,7 +2663,7 @@ class JSObject: public JSReceiver {
ElementsKind kind,
Object* object);
static Object* GetIdentityHash(Isolate* isolate, JSObject* object);
static Object* GetIdentityHash(Isolate* isolate, Handle<JSObject> object);
static Smi* GetOrCreateIdentityHash(Isolate* isolate,
Handle<JSObject> object);
@ -3106,6 +3041,54 @@ class ArrayList : public FixedArray {
DISALLOW_IMPLICIT_CONSTRUCTORS(ArrayList);
};
class PropertyArray : public HeapObject {
public:
// [length]: length of the array.
inline int length() const;
// Get the length using acquire loads.
inline int synchronized_length() const;
// This is only used on a newly allocated PropertyArray which
// doesn't have an existing hash.
inline void initialize_length(int length);
inline Object* get(int index) const;
// Setter that doesn't need write barrier.
inline void set(int index, Object* value);
// Setter with explicit barrier mode.
inline void set(int index, Object* value, WriteBarrierMode mode);
// Gives access to raw memory which stores the array's data.
inline Object** data_start();
// Garbage collection support.
static constexpr int SizeFor(int length) {
return kHeaderSize + length * kPointerSize;
}
DECL_CAST(PropertyArray)
DECL_PRINTER(PropertyArray)
DECL_VERIFIER(PropertyArray)
// Layout description.
static const int kLengthOffset = HeapObject::kHeaderSize;
static const int kHeaderSize = kLengthOffset + kPointerSize;
// Garbage collection support.
typedef FlexibleBodyDescriptor<kHeaderSize> BodyDescriptor;
// No weak fields.
typedef BodyDescriptor BodyDescriptorWeak;
static const int kLengthMask = 1023;
static const int kMaxLength = kLengthMask;
STATIC_ASSERT(kMaxLength > kMaxNumberOfDescriptors);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PropertyArray);
};
enum SearchMode { ALL_ENTRIES, VALID_ENTRIES };
template <SearchMode search_mode, typename T>
@ -6355,7 +6338,7 @@ class JSProxy: public JSReceiver {
// No weak fields.
typedef BodyDescriptor BodyDescriptorWeak;
static Object* GetIdentityHash(JSProxy* receiver);
static Object* GetIdentityHash(Handle<JSProxy> receiver);
static Smi* GetOrCreateIdentityHash(Isolate* isolate, Handle<JSProxy> proxy);

View File

@ -112,7 +112,7 @@ class NameDictionaryShape : public BaseDictionaryShape<Handle<Name>> {
static inline uint32_t Hash(Isolate* isolate, Handle<Name> key);
static inline uint32_t HashForObject(Isolate* isolate, Object* object);
static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Name> key);
static const int kPrefixSize = 2;
static const int kPrefixSize = 1;
static const int kEntrySize = 3;
static const int kEntryValueIndex = 1;
static const bool kNeedsHoleCheck = false;
@ -125,7 +125,6 @@ class BaseNameDictionary : public Dictionary<Derived, Shape> {
public:
static const int kNextEnumerationIndexIndex =
HashTableBase::kPrefixStartIndex;
static const int kObjectHashIndex = kNextEnumerationIndexIndex + 1;
static const int kEntryValueIndex = 1;
// Accessors for next enumeration index.
@ -138,16 +137,6 @@ class BaseNameDictionary : public Dictionary<Derived, Shape> {
return Smi::ToInt(this->get(kNextEnumerationIndexIndex));
}
void SetHash(int masked_hash) {
DCHECK_EQ(masked_hash & JSReceiver::kHashMask, masked_hash);
this->set(kObjectHashIndex, Smi::FromInt(masked_hash));
}
int Hash() const {
Object* hash_obj = this->get(kObjectHashIndex);
return Smi::ToInt(hash_obj);
}
// Creates a new dictionary.
MUST_USE_RESULT static Handle<Derived> New(
Isolate* isolate, int at_least_space_for,
@ -182,10 +171,7 @@ class NameDictionary
static const int kEntryDetailsIndex = 2;
static const int kInitialCapacity = 2;
inline Name* NameAt(int entry);
inline void set_hash(int hash);
inline int hash() const;
};
class GlobalDictionaryShape : public NameDictionaryShape {

View File

@ -17,13 +17,6 @@ RUNTIME_FUNCTION(Runtime_TheHole) {
return isolate->heap()->the_hole_value();
}
RUNTIME_FUNCTION(Runtime_GetExistingHash) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
return object->GetHash();
}
RUNTIME_FUNCTION(Runtime_GenericHash) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());

View File

@ -90,7 +90,6 @@ namespace internal {
#define FOR_EACH_INTRINSIC_COLLECTIONS(F) \
F(TheHole, 0, 1) \
F(GenericHash, 1, 1) \
F(GetExistingHash, 1, 1) \
F(SetGrow, 1, 1) \
F(SetShrink, 1, 1) \
F(SetIteratorClone, 1, 1) \

View File

@ -4035,7 +4035,7 @@ THREADED_TEST(External) {
CHECK_EQ(i::HeapObject::cast(*obj)->map(), CcTest::heap()->external_map());
CHECK(ext->IsExternal());
CHECK(!CompileRun("new Set().add(this.ext)").IsEmpty());
CHECK_EQ(i::HeapObject::cast(*obj)->map(), CcTest::heap()->external_map());
CHECK_NE(i::HeapObject::cast(*obj)->map(), CcTest::heap()->external_map());
CHECK(ext->IsExternal());
}

View File

@ -84,7 +84,7 @@ static void TestHashMap(Handle<HashMap> table) {
CHECK_EQ(table->NumberOfElements(), i + 1);
CHECK_NE(table->FindEntry(key), HashMap::kNotFound);
CHECK_EQ(table->Lookup(key), *value);
CHECK(JSReceiver::GetIdentityHash(isolate, *key)->IsSmi());
CHECK(JSReceiver::GetIdentityHash(isolate, key)->IsSmi());
}
// Keys never added to the map which already have an identity hash
@ -94,7 +94,7 @@ static void TestHashMap(Handle<HashMap> table) {
CHECK(JSReceiver::GetOrCreateIdentityHash(isolate, key)->IsSmi());
CHECK_EQ(table->FindEntry(key), HashMap::kNotFound);
CHECK_EQ(table->Lookup(key), CcTest::heap()->the_hole_value());
CHECK(JSReceiver::GetIdentityHash(isolate, *key)->IsSmi());
CHECK(JSReceiver::GetIdentityHash(isolate, key)->IsSmi());
}
// Keys that don't have an identity hash should not be found and also
@ -102,7 +102,7 @@ static void TestHashMap(Handle<HashMap> table) {
for (int i = 0; i < 100; i++) {
Handle<JSReceiver> key = factory->NewJSArray(7);
CHECK_EQ(table->Lookup(key), CcTest::heap()->the_hole_value());
Object* identity_hash = JSReceiver::GetIdentityHash(isolate, *key);
Object* identity_hash = JSReceiver::GetIdentityHash(isolate, key);
CHECK_EQ(CcTest::heap()->undefined_value(), identity_hash);
}
}
@ -155,7 +155,7 @@ static void TestHashSet(Handle<HashSet> table) {
table = HashSet::Add(table, key);
CHECK_EQ(table->NumberOfElements(), i + 2);
CHECK(table->Has(isolate, key));
CHECK(JSReceiver::GetIdentityHash(isolate, *key)->IsSmi());
CHECK(JSReceiver::GetIdentityHash(isolate, key)->IsSmi());
}
// Keys never added to the map which already have an identity hash
@ -164,7 +164,7 @@ static void TestHashSet(Handle<HashSet> table) {
Handle<JSReceiver> key = factory->NewJSArray(7);
CHECK(JSReceiver::GetOrCreateIdentityHash(isolate, key)->IsSmi());
CHECK(!table->Has(isolate, key));
CHECK(JSReceiver::GetIdentityHash(isolate, *key)->IsSmi());
CHECK(JSReceiver::GetIdentityHash(isolate, key)->IsSmi());
}
// Keys that don't have an identity hash should not be found and also
@ -172,7 +172,7 @@ static void TestHashSet(Handle<HashSet> table) {
for (int i = 0; i < 100; i++) {
Handle<JSReceiver> key = factory->NewJSArray(7);
CHECK(!table->Has(isolate, key));
Object* identity_hash = JSReceiver::GetIdentityHash(isolate, *key);
Object* identity_hash = JSReceiver::GetIdentityHash(isolate, key);
CHECK_EQ(CcTest::heap()->undefined_value(), identity_hash);
}
}
@ -267,15 +267,15 @@ static void TestHashSetCausesGC(Handle<HashSet> table) {
#ifdef DEBUG
template <class HashMap>
static void TestHashMapDoesNotCauseGC(Handle<HashMap> table) {
template<class HashMap>
static void TestHashMapCausesGC(Handle<HashMap> table) {
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
Handle<JSObject> key = factory->NewJSArray(0);
// Even though we simulate a full heap, generating an identity hash
// code in subsequent calls will not request GC.
// Simulate a full heap so that generating an identity hash code
// in subsequent calls will request GC.
heap::SimulateFullSpace(CcTest::heap()->new_space());
heap::SimulateFullSpace(CcTest::heap()->old_space());
@ -285,7 +285,7 @@ static void TestHashMapDoesNotCauseGC(Handle<HashMap> table) {
// Calling Put() should request GC by returning a failure.
int gc_count = isolate->heap()->gc_count();
HashMap::Put(table, key, key);
CHECK(gc_count == isolate->heap()->gc_count());
CHECK(gc_count < isolate->heap()->gc_count());
}
@ -294,7 +294,7 @@ TEST(ObjectHashTableCausesGC) {
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
Isolate* isolate = CcTest::i_isolate();
TestHashMapDoesNotCauseGC(ObjectHashTable::New(isolate, 1));
TestHashMapCausesGC(ObjectHashTable::New(isolate, 1));
}
#endif

View File

@ -13,9 +13,17 @@ static Isolate* GetIsolateFrom(LocalContext* context) {
return reinterpret_cast<Isolate*>((*context)->GetIsolate());
}
void CopyHashCode(Handle<JSReceiver> from, Handle<JSReceiver> to) {
int hash = Smi::ToInt(from->GetHash());
to->SetIdentityHash(hash);
void CopyHashCode(Isolate* isolate, Handle<JSReceiver> from,
Handle<JSReceiver> to) {
Handle<Name> hash_code_symbol = isolate->factory()->hash_code_symbol();
Handle<Smi> hash =
Handle<Smi>::cast(JSObject::GetDataProperty(from, hash_code_symbol));
LookupIterator it(to, hash_code_symbol, to, LookupIterator::OWN);
CHECK(to->AddDataProperty(
&it, hash, NONE, v8::internal::AccessCheckInfo::THROW_ON_ERROR,
v8::internal::AccessCheckInfo::CERTAINLY_NOT_STORE_FROM_KEYED)
.IsJust());
}
void Verify(Handle<HeapObject> obj) {
@ -205,7 +213,7 @@ TEST(SmallOrderedHashSetDuplicateHashCode) {
CHECK(set->HasKey(isolate, key1));
Handle<JSObject> key2 = factory->NewJSObjectWithNullProto();
CopyHashCode(key1, key2);
CopyHashCode(isolate, key1, key2);
set = SmallOrderedHashSet::Add(set, key2);
Verify(set);
@ -230,9 +238,16 @@ TEST(SmallOrderedHashMapDuplicateHashCode) {
CHECK_EQ(1, map->NumberOfElements());
CHECK(map->HasKey(isolate, key1));
Handle<JSObject> key2 = factory->NewJSObjectWithNullProto();
CopyHashCode(key1, key2);
Handle<Name> hash_code_symbol = isolate->factory()->hash_code_symbol();
Handle<Smi> hash =
Handle<Smi>::cast(JSObject::GetDataProperty(key1, hash_code_symbol));
Handle<JSObject> key2 = factory->NewJSObjectWithNullProto();
LookupIterator it(key2, hash_code_symbol, key2, LookupIterator::OWN);
CHECK(key2->AddDataProperty(
&it, hash, NONE, v8::internal::AccessCheckInfo::THROW_ON_ERROR,
v8::internal::AccessCheckInfo::CERTAINLY_NOT_STORE_FROM_KEYED)
.IsJust());
CHECK(!key1->SameValue(*key2));
Object* hash1 = key1->GetHash();
Object* hash2 = key2->GetHash();
@ -584,7 +599,7 @@ TEST(OrderedHashMapDuplicateHashCode) {
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
Handle<JSObject> key2 = factory->NewJSObjectWithNullProto();
CopyHashCode(key1, key2);
CopyHashCode(isolate, key1, key2);
map = OrderedHashMap::Add(map, key2, value);
Verify(map);
@ -734,7 +749,7 @@ TEST(OrderedHashMapDuplicateHashCodeDeletion) {
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
Handle<JSObject> key2 = factory->NewJSObjectWithNullProto();
CopyHashCode(key1, key2);
CopyHashCode(isolate, key1, key2);
// We shouldn't be able to delete the key!
CHECK(!OrderedHashMap::Delete(isolate, *map, *key2));
@ -883,7 +898,7 @@ TEST(OrderedHashSetDuplicateHashCodeDeletion) {
CHECK(OrderedHashSet::HasKey(isolate, *set, *key1));
Handle<JSObject> key2 = factory->NewJSObjectWithNullProto();
CopyHashCode(key1, key2);
CopyHashCode(isolate, key1, key2);
// We shouldn't be able to delete the key!
CHECK(!OrderedHashSet::Delete(isolate, *set, *key2));