[runtime] Load only 10 bits as PropertyArray length
Bug: v8:6404 Change-Id: I187f20006c14aab4a36e2bfef31ca68ebb249e43 Reviewed-on: https://chromium-review.googlesource.com/576516 Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/master@{#46822}
This commit is contained in:
parent
d77e98e8df
commit
b2bf43d529
@ -2349,6 +2349,30 @@ Node* CodeStubAssembler::AllocateFixedArray(ElementsKind kind,
|
||||
return array;
|
||||
}
|
||||
|
||||
void CodeStubAssembler::InitializePropertyArrayLength(Node* property_array,
|
||||
Node* length,
|
||||
ParameterMode mode) {
|
||||
CSA_SLOW_ASSERT(this, IsPropertyArray(property_array));
|
||||
CSA_ASSERT(
|
||||
this, IntPtrOrSmiGreaterThan(length, IntPtrOrSmiConstant(0, mode), mode));
|
||||
CSA_ASSERT(
|
||||
this,
|
||||
IntPtrOrSmiLessThanOrEqual(
|
||||
length, IntPtrOrSmiConstant(PropertyArray::kMaxLength, mode), mode));
|
||||
StoreObjectFieldNoWriteBarrier(property_array, PropertyArray::kLengthOffset,
|
||||
ParameterToTagged(length, mode),
|
||||
MachineRepresentation::kTaggedSigned);
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::LoadPropertyArrayLength(Node* property_array) {
|
||||
CSA_SLOW_ASSERT(this, 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) {
|
||||
@ -2361,8 +2385,7 @@ Node* CodeStubAssembler::AllocatePropertyArray(Node* capacity_node,
|
||||
Heap::RootListIndex map_index = Heap::kPropertyArrayMapRootIndex;
|
||||
DCHECK(Heap::RootIsImmortalImmovable(map_index));
|
||||
StoreMapNoWriteBarrier(array, map_index);
|
||||
StoreObjectFieldNoWriteBarrier(array, FixedArray::kLengthOffset,
|
||||
ParameterToTagged(capacity_node, mode));
|
||||
InitializePropertyArrayLength(array, capacity_node, mode);
|
||||
return array;
|
||||
}
|
||||
|
||||
|
@ -419,6 +419,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
|
||||
// Map::GetConstructor()).
|
||||
Node* LoadMapConstructor(Node* map);
|
||||
|
||||
// This is only used on a newly allocated PropertyArray which
|
||||
// doesn't have an existing hash.
|
||||
void InitializePropertyArrayLength(Node* property_array, Node* length,
|
||||
ParameterMode mode);
|
||||
Node* LoadPropertyArrayLength(Node* property_array);
|
||||
|
||||
// Check if the map is set for slow properties.
|
||||
Node* IsDictionaryMap(Node* map);
|
||||
|
||||
|
@ -476,6 +476,19 @@ FieldAccess AccessBuilder::ForFixedArrayLength() {
|
||||
return access;
|
||||
}
|
||||
|
||||
// static
|
||||
FieldAccess AccessBuilder::ForPropertyArrayLength() {
|
||||
// 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;
|
||||
}
|
||||
|
||||
// static
|
||||
FieldAccess AccessBuilder::ForFixedTypedArrayBaseBasePointer() {
|
||||
FieldAccess access = {
|
||||
|
@ -160,6 +160,9 @@ class V8_EXPORT_PRIVATE AccessBuilder final
|
||||
// Provides access to FixedArray::length() field.
|
||||
static FieldAccess ForFixedArrayLength();
|
||||
|
||||
// Provides access to PropertyArray::length() field.
|
||||
static FieldAccess ForPropertyArrayLength();
|
||||
|
||||
// Provides access to FixedTypedArrayBase::base_pointer() field.
|
||||
static FieldAccess ForFixedTypedArrayBaseBasePointer();
|
||||
|
||||
|
@ -2248,13 +2248,14 @@ Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore(
|
||||
simplified()->StoreField(AccessBuilder::ForMap()), new_properties,
|
||||
jsgraph()->PropertyArrayMapConstant(), effect, control);
|
||||
effect = graph()->NewNode(
|
||||
simplified()->StoreField(AccessBuilder::ForFixedArrayLength()),
|
||||
simplified()->StoreField(AccessBuilder::ForPropertyArrayLength()),
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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 =
|
||||
|
@ -4084,6 +4084,19 @@ AllocationResult Heap::AllocateEmptyFixedTypedArray(
|
||||
return AllocateFixedTypedArray(0, array_type, false, TENURED);
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
void initialize_length(T* array, int length) {
|
||||
array->set_length(length);
|
||||
}
|
||||
|
||||
template <>
|
||||
void initialize_length<PropertyArray>(PropertyArray* array, int length) {
|
||||
array->initialize_length(length);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
template <typename T>
|
||||
AllocationResult Heap::CopyArrayAndGrow(T* src, int grow_by,
|
||||
PretenureFlag pretenure) {
|
||||
@ -4098,7 +4111,7 @@ AllocationResult Heap::CopyArrayAndGrow(T* src, int grow_by,
|
||||
|
||||
obj->set_map_after_allocation(src->map(), SKIP_WRITE_BARRIER);
|
||||
T* result = T::cast(obj);
|
||||
result->set_length(new_len);
|
||||
initialize_length(result, new_len);
|
||||
|
||||
// Copy the content.
|
||||
DisallowHeapAllocation no_gc;
|
||||
@ -4159,7 +4172,7 @@ AllocationResult Heap::CopyArrayWithMap(T* src, Map* map) {
|
||||
}
|
||||
|
||||
// Slow case: Just copy the content one-by-one.
|
||||
result->set_length(len);
|
||||
initialize_length(result, len);
|
||||
for (int i = 0; i < len; i++) result->set(i, src->get(i), mode);
|
||||
return result;
|
||||
}
|
||||
@ -4243,7 +4256,7 @@ AllocationResult Heap::AllocatePropertyArray(int length,
|
||||
|
||||
result->set_map_after_allocation(property_array_map(), SKIP_WRITE_BARRIER);
|
||||
PropertyArray* array = PropertyArray::cast(result);
|
||||
array->set_length(length);
|
||||
array->initialize_length(length);
|
||||
MemsetPointer(array->data_start(), undefined_value(), length);
|
||||
return result;
|
||||
}
|
||||
|
@ -1050,9 +1050,7 @@ void AccessorAssembler::ExtendPropertiesBackingStore(Node* object,
|
||||
ParameterMode mode = OptimalParameterMode();
|
||||
|
||||
Node* properties = LoadProperties(object);
|
||||
Node* length = (mode == INTPTR_PARAMETERS)
|
||||
? LoadAndUntagFixedArrayBaseLength(properties)
|
||||
: LoadFixedArrayBaseLength(properties);
|
||||
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.
|
||||
@ -1086,6 +1084,7 @@ void AccessorAssembler::ExtendPropertiesBackingStore(Node* object,
|
||||
CopyPropertyArrayValues(properties, new_properties, length,
|
||||
SKIP_WRITE_BARRIER, mode);
|
||||
|
||||
// TODO(gsathya): Update hash code here.
|
||||
StoreObjectField(object, JSObject::kPropertiesOrHashOffset, new_properties);
|
||||
Comment("] Extend storage");
|
||||
Goto(&done);
|
||||
|
@ -2701,8 +2701,23 @@ const HashTable<Derived, Shape>* HashTable<Derived, Shape>::cast(
|
||||
SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
|
||||
SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
|
||||
|
||||
SMI_ACCESSORS(PropertyArray, length, kLengthOffset)
|
||||
SYNCHRONIZED_SMI_ACCESSORS(PropertyArray, length, kLengthOffset)
|
||||
int PropertyArray::length() const {
|
||||
Object* value = READ_FIELD(this, kLengthOffset);
|
||||
int len = Smi::ToInt(value);
|
||||
return len & kLengthMask;
|
||||
}
|
||||
|
||||
void PropertyArray::initialize_length(int len) {
|
||||
SLOW_DCHECK(len >= 0);
|
||||
SLOW_DCHECK(len < kMaxLength);
|
||||
WRITE_FIELD(this, kLengthOffset, Smi::FromInt(len));
|
||||
}
|
||||
|
||||
int PropertyArray::synchronized_length() const {
|
||||
Object* value = ACQUIRE_READ_FIELD(this, kLengthOffset);
|
||||
int len = Smi::ToInt(value);
|
||||
return len & kLengthMask;
|
||||
}
|
||||
|
||||
SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
|
||||
RELAXED_SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
|
||||
|
@ -3041,11 +3041,13 @@ class PropertyArray : public HeapObject {
|
||||
public:
|
||||
// [length]: length of the array.
|
||||
inline int length() const;
|
||||
inline void set_length(int length);
|
||||
|
||||
// Get and set the length using acquire loads and release stores.
|
||||
// Get the length using acquire loads.
|
||||
inline int synchronized_length() const;
|
||||
inline void synchronized_set_length(int value);
|
||||
|
||||
// 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;
|
||||
|
||||
@ -3075,6 +3077,10 @@ class PropertyArray : public HeapObject {
|
||||
// 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);
|
||||
};
|
||||
|
@ -34,6 +34,8 @@
|
||||
#undef WRITE_INT_FIELD
|
||||
#undef READ_INTPTR_FIELD
|
||||
#undef WRITE_INTPTR_FIELD
|
||||
#undef RELAXED_READ_INTPTR_FIELD
|
||||
#undef RELAXED_WRITE_INTPTR_FIELD
|
||||
#undef READ_UINT8_FIELD
|
||||
#undef WRITE_UINT8_FIELD
|
||||
#undef READ_INT8_FIELD
|
||||
|
@ -178,6 +178,10 @@
|
||||
#define WRITE_INT_FIELD(p, offset, value) \
|
||||
(*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
|
||||
|
||||
#define RELAXED_READ_INTPTR_FIELD(p, offset) \
|
||||
static_cast<intptr_t>(base::Relaxed_Load( \
|
||||
reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset))))
|
||||
|
||||
#define READ_INTPTR_FIELD(p, offset) \
|
||||
(*reinterpret_cast<const intptr_t*>(FIELD_ADDR_CONST(p, offset)))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user