Commit 7f031160 authored by Marja Hölttä's avatar Marja Hölttä Committed by Commit Bot

[objects.h splitting] Move FixedArray & co.

BUG=v8:5402,v8:7109

Change-Id: Ief9bea58e4dcade4cf4dfbb1d52166b7a5ef3ac0
Reviewed-on: https://chromium-review.googlesource.com/803255
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49787}
parent 1c819ae0
......@@ -757,6 +757,8 @@ action("postmortem-metadata") {
"src/objects-inl.h",
"src/objects/code-inl.h",
"src/objects/code.h",
"src/objects/fixed-array-inl.h",
"src/objects/fixed-array.h",
"src/objects/js-array-inl.h",
"src/objects/js-array.h",
"src/objects/js-regexp-inl.h",
......@@ -1805,6 +1807,8 @@ v8_source_set("v8_base") {
"src/objects/debug-objects.h",
"src/objects/descriptor-array.h",
"src/objects/dictionary.h",
"src/objects/fixed-array-inl.h",
"src/objects/fixed-array.h",
"src/objects/frame-array-inl.h",
"src/objects/frame-array.h",
"src/objects/hash-table-inl.h",
......
......@@ -5,7 +5,7 @@
#ifndef V8_CONTEXTS_H_
#define V8_CONTEXTS_H_
#include "src/objects.h"
#include "src/objects/fixed-array.h"
namespace v8 {
namespace internal {
......
......@@ -42,6 +42,7 @@ class BytecodeArray;
class CodeDataContainer;
class DeoptimizationData;
class HandlerTable;
class IncrementalMarking;
class JSArrayBuffer;
using v8::MemoryPressureLevel;
......
......@@ -7,7 +7,7 @@
#include <iosfwd>
#include "src/objects.h"
#include "src/objects/fixed-array.h"
namespace v8 {
namespace internal {
......
......@@ -34,6 +34,7 @@
#include "src/objects.h"
#include "src/objects/arguments-inl.h"
#include "src/objects/bigint.h"
#include "src/objects/fixed-array-inl.h"
#include "src/objects/hash-table-inl.h"
#include "src/objects/hash-table.h"
#include "src/objects/js-array-inl.h"
......@@ -77,15 +78,12 @@ int PropertyDetails::field_width_in_words() const {
TYPE_CHECKER(BigInt, BIGINT_TYPE)
TYPE_CHECKER(BreakPoint, TUPLE2_TYPE)
TYPE_CHECKER(BreakPointInfo, TUPLE2_TYPE)
TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
TYPE_CHECKER(CallHandlerInfo, TUPLE3_TYPE)
TYPE_CHECKER(Cell, CELL_TYPE)
TYPE_CHECKER(ConstantElementsPair, TUPLE2_TYPE)
TYPE_CHECKER(CoverageInfo, FIXED_ARRAY_TYPE)
TYPE_CHECKER(DescriptorArray, DESCRIPTOR_ARRAY_TYPE)
TYPE_CHECKER(FeedbackVector, FEEDBACK_VECTOR_TYPE)
TYPE_CHECKER(FixedArrayExact, FIXED_ARRAY_TYPE)
TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
TYPE_CHECKER(Foreign, FOREIGN_TYPE)
TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
TYPE_CHECKER(HashTable, HASH_TABLE_TYPE)
......@@ -126,7 +124,6 @@ TYPE_CHECKER(WasmMemoryObject, WASM_MEMORY_TYPE)
TYPE_CHECKER(WasmModuleObject, WASM_MODULE_TYPE)
TYPE_CHECKER(WasmTableObject, WASM_TABLE_TYPE)
TYPE_CHECKER(WeakCell, WEAK_CELL_TYPE)
TYPE_CHECKER(WeakFixedArray, FIXED_ARRAY_TYPE)
#define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype, size) \
TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE)
......@@ -548,21 +545,15 @@ CAST_ACCESSOR(AccessorInfo)
CAST_ACCESSOR(AccessorPair)
CAST_ACCESSOR(AllocationMemento)
CAST_ACCESSOR(AllocationSite)
CAST_ACCESSOR(ArrayList)
CAST_ACCESSOR(AsyncGeneratorRequest)
CAST_ACCESSOR(BigInt)
CAST_ACCESSOR(BoilerplateDescription)
CAST_ACCESSOR(ByteArray)
CAST_ACCESSOR(CallHandlerInfo)
CAST_ACCESSOR(Cell)
CAST_ACCESSOR(ConstantElementsPair)
CAST_ACCESSOR(ContextExtension)
CAST_ACCESSOR(DescriptorArray)
CAST_ACCESSOR(EnumCache)
CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(FixedArrayBase)
CAST_ACCESSOR(FixedDoubleArray)
CAST_ACCESSOR(FixedTypedArrayBase)
CAST_ACCESSOR(Foreign)
CAST_ACCESSOR(FunctionTemplateInfo)
CAST_ACCESSOR(GlobalDictionary)
......@@ -619,14 +610,12 @@ CAST_ACCESSOR(StringSet)
CAST_ACCESSOR(StringTable)
CAST_ACCESSOR(Struct)
CAST_ACCESSOR(TemplateInfo)
CAST_ACCESSOR(TemplateList)
CAST_ACCESSOR(TemplateMap)
CAST_ACCESSOR(TemplateObjectDescription)
CAST_ACCESSOR(Tuple2)
CAST_ACCESSOR(Tuple3)
CAST_ACCESSOR(TypeFeedbackInfo)
CAST_ACCESSOR(WeakCell)
CAST_ACCESSOR(WeakFixedArray)
CAST_ACCESSOR(WeakHashTable)
bool Object::HasValidElements() {
......@@ -1094,22 +1083,6 @@ inline Object* OrderedHashMap::ValueAt(int entry) {
ACCESSORS(JSReceiver, raw_properties_or_hash, Object, kPropertiesOrHashOffset)
Object** FixedArray::GetFirstElementAddress() {
return reinterpret_cast<Object**>(FIELD_ADDR(this, OffsetOfElementAt(0)));
}
bool FixedArray::ContainsOnlySmisOrHoles() {
Object* the_hole = GetHeap()->the_hole_value();
Object** current = GetFirstElementAddress();
for (int i = 0; i < length(); ++i) {
Object* candidate = *current++;
if (!candidate->IsSmi() && candidate != the_hole) return false;
}
return true;
}
FixedArrayBase* JSObject::elements() const {
Object* array = READ_FIELD(this, kElementsOffset);
return static_cast<FixedArrayBase*>(array);
......@@ -1696,57 +1669,12 @@ void Object::VerifyApiCallResultType() {
#endif // DEBUG
}
Object* FixedArray::get(int index) const {
SLOW_DCHECK(index >= 0 && index < this->length());
return RELAXED_READ_FIELD(this, kHeaderSize + index * kPointerSize);
}
Object* PropertyArray::get(int index) const {
DCHECK_GE(index, 0);
DCHECK_LE(index, this->length());
return RELAXED_READ_FIELD(this, kHeaderSize + index * kPointerSize);
}
Handle<Object> FixedArray::get(FixedArray* array, int index, Isolate* isolate) {
return handle(array->get(index), isolate);
}
template <class T>
MaybeHandle<T> FixedArray::GetValue(Isolate* isolate, int index) const {
Object* obj = get(index);
if (obj->IsUndefined(isolate)) return MaybeHandle<T>();
return Handle<T>(T::cast(obj), isolate);
}
template <class T>
Handle<T> FixedArray::GetValueChecked(Isolate* isolate, int index) const {
Object* obj = get(index);
CHECK(!obj->IsUndefined(isolate));
return Handle<T>(T::cast(obj), isolate);
}
bool FixedArray::is_the_hole(Isolate* isolate, int index) {
return get(index)->IsTheHole(isolate);
}
void FixedArray::set(int index, Smi* value) {
DCHECK_NE(map(), GetHeap()->fixed_cow_array_map());
DCHECK_LT(index, this->length());
DCHECK(reinterpret_cast<Object*>(value)->IsSmi());
int offset = kHeaderSize + index * kPointerSize;
RELAXED_WRITE_FIELD(this, offset, value);
}
void FixedArray::set(int index, Object* value) {
DCHECK_NE(GetHeap()->fixed_cow_array_map(), map());
DCHECK(IsFixedArray());
DCHECK_GE(index, 0);
DCHECK_LT(index, this->length());
int offset = kHeaderSize + index * kPointerSize;
RELAXED_WRITE_FIELD(this, offset, value);
WRITE_BARRIER(GetHeap(), this, offset, value);
}
void PropertyArray::set(int index, Object* value) {
DCHECK(IsPropertyArray());
DCHECK_GE(index, 0);
......@@ -1756,154 +1684,6 @@ void PropertyArray::set(int index, Object* value) {
WRITE_BARRIER(GetHeap(), this, offset, value);
}
double FixedDoubleArray::get_scalar(int index) {
DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
map() != GetHeap()->fixed_array_map());
DCHECK(index >= 0 && index < this->length());
DCHECK(!is_the_hole(index));
return READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
}
uint64_t FixedDoubleArray::get_representation(int index) {
DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
map() != GetHeap()->fixed_array_map());
DCHECK(index >= 0 && index < this->length());
int offset = kHeaderSize + index * kDoubleSize;
return READ_UINT64_FIELD(this, offset);
}
Handle<Object> FixedDoubleArray::get(FixedDoubleArray* array, int index,
Isolate* isolate) {
if (array->is_the_hole(index)) {
return isolate->factory()->the_hole_value();
} else {
return isolate->factory()->NewNumber(array->get_scalar(index));
}
}
void FixedDoubleArray::set(int index, double value) {
DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
map() != GetHeap()->fixed_array_map());
int offset = kHeaderSize + index * kDoubleSize;
if (std::isnan(value)) {
WRITE_DOUBLE_FIELD(this, offset, std::numeric_limits<double>::quiet_NaN());
} else {
WRITE_DOUBLE_FIELD(this, offset, value);
}
DCHECK(!is_the_hole(index));
}
void FixedDoubleArray::set_the_hole(Isolate* isolate, int index) {
set_the_hole(index);
}
void FixedDoubleArray::set_the_hole(int index) {
DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
map() != GetHeap()->fixed_array_map());
int offset = kHeaderSize + index * kDoubleSize;
WRITE_UINT64_FIELD(this, offset, kHoleNanInt64);
}
bool FixedDoubleArray::is_the_hole(Isolate* isolate, int index) {
return is_the_hole(index);
}
bool FixedDoubleArray::is_the_hole(int index) {
return get_representation(index) == kHoleNanInt64;
}
double* FixedDoubleArray::data_start() {
return reinterpret_cast<double*>(FIELD_ADDR(this, kHeaderSize));
}
void FixedDoubleArray::FillWithHoles(int from, int to) {
for (int i = from; i < to; i++) {
set_the_hole(i);
}
}
Object* WeakFixedArray::Get(int index) const {
Object* raw = FixedArray::cast(this)->get(index + kFirstIndex);
if (raw->IsSmi()) return raw;
DCHECK(raw->IsWeakCell());
return WeakCell::cast(raw)->value();
}
bool WeakFixedArray::IsEmptySlot(int index) const {
DCHECK(index < Length());
return Get(index)->IsSmi();
}
void WeakFixedArray::Clear(int index) {
FixedArray::cast(this)->set(index + kFirstIndex, Smi::kZero);
}
int WeakFixedArray::Length() const {
return FixedArray::cast(this)->length() - kFirstIndex;
}
int WeakFixedArray::last_used_index() const {
return Smi::ToInt(FixedArray::cast(this)->get(kLastUsedIndexIndex));
}
void WeakFixedArray::set_last_used_index(int index) {
FixedArray::cast(this)->set(kLastUsedIndexIndex, Smi::FromInt(index));
}
template <class T>
T* WeakFixedArray::Iterator::Next() {
if (list_ != nullptr) {
// Assert that list did not change during iteration.
DCHECK_EQ(last_used_index_, list_->last_used_index());
while (index_ < list_->Length()) {
Object* item = list_->Get(index_++);
if (item != Empty()) return T::cast(item);
}
list_ = nullptr;
}
return nullptr;
}
int ArrayList::Length() const {
if (FixedArray::cast(this)->length() == 0) return 0;
return Smi::ToInt(FixedArray::cast(this)->get(kLengthIndex));
}
void ArrayList::SetLength(int length) {
return FixedArray::cast(this)->set(kLengthIndex, Smi::FromInt(length));
}
Object* ArrayList::Get(int index) const {
return FixedArray::cast(this)->get(kFirstIndex + index);
}
Object** ArrayList::Slot(int index) {
return data_start() + kFirstIndex + index;
}
void ArrayList::Set(int index, Object* obj, WriteBarrierMode mode) {
FixedArray::cast(this)->set(kFirstIndex + index, obj, mode);
}
void ArrayList::Clear(int index, Object* undefined) {
DCHECK(undefined->IsUndefined(GetIsolate()));
FixedArray::cast(this)
->set(kFirstIndex + index, undefined, SKIP_WRITE_BARRIER);
}
int RegExpMatchInfo::NumberOfCaptureRegisters() {
DCHECK_GE(length(), kLastMatchOverhead);
Object* obj = get(kNumberOfCapturesIndex);
......@@ -1987,17 +1767,6 @@ bool HeapObject::NeedsRehashing() const {
}
}
void FixedArray::set(int index,
Object* value,
WriteBarrierMode mode) {
DCHECK_NE(map(), GetHeap()->fixed_cow_array_map());
DCHECK_GE(index, 0);
DCHECK_LT(index, this->length());
int offset = kHeaderSize + index * kPointerSize;
RELAXED_WRITE_FIELD(this, offset, value);
CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
}
void PropertyArray::set(int index, Object* value, WriteBarrierMode mode) {
DCHECK_GE(index, 0);
DCHECK_LT(index, this->length());
......@@ -2006,57 +1775,10 @@ void PropertyArray::set(int index, Object* value, WriteBarrierMode mode) {
CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
}
void FixedArray::NoWriteBarrierSet(FixedArray* array,
int index,
Object* value) {
DCHECK_NE(array->map(), array->GetHeap()->fixed_cow_array_map());
DCHECK_GE(index, 0);
DCHECK_LT(index, array->length());
DCHECK(!array->GetHeap()->InNewSpace(value));
RELAXED_WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
}
void FixedArray::set_undefined(int index) {
set_undefined(GetIsolate(), index);
}
void FixedArray::set_undefined(Isolate* isolate, int index) {
FixedArray::NoWriteBarrierSet(this, index,
isolate->heap()->undefined_value());
}
void FixedArray::set_null(int index) { set_null(GetIsolate(), index); }
void FixedArray::set_null(Isolate* isolate, int index) {
FixedArray::NoWriteBarrierSet(this, index, isolate->heap()->null_value());
}
void FixedArray::set_the_hole(int index) { set_the_hole(GetIsolate(), index); }
void FixedArray::set_the_hole(Isolate* isolate, int index) {
FixedArray::NoWriteBarrierSet(this, index, isolate->heap()->the_hole_value());
}
void FixedArray::FillWithHoles(int from, int to) {
Isolate* isolate = GetIsolate();
for (int i = from; i < to; i++) {
set_the_hole(isolate, i);
}
}
Object** FixedArray::data_start() {
return HeapObject::RawField(this, kHeaderSize);
}
Object** PropertyArray::data_start() {
return HeapObject::RawField(this, kHeaderSize);
}
Object** FixedArray::RawFieldOfElementAt(int index) {
return HeapObject::RawField(this, OffsetOfElementAt(index));
}
ACCESSORS(EnumCache, keys, FixedArray, kKeysOffset)
ACCESSORS(EnumCache, indices, FixedArray, kIndicesOffset)
......@@ -2534,50 +2256,6 @@ void NumberDictionary::set_requires_slow_elements() {
set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
}
template <class T>
PodArray<T>* PodArray<T>::cast(Object* object) {
SLOW_DCHECK(object->IsByteArray());
return reinterpret_cast<PodArray<T>*>(object);
}
template <class T>
const PodArray<T>* PodArray<T>::cast(const Object* object) {
SLOW_DCHECK(object->IsByteArray());
return reinterpret_cast<const PodArray<T>*>(object);
}
// static
template <class T>
Handle<PodArray<T>> PodArray<T>::New(Isolate* isolate, int length,
PretenureFlag pretenure) {
return Handle<PodArray<T>>::cast(
isolate->factory()->NewByteArray(length * sizeof(T), pretenure));
}
// static
template <class Traits>
STATIC_CONST_MEMBER_DEFINITION const InstanceType
FixedTypedArray<Traits>::kInstanceType;
template <class Traits>
FixedTypedArray<Traits>* FixedTypedArray<Traits>::cast(Object* object) {
SLOW_DCHECK(object->IsHeapObject() &&
HeapObject::cast(object)->map()->instance_type() ==
Traits::kInstanceType);
return reinterpret_cast<FixedTypedArray<Traits>*>(object);
}
template <class Traits>
const FixedTypedArray<Traits>*
FixedTypedArray<Traits>::cast(const Object* object) {
SLOW_DCHECK(object->IsHeapObject() &&
HeapObject::cast(object)->map()->instance_type() ==
Traits::kInstanceType);
return reinterpret_cast<FixedTypedArray<Traits>*>(object);
}
DEFINE_DEOPT_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray)
DEFINE_DEOPT_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi)
DEFINE_DEOPT_ELEMENT_ACCESSORS(LiteralArray, FixedArray)
......@@ -2604,10 +2282,6 @@ const HashTable<Derived, Shape>* HashTable<Derived, Shape>::cast(
return reinterpret_cast<const HashTable*>(obj);
}
SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
int PropertyArray::length() const {
Object* value_obj = READ_FIELD(this, kLengthAndHashOffset);
int value = Smi::ToInt(value_obj);
......@@ -2670,313 +2344,6 @@ FreeSpace* FreeSpace::cast(HeapObject* o) {
return reinterpret_cast<FreeSpace*>(o);
}
int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kPointerSize); }
byte ByteArray::get(int index) const {
DCHECK(index >= 0 && index < this->length());
return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
}
void ByteArray::set(int index, byte value) {
DCHECK(index >= 0 && index < this->length());
WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
}
void ByteArray::copy_in(int index, const byte* buffer, int length) {
DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
index + length <= this->length());
byte* dst_addr = FIELD_ADDR(this, kHeaderSize + index * kCharSize);
memcpy(dst_addr, buffer, length);
}
void ByteArray::copy_out(int index, byte* buffer, int length) {
DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
index + length <= this->length());
const byte* src_addr = FIELD_ADDR(this, kHeaderSize + index * kCharSize);
memcpy(buffer, src_addr, length);
}
int ByteArray::get_int(int index) const {
DCHECK(index >= 0 && index < this->length() / kIntSize);
return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
}
void ByteArray::set_int(int index, int value) {
DCHECK(index >= 0 && index < this->length() / kIntSize);
WRITE_INT_FIELD(this, kHeaderSize + index * kIntSize, value);
}
uint32_t ByteArray::get_uint32(int index) const {
DCHECK(index >= 0 && index < this->length() / kUInt32Size);
return READ_UINT32_FIELD(this, kHeaderSize + index * kUInt32Size);
}
void ByteArray::set_uint32(int index, uint32_t value) {
DCHECK(index >= 0 && index < this->length() / kUInt32Size);
WRITE_UINT32_FIELD(this, kHeaderSize + index * kUInt32Size, value);
}
void ByteArray::clear_padding() {
int data_size = length() + kHeaderSize;
memset(address() + data_size, 0, Size() - data_size);
}
ByteArray* ByteArray::FromDataStartAddress(Address address) {
DCHECK_TAG_ALIGNED(address);
return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
}
int ByteArray::DataSize() const { return RoundUp(length(), kPointerSize); }
int ByteArray::ByteArraySize() { return SizeFor(this->length()); }
Address ByteArray::GetDataStartAddress() {
return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
}
ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset)
void* FixedTypedArrayBase::external_pointer() const {
intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
return reinterpret_cast<void*>(ptr);
}
void FixedTypedArrayBase::set_external_pointer(void* value,
WriteBarrierMode mode) {
intptr_t ptr = reinterpret_cast<intptr_t>(value);
WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
}
void* FixedTypedArrayBase::DataPtr() {
return reinterpret_cast<void*>(
reinterpret_cast<intptr_t>(base_pointer()) +
reinterpret_cast<intptr_t>(external_pointer()));
}
int FixedTypedArrayBase::ElementSize(InstanceType type) {
int element_size;
switch (type) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
case FIXED_##TYPE##_ARRAY_TYPE: \
element_size = size; \
break;
TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
default:
UNREACHABLE();
}
return element_size;
}
int FixedTypedArrayBase::DataSize(InstanceType type) const {
if (base_pointer() == Smi::kZero) return 0;
return length() * ElementSize(type);
}
int FixedTypedArrayBase::DataSize() const {
return DataSize(map()->instance_type());
}
size_t FixedTypedArrayBase::ByteLength() const {
return static_cast<size_t>(length()) *
static_cast<size_t>(ElementSize(map()->instance_type()));
}
int FixedTypedArrayBase::size() const {
return OBJECT_POINTER_ALIGN(kDataOffset + DataSize());
}
int FixedTypedArrayBase::TypedArraySize(InstanceType type) const {
return OBJECT_POINTER_ALIGN(kDataOffset + DataSize(type));
}
// static
int FixedTypedArrayBase::TypedArraySize(InstanceType type, int length) {
return OBJECT_POINTER_ALIGN(kDataOffset + length * ElementSize(type));
}
uint8_t Uint8ArrayTraits::defaultValue() { return 0; }
uint8_t Uint8ClampedArrayTraits::defaultValue() { return 0; }
int8_t Int8ArrayTraits::defaultValue() { return 0; }
uint16_t Uint16ArrayTraits::defaultValue() { return 0; }
int16_t Int16ArrayTraits::defaultValue() { return 0; }
uint32_t Uint32ArrayTraits::defaultValue() { return 0; }
int32_t Int32ArrayTraits::defaultValue() { return 0; }
float Float32ArrayTraits::defaultValue() {
return std::numeric_limits<float>::quiet_NaN();
}
double Float64ArrayTraits::defaultValue() {
return std::numeric_limits<double>::quiet_NaN();
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
DCHECK((index >= 0) && (index < this->length()));
// The JavaScript memory model allows for racy reads and writes to a
// SharedArrayBuffer's backing store, which will always be a FixedTypedArray.
// ThreadSanitizer will catch these racy accesses and warn about them, so we
// disable TSAN for these reads and writes using annotations.
//
// We don't use relaxed atomics here, as it is not a requirement of the
// JavaScript memory model to have tear-free reads of overlapping accesses,
// and using relaxed atomics may introduce overhead.
auto* ptr = reinterpret_cast<ElementType*>(DataPtr());
TSAN_ANNOTATE_IGNORE_READS_BEGIN;
auto result = ptr[index];
TSAN_ANNOTATE_IGNORE_READS_END;
return result;
}
template <class Traits>
void FixedTypedArray<Traits>::set(int index, ElementType value) {
CHECK((index >= 0) && (index < this->length()));
// See the comment in FixedTypedArray<Traits>::get_scalar.
auto* ptr = reinterpret_cast<ElementType*>(DataPtr());
TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
ptr[index] = value;
TSAN_ANNOTATE_IGNORE_WRITES_END;
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::from(int value) {
return static_cast<ElementType>(value);
}
template <>
inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(int value) {
if (value < 0) return 0;
if (value > 0xFF) return 0xFF;
return static_cast<uint8_t>(value);
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::from(uint32_t value) {
return static_cast<ElementType>(value);
}
template <>
inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(uint32_t value) {
// We need this special case for Uint32 -> Uint8Clamped, because the highest
// Uint32 values will be negative as an int, clamping to 0, rather than 255.
if (value > 0xFF) return 0xFF;
return static_cast<uint8_t>(value);
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::from(double value) {
return static_cast<ElementType>(DoubleToInt32(value));
}
template <>
inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(double value) {
// Handle NaNs and less than zero values which clamp to zero.
if (!(value > 0)) return 0;
if (value > 0xFF) return 0xFF;
return static_cast<uint8_t>(lrint(value));
}
template <>
inline float FixedTypedArray<Float32ArrayTraits>::from(double value) {
return static_cast<float>(value);
}
template <>
inline double FixedTypedArray<Float64ArrayTraits>::from(double value) {
return value;
}
template <class Traits>
Handle<Object> FixedTypedArray<Traits>::get(FixedTypedArray<Traits>* array,
int index) {
return Traits::ToHandle(array->GetIsolate(), array->get_scalar(index));
}
template <class Traits>
void FixedTypedArray<Traits>::SetValue(uint32_t index, Object* value) {
ElementType cast_value = Traits::defaultValue();
if (value->IsSmi()) {
int int_value = Smi::ToInt(value);
cast_value = from(int_value);
} else if (value->IsHeapNumber()) {
double double_value = HeapNumber::cast(value)->value();
cast_value = from(double_value);
} else {
// Clamp undefined to the default value. All other types have been
// converted to a number type further up in the call chain.
DCHECK(value->IsUndefined(GetIsolate()));
}
set(index, cast_value);
}
Handle<Object> Uint8ArrayTraits::ToHandle(Isolate* isolate, uint8_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate,
uint8_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) {
return isolate->factory()->NewNumberFromUint(scalar);
}
Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) {
return isolate->factory()->NewNumberFromInt(scalar);
}
Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) {
return isolate->factory()->NewNumber(scalar);
}
Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) {
return isolate->factory()->NewNumber(scalar);
}
VisitorId Map::visitor_id() const {
return static_cast<VisitorId>(READ_BYTE_FIELD(this, kVisitorIdOffset));
......@@ -3953,18 +3320,6 @@ void ObjectTemplateInfo::set_immutable_proto(bool immutable) {
IsImmutablePrototype::update(Smi::ToInt(data()), immutable)));
}
int TemplateList::length() const {
return Smi::ToInt(FixedArray::cast(this)->get(kLengthIndex));
}
Object* TemplateList::get(int index) const {
return FixedArray::cast(this)->get(kFirstElementIndex + index);
}
void TemplateList::set(int index, Object* value) {
FixedArray::cast(this)->set(kFirstElementIndex + index, value);
}
ACCESSORS(AllocationSite, transition_info_or_boilerplate, Object,
kTransitionInfoOrBoilerplateOffset)
......
......@@ -857,55 +857,6 @@ STATIC_ASSERT(FOREIGN_TYPE == Internals::kForeignType);
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
InstanceType instance_type);
#define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \
V(BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE) \
V(BYTECODE_ARRAY_HANDLER_TABLE_SUB_TYPE) \
V(CODE_STUBS_TABLE_SUB_TYPE) \
V(COMPILATION_CACHE_TABLE_SUB_TYPE) \
V(CONTEXT_SUB_TYPE) \
V(COPY_ON_WRITE_SUB_TYPE) \
V(DEOPTIMIZATION_DATA_SUB_TYPE) \
V(DESCRIPTOR_ARRAY_SUB_TYPE) \
V(EMBEDDED_OBJECT_SUB_TYPE) \
V(ENUM_CACHE_SUB_TYPE) \
V(ENUM_INDICES_CACHE_SUB_TYPE) \
V(DEPENDENT_CODE_SUB_TYPE) \
V(DICTIONARY_ELEMENTS_SUB_TYPE) \
V(DICTIONARY_PROPERTIES_SUB_TYPE) \
V(EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE) \
V(PACKED_ELEMENTS_SUB_TYPE) \
V(FAST_PROPERTIES_SUB_TYPE) \
V(FAST_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \
V(HANDLER_TABLE_SUB_TYPE) \
V(JS_COLLECTION_SUB_TYPE) \
V(JS_WEAK_COLLECTION_SUB_TYPE) \
V(NOSCRIPT_SHARED_FUNCTION_INFOS_SUB_TYPE) \
V(NUMBER_STRING_CACHE_SUB_TYPE) \
V(OBJECT_TO_CODE_SUB_TYPE) \
V(OPTIMIZED_CODE_LITERALS_SUB_TYPE) \
V(OPTIMIZED_CODE_MAP_SUB_TYPE) \
V(PROTOTYPE_USERS_SUB_TYPE) \
V(REGEXP_MULTIPLE_CACHE_SUB_TYPE) \
V(RETAINED_MAPS_SUB_TYPE) \
V(SCOPE_INFO_SUB_TYPE) \
V(SCRIPT_LIST_SUB_TYPE) \
V(SERIALIZED_TEMPLATES_SUB_TYPE) \
V(SHARED_FUNCTION_INFOS_SUB_TYPE) \
V(SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE) \
V(SLOW_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \
V(STRING_SPLIT_CACHE_SUB_TYPE) \
V(STRING_TABLE_SUB_TYPE) \
V(TEMPLATE_INFO_SUB_TYPE) \
V(FEEDBACK_METADATA_SUB_TYPE) \
V(WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE)
enum FixedArraySubInstanceType {
#define DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE(name) name,
FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE)
#undef DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE
LAST_FIXED_ARRAY_SUB_TYPE = WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE
};
// Result of an abstract relational comparison of x and y, implemented according
// to ES6 section 7.2.11 Abstract Relational Comparison.
enum class ComparisonResult {
......@@ -921,6 +872,7 @@ bool ComparisonResultToBool(Operation op, ComparisonResult result);
class AbstractCode;
class AccessorPair;
class AllocationSite;
class ByteArray;
class Cell;
class ConsString;
class DependentCode;
......@@ -2798,414 +2750,6 @@ class JSIteratorResult: public JSObject {
DISALLOW_IMPLICIT_CONSTRUCTORS(JSIteratorResult);
};
// Common superclass for FixedArrays that allow implementations to share
// common accessors and some code paths.
class FixedArrayBase: public HeapObject {
public:
// [length]: length of the array.
inline int length() const;
inline void set_length(int value);
// Get and set the length using acquire loads and release stores.
inline int synchronized_length() const;
inline void synchronized_set_length(int value);
DECL_CAST(FixedArrayBase)
static int GetMaxLengthForNewSpaceAllocation(ElementsKind kind);
bool IsCowArray() const;
// Layout description.
// Length is smi tagged when it is stored.
static const int kLengthOffset = HeapObject::kHeaderSize;
static const int kHeaderSize = kLengthOffset + kPointerSize;
};
class FixedDoubleArray;
class IncrementalMarking;
// FixedArray describes fixed-sized arrays with element type Object*.
class FixedArray: public FixedArrayBase {
public:
// Setter and getter for elements.
inline Object* get(int index) const;
static inline Handle<Object> get(FixedArray* array, int index,
Isolate* isolate);
template <class T>
MaybeHandle<T> GetValue(Isolate* isolate, int index) const;
template <class T>
Handle<T> GetValueChecked(Isolate* isolate, int index) const;
// Return a grown copy if the index is bigger than the array's length.
static Handle<FixedArray> SetAndGrow(Handle<FixedArray> array, int index,
Handle<Object> value);
// Setter that uses write barrier.
inline void set(int index, Object* value);
inline bool is_the_hole(Isolate* isolate, int index);
// Setter that doesn't need write barrier.
inline void set(int index, Smi* value);
// Setter with explicit barrier mode.
inline void set(int index, Object* value, WriteBarrierMode mode);
// Setters for frequently used oddballs located in old space.
inline void set_undefined(int index);
inline void set_undefined(Isolate* isolate, int index);
inline void set_null(int index);
inline void set_null(Isolate* isolate, int index);
inline void set_the_hole(int index);
inline void set_the_hole(Isolate* isolate, int index);
inline Object** GetFirstElementAddress();
inline bool ContainsOnlySmisOrHoles();
// Gives access to raw memory which stores the array's data.
inline Object** data_start();
inline void FillWithHoles(int from, int to);
// Shrink length and insert filler objects.
void Shrink(int length);
// Copy a sub array from the receiver to dest.
void CopyTo(int pos, FixedArray* dest, int dest_pos, int len) const;
// Garbage collection support.
static constexpr int SizeFor(int length) {
return kHeaderSize + length * kPointerSize;
}
// Code Generation support.
static constexpr int OffsetOfElementAt(int index) { return SizeFor(index); }
// Garbage collection support.
inline Object** RawFieldOfElementAt(int index);
DECL_CAST(FixedArray)
// Maximal allowed size, in bytes, of a single FixedArray.
// Prevents overflowing size computations, as well as extreme memory
// consumption.
static const int kMaxSize = 128 * MB * kPointerSize;
// Maximally allowed length of a FixedArray.
static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
// Maximally allowed length for regular (non large object space) object.
STATIC_ASSERT(kMaxRegularHeapObjectSize < kMaxSize);
static const int kMaxRegularLength =
(kMaxRegularHeapObjectSize - kHeaderSize) / kPointerSize;
// Dispatched behavior.
DECL_PRINTER(FixedArray)
DECL_VERIFIER(FixedArray)
#ifdef DEBUG
// Checks if two FixedArrays have identical contents.
bool IsEqualTo(FixedArray* other);
#endif
typedef FlexibleBodyDescriptor<kHeaderSize> BodyDescriptor;
// No weak fields.
typedef BodyDescriptor BodyDescriptorWeak;
protected:
// Set operation on FixedArray without using write barriers. Can
// only be used for storing old space objects or smis.
static inline void NoWriteBarrierSet(FixedArray* array,
int index,
Object* value);
private:
STATIC_ASSERT(kHeaderSize == Internals::kFixedArrayHeaderSize);
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
};
// FixedArray alias added only because of IsFixedArrayExact() predicate, which
// checks for the exact instance type FIXED_ARRAY_TYPE instead of a range
// check: [FIRST_FIXED_ARRAY_TYPE, LAST_FIXED_ARRAY_TYPE].
class FixedArrayExact final : public FixedArray {
public:
DECL_CAST(FixedArrayExact)
};
// FixedDoubleArray describes fixed-sized arrays with element type double.
class FixedDoubleArray: public FixedArrayBase {
public:
// Setter and getter for elements.
inline double get_scalar(int index);
inline uint64_t get_representation(int index);
static inline Handle<Object> get(FixedDoubleArray* array, int index,
Isolate* isolate);
inline void set(int index, double value);
inline void set_the_hole(Isolate* isolate, int index);
inline void set_the_hole(int index);
// Checking for the hole.
inline bool is_the_hole(Isolate* isolate, int index);
inline bool is_the_hole(int index);
// Garbage collection support.
inline static int SizeFor(int length) {
return kHeaderSize + length * kDoubleSize;
}
// Gives access to raw memory which stores the array's data.
inline double* data_start();
inline void FillWithHoles(int from, int to);
// Code Generation support.
static int OffsetOfElementAt(int index) { return SizeFor(index); }
DECL_CAST(FixedDoubleArray)
// Maximal allowed size, in bytes, of a single FixedDoubleArray.
// Prevents overflowing size computations, as well as extreme memory
// consumption.
static const int kMaxSize = 512 * MB;
// Maximally allowed length of a FixedArray.
static const int kMaxLength = (kMaxSize - kHeaderSize) / kDoubleSize;
// Dispatched behavior.
DECL_PRINTER(FixedDoubleArray)
DECL_VERIFIER(FixedDoubleArray)
class BodyDescriptor;
// No weak fields.
typedef BodyDescriptor BodyDescriptorWeak;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedDoubleArray);
};
class WeakFixedArray : public FixedArray {
public:
// If |maybe_array| is not a WeakFixedArray, a fresh one will be allocated.
// This function does not check if the value exists already, callers must
// ensure this themselves if necessary.
static Handle<WeakFixedArray> Add(Handle<Object> maybe_array,
Handle<HeapObject> value,
int* assigned_index = nullptr);
// Returns true if an entry was found and removed.
bool Remove(Handle<HeapObject> value);
class NullCallback {
public:
static void Callback(Object* value, int old_index, int new_index) {}
};
template <class CompactionCallback>
void Compact();
inline Object* Get(int index) const;
inline void Clear(int index);
inline int Length() const;
inline bool IsEmptySlot(int index) const;
static Object* Empty() { return Smi::kZero; }
class Iterator {
public:
explicit Iterator(Object* maybe_array) : list_(nullptr) {
Reset(maybe_array);
}
void Reset(Object* maybe_array);
template <class T>
inline T* Next();
private:
int index_;
WeakFixedArray* list_;
#ifdef DEBUG
int last_used_index_;
DisallowHeapAllocation no_gc_;
#endif // DEBUG
DISALLOW_COPY_AND_ASSIGN(Iterator);
};
DECL_CAST(WeakFixedArray)
private:
static const int kLastUsedIndexIndex = 0;
static const int kFirstIndex = 1;
static Handle<WeakFixedArray> Allocate(
Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from);
static void Set(Handle<WeakFixedArray> array, int index,
Handle<HeapObject> value);
inline void clear(int index);
inline int last_used_index() const;
inline void set_last_used_index(int index);
// Disallow inherited setters.
void set(int index, Smi* value);
void set(int index, Object* value);
void set(int index, Object* value, WriteBarrierMode mode);
DISALLOW_IMPLICIT_CONSTRUCTORS(WeakFixedArray);
};
// Generic array grows dynamically with O(1) amortized insertion.
//
// ArrayList is a FixedArray with static convenience methods for adding more
// elements. The Length() method returns the number of elements in the list, not
// the allocated size. The number of elements is stored at kLengthIndex and is
// updated with every insertion. The elements of the ArrayList are stored in the
// underlying FixedArray starting at kFirstIndex.
class ArrayList : public FixedArray {
public:
enum AddMode {
kNone,
// Use this if GC can delete elements from the array.
kReloadLengthAfterAllocation,
};
static Handle<ArrayList> Add(Handle<ArrayList> array, Handle<Object> obj,
AddMode mode = kNone);
static Handle<ArrayList> Add(Handle<ArrayList> array, Handle<Object> obj1,
Handle<Object> obj2, AddMode = kNone);
static Handle<ArrayList> New(Isolate* isolate, int size);
// Returns the number of elements in the list, not the allocated size, which
// is length(). Lower and upper case length() return different results!
inline int Length() const;
// Sets the Length() as used by Elements(). Does not change the underlying
// storage capacity, i.e., length().
inline void SetLength(int length);
inline Object* Get(int index) const;
inline Object** Slot(int index);
// Set the element at index to obj. The underlying array must be large enough.
// If you need to grow the ArrayList, use the static Add() methods instead.
inline void Set(int index, Object* obj,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Set the element at index to undefined. This does not change the Length().
inline void Clear(int index, Object* undefined);
// Return a copy of the list of size Length() without the first entry. The
// number returned by Length() is stored in the first entry.
static Handle<FixedArray> Elements(Handle<ArrayList> array);
bool IsFull();
DECL_CAST(ArrayList)
private:
static Handle<ArrayList> EnsureSpace(Handle<ArrayList> array, int length);
static const int kLengthIndex = 0;
static const int kFirstIndex = 1;
DISALLOW_IMPLICIT_CONSTRUCTORS(ArrayList);
};
enum SearchMode { ALL_ENTRIES, VALID_ENTRIES };
template <SearchMode search_mode, typename T>
inline int Search(T* array, Name* name, int valid_entries = 0,
int* out_insertion_index = nullptr);
// ByteArray represents fixed sized byte arrays. Used for the relocation info
// that is attached to code objects.
class ByteArray: public FixedArrayBase {
public:
inline int Size();
// Setter and getter.
inline byte get(int index) const;
inline void set(int index, byte value);
// Copy in / copy out whole byte slices.
inline void copy_out(int index, byte* buffer, int length);
inline void copy_in(int index, const byte* buffer, int length);
// Treat contents as an int array.
inline int get_int(int index) const;
inline void set_int(int index, int value);
inline uint32_t get_uint32(int index) const;
inline void set_uint32(int index, uint32_t value);
// Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic.
inline void clear_padding();
static int SizeFor(int length) {
return OBJECT_POINTER_ALIGN(kHeaderSize + length);
}
// We use byte arrays for free blocks in the heap. Given a desired size in
// bytes that is a multiple of the word size and big enough to hold a byte
// array, this function returns the number of elements a byte array should
// have.
static int LengthFor(int size_in_bytes) {
DCHECK(IsAligned(size_in_bytes, kPointerSize));
DCHECK_GE(size_in_bytes, kHeaderSize);
return size_in_bytes - kHeaderSize;
}
// Returns data start address.
inline Address GetDataStartAddress();
inline int DataSize() const;
// Returns a pointer to the ByteArray object for a given data start address.
static inline ByteArray* FromDataStartAddress(Address address);
DECL_CAST(ByteArray)
// Dispatched behavior.
inline int ByteArraySize();
DECL_PRINTER(ByteArray)
DECL_VERIFIER(ByteArray)
// Layout description.
static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
// Maximal memory consumption for a single ByteArray.
static const int kMaxSize = 512 * MB;
// Maximal length of a single ByteArray.
static const int kMaxLength = kMaxSize - kHeaderSize;
class BodyDescriptor;
// No weak fields.
typedef BodyDescriptor BodyDescriptorWeak;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
};
// Wrapper class for ByteArray which can store arbitrary C++ classes, as long
// as they can be copied with memcpy.
template <class T>
class PodArray : public ByteArray {
public:
static Handle<PodArray<T>> New(Isolate* isolate, int length,
PretenureFlag pretenure = NOT_TENURED);
void copy_out(int index, T* result) {
ByteArray::copy_out(index * sizeof(T), reinterpret_cast<byte*>(result),
sizeof(T));
}
T get(int index) {
T result;
copy_out(index, &result);
return result;
}
void set(int index, const T& value) {
copy_in(index * sizeof(T), reinterpret_cast<const byte*>(&value),
sizeof(T));
}
int length() { return ByteArray::length() / sizeof(T); }
DECL_CAST(PodArray<T>)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PodArray<T>);
};
// FreeSpace are fixed-size free memory blocks used by the heap and GC.
// They look like heap objects (are heap object tagged and have a map) so that
// the heap remains iterable. They have a size and a next pointer.
......@@ -3242,136 +2786,6 @@ class FreeSpace: public HeapObject {
DISALLOW_IMPLICIT_CONSTRUCTORS(FreeSpace);
};
// V has parameters (Type, type, TYPE, C type, element_size)
#define TYPED_ARRAYS(V) \
V(Uint8, uint8, UINT8, uint8_t, 1) \
V(Int8, int8, INT8, int8_t, 1) \
V(Uint16, uint16, UINT16, uint16_t, 2) \
V(Int16, int16, INT16, int16_t, 2) \
V(Uint32, uint32, UINT32, uint32_t, 4) \
V(Int32, int32, INT32, int32_t, 4) \
V(Float32, float32, FLOAT32, float, 4) \
V(Float64, float64, FLOAT64, double, 8) \
V(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t, 1)
class FixedTypedArrayBase: public FixedArrayBase {
public:
// [base_pointer]: Either points to the FixedTypedArrayBase itself or nullptr.
DECL_ACCESSORS(base_pointer, Object)
// [external_pointer]: Contains the offset between base_pointer and the start
// of the data. If the base_pointer is a nullptr, the external_pointer
// therefore points to the actual backing store.
DECL_ACCESSORS(external_pointer, void)
// Dispatched behavior.
DECL_CAST(FixedTypedArrayBase)
static const int kBasePointerOffset = FixedArrayBase::kHeaderSize;
static const int kExternalPointerOffset = kBasePointerOffset + kPointerSize;
static const int kHeaderSize =
DOUBLE_POINTER_ALIGN(kExternalPointerOffset + kPointerSize);
static const int kDataOffset = kHeaderSize;
static const int kMaxElementSize = 8;
#ifdef V8_HOST_ARCH_32_BIT
static const size_t kMaxByteLength = std::numeric_limits<size_t>::max();
#else
static const size_t kMaxByteLength =
static_cast<size_t>(Smi::kMaxValue) * kMaxElementSize;
#endif // V8_HOST_ARCH_32_BIT
static const size_t kMaxLength = Smi::kMaxValue;
class BodyDescriptor;
// No weak fields.
typedef BodyDescriptor BodyDescriptorWeak;
inline int size() const;
static inline int TypedArraySize(InstanceType type, int length);
inline int TypedArraySize(InstanceType type) const;
// Use with care: returns raw pointer into heap.
inline void* DataPtr();
inline int DataSize() const;
inline size_t ByteLength() const;
private:
static inline int ElementSize(InstanceType type);
inline int DataSize(InstanceType type) const;
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArrayBase);
};
template <class Traits>
class FixedTypedArray: public FixedTypedArrayBase {
public:
typedef typename Traits::ElementType ElementType;
static const InstanceType kInstanceType = Traits::kInstanceType;
DECL_CAST(FixedTypedArray<Traits>)
inline ElementType get_scalar(int index);
static inline Handle<Object> get(FixedTypedArray* array, int index);
inline void set(int index, ElementType value);
static inline ElementType from(int value);
static inline ElementType from(uint32_t value);
static inline ElementType from(double value);
// This accessor applies the correct conversion from Smi, HeapNumber
// and undefined.
inline void SetValue(uint32_t index, Object* value);
DECL_PRINTER(FixedTypedArray)
DECL_VERIFIER(FixedTypedArray)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArray);
};
#define FIXED_TYPED_ARRAY_TRAITS(Type, type, TYPE, elementType, size) \
STATIC_ASSERT(size <= FixedTypedArrayBase::kMaxElementSize); \
class Type##ArrayTraits { \
public: /* NOLINT */ \
typedef elementType ElementType; \
static const InstanceType kInstanceType = FIXED_##TYPE##_ARRAY_TYPE; \
static const char* Designator() { return #type " array"; } \
static inline Handle<Object> ToHandle(Isolate* isolate, \
elementType scalar); \
static inline elementType defaultValue(); \
}; \
\
typedef FixedTypedArray<Type##ArrayTraits> Fixed##Type##Array;
TYPED_ARRAYS(FIXED_TYPED_ARRAY_TRAITS)
#undef FIXED_TYPED_ARRAY_TRAITS
class TemplateList : public FixedArray {
public:
static Handle<TemplateList> New(Isolate* isolate, int size);
inline int length() const;
inline Object* get(int index) const;
inline void set(int index, Object* value);
static Handle<TemplateList> Add(Isolate* isolate, Handle<TemplateList> list,
Handle<Object> value);
DECL_CAST(TemplateList)
private:
static const int kLengthIndex = 0;
static const int kFirstElementIndex = kLengthIndex + 1;
DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateList);
};
class PrototypeInfo;
// An abstract superclass, a marker class really, for simple structure classes.
......
......@@ -6,6 +6,7 @@
#define V8_OBJECTS_CODE_H_
#include "src/objects.h"
#include "src/objects/fixed-array.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
......
......@@ -6,6 +6,7 @@
#define V8_OBJECTS_DEBUG_OBJECTS_H_
#include "src/objects.h"
#include "src/objects/fixed-array.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
......
......@@ -6,6 +6,7 @@
#define V8_OBJECTS_DESCRIPTOR_ARRAY_H_
#include "src/objects.h"
#include "src/objects/fixed-array.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_OBJECTS_FIXED_ARRAY_INL_H_
#define V8_OBJECTS_FIXED_ARRAY_INL_H_
#include "src/objects.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
TYPE_CHECKER(FixedArrayExact, FIXED_ARRAY_TYPE)
TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
TYPE_CHECKER(WeakFixedArray, FIXED_ARRAY_TYPE)
CAST_ACCESSOR(ArrayList)
CAST_ACCESSOR(ByteArray)
CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(FixedArrayBase)
CAST_ACCESSOR(FixedDoubleArray)
CAST_ACCESSOR(FixedTypedArrayBase)
CAST_ACCESSOR(TemplateList)
CAST_ACCESSOR(WeakFixedArray)
SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset)
Object** FixedArray::GetFirstElementAddress() {
return reinterpret_cast<Object**>(FIELD_ADDR(this, OffsetOfElementAt(0)));
}
bool FixedArray::ContainsOnlySmisOrHoles() {
Object* the_hole = GetHeap()->the_hole_value();
Object** current = GetFirstElementAddress();
for (int i = 0; i < length(); ++i) {
Object* candidate = *current++;
if (!candidate->IsSmi() && candidate != the_hole) return false;
}
return true;
}
Object* FixedArray::get(int index) const {
SLOW_DCHECK(index >= 0 && index < this->length());
return RELAXED_READ_FIELD(this, kHeaderSize + index * kPointerSize);
}
Handle<Object> FixedArray::get(FixedArray* array, int index, Isolate* isolate) {
return handle(array->get(index), isolate);
}
template <class T>
MaybeHandle<T> FixedArray::GetValue(Isolate* isolate, int index) const {
Object* obj = get(index);
if (obj->IsUndefined(isolate)) return MaybeHandle<T>();
return Handle<T>(T::cast(obj), isolate);
}
template <class T>
Handle<T> FixedArray::GetValueChecked(Isolate* isolate, int index) const {
Object* obj = get(index);
CHECK(!obj->IsUndefined(isolate));
return Handle<T>(T::cast(obj), isolate);
}
bool FixedArray::is_the_hole(Isolate* isolate, int index) {
return get(index)->IsTheHole(isolate);
}
void FixedArray::set(int index, Smi* value) {
DCHECK_NE(map(), GetHeap()->fixed_cow_array_map());
DCHECK_LT(index, this->length());
DCHECK(reinterpret_cast<Object*>(value)->IsSmi());
int offset = kHeaderSize + index * kPointerSize;
RELAXED_WRITE_FIELD(this, offset, value);
}
void FixedArray::set(int index, Object* value) {
DCHECK_NE(GetHeap()->fixed_cow_array_map(), map());
DCHECK(IsFixedArray());
DCHECK_GE(index, 0);
DCHECK_LT(index, this->length());
int offset = kHeaderSize + index * kPointerSize;
RELAXED_WRITE_FIELD(this, offset, value);
WRITE_BARRIER(GetHeap(), this, offset, value);
}
void FixedArray::set(int index, Object* value, WriteBarrierMode mode) {
DCHECK_NE(map(), GetHeap()->fixed_cow_array_map());
DCHECK_GE(index, 0);
DCHECK_LT(index, this->length());
int offset = kHeaderSize + index * kPointerSize;
RELAXED_WRITE_FIELD(this, offset, value);
CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
}
void FixedArray::NoWriteBarrierSet(FixedArray* array, int index,
Object* value) {
DCHECK_NE(array->map(), array->GetHeap()->fixed_cow_array_map());
DCHECK_GE(index, 0);
DCHECK_LT(index, array->length());
DCHECK(!array->GetHeap()->InNewSpace(value));
RELAXED_WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
}
void FixedArray::set_undefined(int index) {
set_undefined(GetIsolate(), index);
}
void FixedArray::set_undefined(Isolate* isolate, int index) {
FixedArray::NoWriteBarrierSet(this, index,
isolate->heap()->undefined_value());
}
void FixedArray::set_null(int index) { set_null(GetIsolate(), index); }
void FixedArray::set_null(Isolate* isolate, int index) {
FixedArray::NoWriteBarrierSet(this, index, isolate->heap()->null_value());
}
void FixedArray::set_the_hole(int index) { set_the_hole(GetIsolate(), index); }
void FixedArray::set_the_hole(Isolate* isolate, int index) {
FixedArray::NoWriteBarrierSet(this, index, isolate->heap()->the_hole_value());
}
void FixedArray::FillWithHoles(int from, int to) {
Isolate* isolate = GetIsolate();
for (int i = from; i < to; i++) {
set_the_hole(isolate, i);
}
}
Object** FixedArray::data_start() {
return HeapObject::RawField(this, kHeaderSize);
}
Object** FixedArray::RawFieldOfElementAt(int index) {
return HeapObject::RawField(this, OffsetOfElementAt(index));
}
double FixedDoubleArray::get_scalar(int index) {
DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
map() != GetHeap()->fixed_array_map());
DCHECK(index >= 0 && index < this->length());
DCHECK(!is_the_hole(index));
return READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
}
uint64_t FixedDoubleArray::get_representation(int index) {
DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
map() != GetHeap()->fixed_array_map());
DCHECK(index >= 0 && index < this->length());
int offset = kHeaderSize + index * kDoubleSize;
return READ_UINT64_FIELD(this, offset);
}
Handle<Object> FixedDoubleArray::get(FixedDoubleArray* array, int index,
Isolate* isolate) {
if (array->is_the_hole(index)) {
return isolate->factory()->the_hole_value();
} else {
return isolate->factory()->NewNumber(array->get_scalar(index));
}
}
void FixedDoubleArray::set(int index, double value) {
DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
map() != GetHeap()->fixed_array_map());
int offset = kHeaderSize + index * kDoubleSize;
if (std::isnan(value)) {
WRITE_DOUBLE_FIELD(this, offset, std::numeric_limits<double>::quiet_NaN());
} else {
WRITE_DOUBLE_FIELD(this, offset, value);
}
DCHECK(!is_the_hole(index));
}
void FixedDoubleArray::set_the_hole(Isolate* isolate, int index) {
set_the_hole(index);
}
void FixedDoubleArray::set_the_hole(int index) {
DCHECK(map() != GetHeap()->fixed_cow_array_map() &&
map() != GetHeap()->fixed_array_map());
int offset = kHeaderSize + index * kDoubleSize;
WRITE_UINT64_FIELD(this, offset, kHoleNanInt64);
}
bool FixedDoubleArray::is_the_hole(Isolate* isolate, int index) {
return is_the_hole(index);
}
bool FixedDoubleArray::is_the_hole(int index) {
return get_representation(index) == kHoleNanInt64;
}
double* FixedDoubleArray::data_start() {
return reinterpret_cast<double*>(FIELD_ADDR(this, kHeaderSize));
}
void FixedDoubleArray::FillWithHoles(int from, int to) {
for (int i = from; i < to; i++) {
set_the_hole(i);
}
}
Object* WeakFixedArray::Get(int index) const {
Object* raw = FixedArray::cast(this)->get(index + kFirstIndex);
if (raw->IsSmi()) return raw;
DCHECK(raw->IsWeakCell());
return WeakCell::cast(raw)->value();
}
bool WeakFixedArray::IsEmptySlot(int index) const {
DCHECK(index < Length());
return Get(index)->IsSmi();
}
void WeakFixedArray::Clear(int index) {
FixedArray::cast(this)->set(index + kFirstIndex, Smi::kZero);
}
int WeakFixedArray::Length() const {
return FixedArray::cast(this)->length() - kFirstIndex;
}
int WeakFixedArray::last_used_index() const {
return Smi::ToInt(FixedArray::cast(this)->get(kLastUsedIndexIndex));
}
void WeakFixedArray::set_last_used_index(int index) {
FixedArray::cast(this)->set(kLastUsedIndexIndex, Smi::FromInt(index));
}
template <class T>
T* WeakFixedArray::Iterator::Next() {
if (list_ != nullptr) {
// Assert that list did not change during iteration.
DCHECK_EQ(last_used_index_, list_->last_used_index());
while (index_ < list_->Length()) {
Object* item = list_->Get(index_++);
if (item != Empty()) return T::cast(item);
}
list_ = nullptr;
}
return nullptr;
}
int ArrayList::Length() const {
if (FixedArray::cast(this)->length() == 0) return 0;
return Smi::ToInt(FixedArray::cast(this)->get(kLengthIndex));
}
void ArrayList::SetLength(int length) {
return FixedArray::cast(this)->set(kLengthIndex, Smi::FromInt(length));
}
Object* ArrayList::Get(int index) const {
return FixedArray::cast(this)->get(kFirstIndex + index);
}
Object** ArrayList::Slot(int index) {
return data_start() + kFirstIndex + index;
}
void ArrayList::Set(int index, Object* obj, WriteBarrierMode mode) {
FixedArray::cast(this)->set(kFirstIndex + index, obj, mode);
}
void ArrayList::Clear(int index, Object* undefined) {
DCHECK(undefined->IsUndefined(GetIsolate()));
FixedArray::cast(this)->set(kFirstIndex + index, undefined,
SKIP_WRITE_BARRIER);
}
int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kPointerSize); }
byte ByteArray::get(int index) const {
DCHECK(index >= 0 && index < this->length());
return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
}
void ByteArray::set(int index, byte value) {
DCHECK(index >= 0 && index < this->length());
WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
}
void ByteArray::copy_in(int index, const byte* buffer, int length) {
DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
index + length <= this->length());
byte* dst_addr = FIELD_ADDR(this, kHeaderSize + index * kCharSize);
memcpy(dst_addr, buffer, length);
}
void ByteArray::copy_out(int index, byte* buffer, int length) {
DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
index + length <= this->length());
const byte* src_addr = FIELD_ADDR(this, kHeaderSize + index * kCharSize);
memcpy(buffer, src_addr, length);
}
int ByteArray::get_int(int index) const {
DCHECK(index >= 0 && index < this->length() / kIntSize);
return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
}
void ByteArray::set_int(int index, int value) {
DCHECK(index >= 0 && index < this->length() / kIntSize);
WRITE_INT_FIELD(this, kHeaderSize + index * kIntSize, value);
}
uint32_t ByteArray::get_uint32(int index) const {
DCHECK(index >= 0 && index < this->length() / kUInt32Size);
return READ_UINT32_FIELD(this, kHeaderSize + index * kUInt32Size);
}
void ByteArray::set_uint32(int index, uint32_t value) {
DCHECK(index >= 0 && index < this->length() / kUInt32Size);
WRITE_UINT32_FIELD(this, kHeaderSize + index * kUInt32Size, value);
}
void ByteArray::clear_padding() {
int data_size = length() + kHeaderSize;
memset(address() + data_size, 0, Size() - data_size);
}
ByteArray* ByteArray::FromDataStartAddress(Address address) {
DCHECK_TAG_ALIGNED(address);
return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
}
int ByteArray::DataSize() const { return RoundUp(length(), kPointerSize); }
int ByteArray::ByteArraySize() { return SizeFor(this->length()); }
Address ByteArray::GetDataStartAddress() {
return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
}
template <class T>
PodArray<T>* PodArray<T>::cast(Object* object) {
SLOW_DCHECK(object->IsByteArray());
return reinterpret_cast<PodArray<T>*>(object);
}
template <class T>
const PodArray<T>* PodArray<T>::cast(const Object* object) {
SLOW_DCHECK(object->IsByteArray());
return reinterpret_cast<const PodArray<T>*>(object);
}
// static
template <class T>
Handle<PodArray<T>> PodArray<T>::New(Isolate* isolate, int length,
PretenureFlag pretenure) {
return Handle<PodArray<T>>::cast(
isolate->factory()->NewByteArray(length * sizeof(T), pretenure));
}
void* FixedTypedArrayBase::external_pointer() const {
intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
return reinterpret_cast<void*>(ptr);
}
void FixedTypedArrayBase::set_external_pointer(void* value,
WriteBarrierMode mode) {
intptr_t ptr = reinterpret_cast<intptr_t>(value);
WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
}
void* FixedTypedArrayBase::DataPtr() {
return reinterpret_cast<void*>(
reinterpret_cast<intptr_t>(base_pointer()) +
reinterpret_cast<intptr_t>(external_pointer()));
}
int FixedTypedArrayBase::ElementSize(InstanceType type) {
int element_size;
switch (type) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
case FIXED_##TYPE##_ARRAY_TYPE: \
element_size = size; \
break;
TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
default:
UNREACHABLE();
}
return element_size;
}
int FixedTypedArrayBase::DataSize(InstanceType type) const {
if (base_pointer() == Smi::kZero) return 0;
return length() * ElementSize(type);
}
int FixedTypedArrayBase::DataSize() const {
return DataSize(map()->instance_type());
}
size_t FixedTypedArrayBase::ByteLength() const {
return static_cast<size_t>(length()) *
static_cast<size_t>(ElementSize(map()->instance_type()));
}
int FixedTypedArrayBase::size() const {
return OBJECT_POINTER_ALIGN(kDataOffset + DataSize());
}
int FixedTypedArrayBase::TypedArraySize(InstanceType type) const {
return OBJECT_POINTER_ALIGN(kDataOffset + DataSize(type));
}
// static
int FixedTypedArrayBase::TypedArraySize(InstanceType type, int length) {
return OBJECT_POINTER_ALIGN(kDataOffset + length * ElementSize(type));
}
uint8_t Uint8ArrayTraits::defaultValue() { return 0; }
uint8_t Uint8ClampedArrayTraits::defaultValue() { return 0; }
int8_t Int8ArrayTraits::defaultValue() { return 0; }
uint16_t Uint16ArrayTraits::defaultValue() { return 0; }
int16_t Int16ArrayTraits::defaultValue() { return 0; }
uint32_t Uint32ArrayTraits::defaultValue() { return 0; }
int32_t Int32ArrayTraits::defaultValue() { return 0; }
float Float32ArrayTraits::defaultValue() {
return std::numeric_limits<float>::quiet_NaN();
}
double Float64ArrayTraits::defaultValue() {
return std::numeric_limits<double>::quiet_NaN();
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
DCHECK((index >= 0) && (index < this->length()));
// The JavaScript memory model allows for racy reads and writes to a
// SharedArrayBuffer's backing store, which will always be a FixedTypedArray.
// ThreadSanitizer will catch these racy accesses and warn about them, so we
// disable TSAN for these reads and writes using annotations.
//
// We don't use relaxed atomics here, as it is not a requirement of the
// JavaScript memory model to have tear-free reads of overlapping accesses,
// and using relaxed atomics may introduce overhead.
auto* ptr = reinterpret_cast<ElementType*>(DataPtr());
TSAN_ANNOTATE_IGNORE_READS_BEGIN;
auto result = ptr[index];
TSAN_ANNOTATE_IGNORE_READS_END;
return result;
}
template <class Traits>
void FixedTypedArray<Traits>::set(int index, ElementType value) {
CHECK((index >= 0) && (index < this->length()));
// See the comment in FixedTypedArray<Traits>::get_scalar.
auto* ptr = reinterpret_cast<ElementType*>(DataPtr());
TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
ptr[index] = value;
TSAN_ANNOTATE_IGNORE_WRITES_END;
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::from(int value) {
return static_cast<ElementType>(value);
}
template <>
inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(int value) {
if (value < 0) return 0;
if (value > 0xFF) return 0xFF;
return static_cast<uint8_t>(value);
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::from(uint32_t value) {
return static_cast<ElementType>(value);
}
template <>
inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(uint32_t value) {
// We need this special case for Uint32 -> Uint8Clamped, because the highest
// Uint32 values will be negative as an int, clamping to 0, rather than 255.
if (value > 0xFF) return 0xFF;
return static_cast<uint8_t>(value);
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::from(double value) {
return static_cast<ElementType>(DoubleToInt32(value));
}
template <>
inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(double value) {
// Handle NaNs and less than zero values which clamp to zero.
if (!(value > 0)) return 0;
if (value > 0xFF) return 0xFF;
return static_cast<uint8_t>(lrint(value));
}
template <>
inline float FixedTypedArray<Float32ArrayTraits>::from(double value) {
return static_cast<float>(value);
}
template <>
inline double FixedTypedArray<Float64ArrayTraits>::from(double value) {
return value;
}
template <class Traits>
Handle<Object> FixedTypedArray<Traits>::get(FixedTypedArray<Traits>* array,
int index) {
return Traits::ToHandle(array->GetIsolate(), array->get_scalar(index));
}
template <class Traits>
void FixedTypedArray<Traits>::SetValue(uint32_t index, Object* value) {
ElementType cast_value = Traits::defaultValue();
if (value->IsSmi()) {
int int_value = Smi::ToInt(value);
cast_value = from(int_value);
} else if (value->IsHeapNumber()) {
double double_value = HeapNumber::cast(value)->value();
cast_value = from(double_value);
} else {
// Clamp undefined to the default value. All other types have been
// converted to a number type further up in the call chain.
DCHECK(value->IsUndefined(GetIsolate()));
}
set(index, cast_value);
}
Handle<Object> Uint8ArrayTraits::ToHandle(Isolate* isolate, uint8_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate,
uint8_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) {
return handle(Smi::FromInt(scalar), isolate);
}
Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) {
return isolate->factory()->NewNumberFromUint(scalar);
}
Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) {
return isolate->factory()->NewNumberFromInt(scalar);
}
Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) {
return isolate->factory()->NewNumber(scalar);
}
Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) {
return isolate->factory()->NewNumber(scalar);
}
// static
template <class Traits>
STATIC_CONST_MEMBER_DEFINITION const InstanceType
FixedTypedArray<Traits>::kInstanceType;
template <class Traits>
FixedTypedArray<Traits>* FixedTypedArray<Traits>::cast(Object* object) {
SLOW_DCHECK(object->IsHeapObject() &&
HeapObject::cast(object)->map()->instance_type() ==
Traits::kInstanceType);
return reinterpret_cast<FixedTypedArray<Traits>*>(object);
}
template <class Traits>
const FixedTypedArray<Traits>* FixedTypedArray<Traits>::cast(
const Object* object) {
SLOW_DCHECK(object->IsHeapObject() &&
HeapObject::cast(object)->map()->instance_type() ==
Traits::kInstanceType);
return reinterpret_cast<FixedTypedArray<Traits>*>(object);
}
int TemplateList::length() const {
return Smi::ToInt(FixedArray::cast(this)->get(kLengthIndex));
}
Object* TemplateList::get(int index) const {
return FixedArray::cast(this)->get(kFirstElementIndex + index);
}
void TemplateList::set(int index, Object* value) {
FixedArray::cast(this)->set(kFirstElementIndex + index, value);
}
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_FIXED_ARRAY_INL_H_
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_OBJECTS_FIXED_ARRAY_H_
#define V8_OBJECTS_FIXED_ARRAY_H_
#include "src/objects.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
#define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \
V(BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE) \
V(BYTECODE_ARRAY_HANDLER_TABLE_SUB_TYPE) \
V(CODE_STUBS_TABLE_SUB_TYPE) \
V(COMPILATION_CACHE_TABLE_SUB_TYPE) \
V(CONTEXT_SUB_TYPE) \
V(COPY_ON_WRITE_SUB_TYPE) \
V(DEOPTIMIZATION_DATA_SUB_TYPE) \
V(DESCRIPTOR_ARRAY_SUB_TYPE) \
V(EMBEDDED_OBJECT_SUB_TYPE) \
V(ENUM_CACHE_SUB_TYPE) \
V(ENUM_INDICES_CACHE_SUB_TYPE) \
V(DEPENDENT_CODE_SUB_TYPE) \
V(DICTIONARY_ELEMENTS_SUB_TYPE) \
V(DICTIONARY_PROPERTIES_SUB_TYPE) \
V(EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE) \
V(PACKED_ELEMENTS_SUB_TYPE) \
V(FAST_PROPERTIES_SUB_TYPE) \
V(FAST_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \
V(HANDLER_TABLE_SUB_TYPE) \
V(JS_COLLECTION_SUB_TYPE) \
V(JS_WEAK_COLLECTION_SUB_TYPE) \
V(NOSCRIPT_SHARED_FUNCTION_INFOS_SUB_TYPE) \
V(NUMBER_STRING_CACHE_SUB_TYPE) \
V(OBJECT_TO_CODE_SUB_TYPE) \
V(OPTIMIZED_CODE_LITERALS_SUB_TYPE) \
V(OPTIMIZED_CODE_MAP_SUB_TYPE) \
V(PROTOTYPE_USERS_SUB_TYPE) \
V(REGEXP_MULTIPLE_CACHE_SUB_TYPE) \
V(RETAINED_MAPS_SUB_TYPE) \
V(SCOPE_INFO_SUB_TYPE) \
V(SCRIPT_LIST_SUB_TYPE) \
V(SERIALIZED_TEMPLATES_SUB_TYPE) \
V(SHARED_FUNCTION_INFOS_SUB_TYPE) \
V(SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE) \
V(SLOW_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \
V(STRING_SPLIT_CACHE_SUB_TYPE) \
V(STRING_TABLE_SUB_TYPE) \
V(TEMPLATE_INFO_SUB_TYPE) \
V(FEEDBACK_METADATA_SUB_TYPE) \
V(WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE)
enum FixedArraySubInstanceType {
#define DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE(name) name,
FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE)
#undef DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE
LAST_FIXED_ARRAY_SUB_TYPE = WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE
};
// Common superclass for FixedArrays that allow implementations to share
// common accessors and some code paths.
class FixedArrayBase : public HeapObject {
public:
// [length]: length of the array.
inline int length() const;
inline void set_length(int value);
// Get and set the length using acquire loads and release stores.
inline int synchronized_length() const;
inline void synchronized_set_length(int value);
DECL_CAST(FixedArrayBase)
static int GetMaxLengthForNewSpaceAllocation(ElementsKind kind);
bool IsCowArray() const;
// Layout description.
// Length is smi tagged when it is stored.
static const int kLengthOffset = HeapObject::kHeaderSize;
static const int kHeaderSize = kLengthOffset + kPointerSize;
};
// FixedArray describes fixed-sized arrays with element type Object*.
class FixedArray : public FixedArrayBase {
public:
// Setter and getter for elements.
inline Object* get(int index) const;
static inline Handle<Object> get(FixedArray* array, int index,
Isolate* isolate);
template <class T>
MaybeHandle<T> GetValue(Isolate* isolate, int index) const;
template <class T>
Handle<T> GetValueChecked(Isolate* isolate, int index) const;
// Return a grown copy if the index is bigger than the array's length.
static Handle<FixedArray> SetAndGrow(Handle<FixedArray> array, int index,
Handle<Object> value);
// Setter that uses write barrier.
inline void set(int index, Object* value);
inline bool is_the_hole(Isolate* isolate, int index);
// Setter that doesn't need write barrier.
inline void set(int index, Smi* value);
// Setter with explicit barrier mode.
inline void set(int index, Object* value, WriteBarrierMode mode);
// Setters for frequently used oddballs located in old space.
inline void set_undefined(int index);
inline void set_undefined(Isolate* isolate, int index);
inline void set_null(int index);
inline void set_null(Isolate* isolate, int index);
inline void set_the_hole(int index);
inline void set_the_hole(Isolate* isolate, int index);
inline Object** GetFirstElementAddress();
inline bool ContainsOnlySmisOrHoles();
// Gives access to raw memory which stores the array's data.
inline Object** data_start();
inline void FillWithHoles(int from, int to);
// Shrink length and insert filler objects.
void Shrink(int length);
// Copy a sub array from the receiver to dest.
void CopyTo(int pos, FixedArray* dest, int dest_pos, int len) const;
// Garbage collection support.
static constexpr int SizeFor(int length) {
return kHeaderSize + length * kPointerSize;
}
// Code Generation support.
static constexpr int OffsetOfElementAt(int index) { return SizeFor(index); }
// Garbage collection support.
inline Object** RawFieldOfElementAt(int index);
DECL_CAST(FixedArray)
// Maximal allowed size, in bytes, of a single FixedArray.
// Prevents overflowing size computations, as well as extreme memory
// consumption.
static const int kMaxSize = 128 * MB * kPointerSize;
// Maximally allowed length of a FixedArray.
static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
// Maximally allowed length for regular (non large object space) object.
STATIC_ASSERT(kMaxRegularHeapObjectSize < kMaxSize);
static const int kMaxRegularLength =
(kMaxRegularHeapObjectSize - kHeaderSize) / kPointerSize;
// Dispatched behavior.
DECL_PRINTER(FixedArray)
DECL_VERIFIER(FixedArray)
#ifdef DEBUG
// Checks if two FixedArrays have identical contents.
bool IsEqualTo(FixedArray* other);
#endif
typedef FlexibleBodyDescriptor<kHeaderSize> BodyDescriptor;
// No weak fields.
typedef BodyDescriptor BodyDescriptorWeak;
protected:
// Set operation on FixedArray without using write barriers. Can
// only be used for storing old space objects or smis.
static inline void NoWriteBarrierSet(FixedArray* array, int index,
Object* value);
private:
STATIC_ASSERT(kHeaderSize == Internals::kFixedArrayHeaderSize);
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
};
// FixedArray alias added only because of IsFixedArrayExact() predicate, which
// checks for the exact instance type FIXED_ARRAY_TYPE instead of a range
// check: [FIRST_FIXED_ARRAY_TYPE, LAST_FIXED_ARRAY_TYPE].
class FixedArrayExact final : public FixedArray {
public:
DECL_CAST(FixedArrayExact)
};
// FixedDoubleArray describes fixed-sized arrays with element type double.
class FixedDoubleArray : public FixedArrayBase {
public:
// Setter and getter for elements.
inline double get_scalar(int index);
inline uint64_t get_representation(int index);
static inline Handle<Object> get(FixedDoubleArray* array, int index,
Isolate* isolate);
inline void set(int index, double value);
inline void set_the_hole(Isolate* isolate, int index);
inline void set_the_hole(int index);
// Checking for the hole.
inline bool is_the_hole(Isolate* isolate, int index);
inline bool is_the_hole(int index);
// Garbage collection support.
inline static int SizeFor(int length) {
return kHeaderSize + length * kDoubleSize;
}
// Gives access to raw memory which stores the array's data.
inline double* data_start();
inline void FillWithHoles(int from, int to);
// Code Generation support.
static int OffsetOfElementAt(int index) { return SizeFor(index); }
DECL_CAST(FixedDoubleArray)
// Maximal allowed size, in bytes, of a single FixedDoubleArray.
// Prevents overflowing size computations, as well as extreme memory
// consumption.
static const int kMaxSize = 512 * MB;
// Maximally allowed length of a FixedArray.
static const int kMaxLength = (kMaxSize - kHeaderSize) / kDoubleSize;
// Dispatched behavior.
DECL_PRINTER(FixedDoubleArray)
DECL_VERIFIER(FixedDoubleArray)
class BodyDescriptor;
// No weak fields.
typedef BodyDescriptor BodyDescriptorWeak;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedDoubleArray);
};
class WeakFixedArray : public FixedArray {
public:
// If |maybe_array| is not a WeakFixedArray, a fresh one will be allocated.
// This function does not check if the value exists already, callers must
// ensure this themselves if necessary.
static Handle<WeakFixedArray> Add(Handle<Object> maybe_array,
Handle<HeapObject> value,
int* assigned_index = nullptr);
// Returns true if an entry was found and removed.
bool Remove(Handle<HeapObject> value);
class NullCallback {
public:
static void Callback(Object* value, int old_index, int new_index) {}
};
template <class CompactionCallback>
void Compact();
inline Object* Get(int index) const;
inline void Clear(int index);
inline int Length() const;
inline bool IsEmptySlot(int index) const;
static Object* Empty() { return Smi::kZero; }
class Iterator {
public:
explicit Iterator(Object* maybe_array) : list_(nullptr) {
Reset(maybe_array);
}
void Reset(Object* maybe_array);
template <class T>
inline T* Next();
private:
int index_;
WeakFixedArray* list_;
#ifdef DEBUG
int last_used_index_;
DisallowHeapAllocation no_gc_;
#endif // DEBUG
DISALLOW_COPY_AND_ASSIGN(Iterator);
};
DECL_CAST(WeakFixedArray)
private:
static const int kLastUsedIndexIndex = 0;
static const int kFirstIndex = 1;
static Handle<WeakFixedArray> Allocate(
Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from);
static void Set(Handle<WeakFixedArray> array, int index,
Handle<HeapObject> value);
inline void clear(int index);
inline int last_used_index() const;
inline void set_last_used_index(int index);
// Disallow inherited setters.
void set(int index, Smi* value);
void set(int index, Object* value);
void set(int index, Object* value, WriteBarrierMode mode);
DISALLOW_IMPLICIT_CONSTRUCTORS(WeakFixedArray);
};
// Generic array grows dynamically with O(1) amortized insertion.
//
// ArrayList is a FixedArray with static convenience methods for adding more
// elements. The Length() method returns the number of elements in the list, not
// the allocated size. The number of elements is stored at kLengthIndex and is
// updated with every insertion. The elements of the ArrayList are stored in the
// underlying FixedArray starting at kFirstIndex.
class ArrayList : public FixedArray {
public:
enum AddMode {
kNone,
// Use this if GC can delete elements from the array.
kReloadLengthAfterAllocation,
};
static Handle<ArrayList> Add(Handle<ArrayList> array, Handle<Object> obj,
AddMode mode = kNone);
static Handle<ArrayList> Add(Handle<ArrayList> array, Handle<Object> obj1,
Handle<Object> obj2, AddMode = kNone);
static Handle<ArrayList> New(Isolate* isolate, int size);
// Returns the number of elements in the list, not the allocated size, which
// is length(). Lower and upper case length() return different results!
inline int Length() const;
// Sets the Length() as used by Elements(). Does not change the underlying
// storage capacity, i.e., length().
inline void SetLength(int length);
inline Object* Get(int index) const;
inline Object** Slot(int index);
// Set the element at index to obj. The underlying array must be large enough.
// If you need to grow the ArrayList, use the static Add() methods instead.
inline void Set(int index, Object* obj,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Set the element at index to undefined. This does not change the Length().
inline void Clear(int index, Object* undefined);
// Return a copy of the list of size Length() without the first entry. The
// number returned by Length() is stored in the first entry.
static Handle<FixedArray> Elements(Handle<ArrayList> array);
bool IsFull();
DECL_CAST(ArrayList)
private:
static Handle<ArrayList> EnsureSpace(Handle<ArrayList> array, int length);
static const int kLengthIndex = 0;
static const int kFirstIndex = 1;
DISALLOW_IMPLICIT_CONSTRUCTORS(ArrayList);
};
enum SearchMode { ALL_ENTRIES, VALID_ENTRIES };
template <SearchMode search_mode, typename T>
inline int Search(T* array, Name* name, int valid_entries = 0,
int* out_insertion_index = nullptr);
// ByteArray represents fixed sized byte arrays. Used for the relocation info
// that is attached to code objects.
class ByteArray : public FixedArrayBase {
public:
inline int Size();
// Setter and getter.
inline byte get(int index) const;
inline void set(int index, byte value);
// Copy in / copy out whole byte slices.
inline void copy_out(int index, byte* buffer, int length);
inline void copy_in(int index, const byte* buffer, int length);
// Treat contents as an int array.
inline int get_int(int index) const;
inline void set_int(int index, int value);
inline uint32_t get_uint32(int index) const;
inline void set_uint32(int index, uint32_t value);
// Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic.
inline void clear_padding();
static int SizeFor(int length) {
return OBJECT_POINTER_ALIGN(kHeaderSize + length);
}
// We use byte arrays for free blocks in the heap. Given a desired size in
// bytes that is a multiple of the word size and big enough to hold a byte
// array, this function returns the number of elements a byte array should
// have.
static int LengthFor(int size_in_bytes) {
DCHECK(IsAligned(size_in_bytes, kPointerSize));
DCHECK_GE(size_in_bytes, kHeaderSize);
return size_in_bytes - kHeaderSize;
}
// Returns data start address.
inline Address GetDataStartAddress();
inline int DataSize() const;
// Returns a pointer to the ByteArray object for a given data start address.
static inline ByteArray* FromDataStartAddress(Address address);
DECL_CAST(ByteArray)
// Dispatched behavior.
inline int ByteArraySize();
DECL_PRINTER(ByteArray)
DECL_VERIFIER(ByteArray)
// Layout description.
static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
// Maximal memory consumption for a single ByteArray.
static const int kMaxSize = 512 * MB;
// Maximal length of a single ByteArray.
static const int kMaxLength = kMaxSize - kHeaderSize;
class BodyDescriptor;
// No weak fields.
typedef BodyDescriptor BodyDescriptorWeak;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
};
// Wrapper class for ByteArray which can store arbitrary C++ classes, as long
// as they can be copied with memcpy.
template <class T>
class PodArray : public ByteArray {
public:
static Handle<PodArray<T>> New(Isolate* isolate, int length,
PretenureFlag pretenure = NOT_TENURED);
void copy_out(int index, T* result) {
ByteArray::copy_out(index * sizeof(T), reinterpret_cast<byte*>(result),
sizeof(T));
}
T get(int index) {
T result;
copy_out(index, &result);
return result;
}
void set(int index, const T& value) {
copy_in(index * sizeof(T), reinterpret_cast<const byte*>(&value),
sizeof(T));
}
int length() { return ByteArray::length() / sizeof(T); }
DECL_CAST(PodArray<T>)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PodArray<T>);
};
// V has parameters (Type, type, TYPE, C type, element_size)
#define TYPED_ARRAYS(V) \
V(Uint8, uint8, UINT8, uint8_t, 1) \
V(Int8, int8, INT8, int8_t, 1) \
V(Uint16, uint16, UINT16, uint16_t, 2) \
V(Int16, int16, INT16, int16_t, 2) \
V(Uint32, uint32, UINT32, uint32_t, 4) \
V(Int32, int32, INT32, int32_t, 4) \
V(Float32, float32, FLOAT32, float, 4) \
V(Float64, float64, FLOAT64, double, 8) \
V(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t, 1)
class FixedTypedArrayBase : public FixedArrayBase {
public:
// [base_pointer]: Either points to the FixedTypedArrayBase itself or nullptr.
DECL_ACCESSORS(base_pointer, Object)
// [external_pointer]: Contains the offset between base_pointer and the start
// of the data. If the base_pointer is a nullptr, the external_pointer
// therefore points to the actual backing store.
DECL_ACCESSORS(external_pointer, void)
// Dispatched behavior.
DECL_CAST(FixedTypedArrayBase)
static const int kBasePointerOffset = FixedArrayBase::kHeaderSize;
static const int kExternalPointerOffset = kBasePointerOffset + kPointerSize;
static const int kHeaderSize =
DOUBLE_POINTER_ALIGN(kExternalPointerOffset + kPointerSize);
static const int kDataOffset = kHeaderSize;
static const int kMaxElementSize = 8;
#ifdef V8_HOST_ARCH_32_BIT
static const size_t kMaxByteLength = std::numeric_limits<size_t>::max();
#else
static const size_t kMaxByteLength =
static_cast<size_t>(Smi::kMaxValue) * kMaxElementSize;
#endif // V8_HOST_ARCH_32_BIT
static const size_t kMaxLength = Smi::kMaxValue;
class BodyDescriptor;
// No weak fields.
typedef BodyDescriptor BodyDescriptorWeak;
inline int size() const;
static inline int TypedArraySize(InstanceType type, int length);
inline int TypedArraySize(InstanceType type) const;
// Use with care: returns raw pointer into heap.
inline void* DataPtr();
inline int DataSize() const;
inline size_t ByteLength() const;
private:
static inline int ElementSize(InstanceType type);
inline int DataSize(InstanceType type) const;
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArrayBase);
};
template <class Traits>
class FixedTypedArray : public FixedTypedArrayBase {
public:
typedef typename Traits::ElementType ElementType;
static const InstanceType kInstanceType = Traits::kInstanceType;
DECL_CAST(FixedTypedArray<Traits>)
inline ElementType get_scalar(int index);
static inline Handle<Object> get(FixedTypedArray* array, int index);
inline void set(int index, ElementType value);
static inline ElementType from(int value);
static inline ElementType from(uint32_t value);
static inline ElementType from(double value);
// This accessor applies the correct conversion from Smi, HeapNumber
// and undefined.
inline void SetValue(uint32_t index, Object* value);
DECL_PRINTER(FixedTypedArray)
DECL_VERIFIER(FixedTypedArray)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArray);
};
#define FIXED_TYPED_ARRAY_TRAITS(Type, type, TYPE, elementType, size) \
STATIC_ASSERT(size <= FixedTypedArrayBase::kMaxElementSize); \
class Type##ArrayTraits { \
public: /* NOLINT */ \
typedef elementType ElementType; \
static const InstanceType kInstanceType = FIXED_##TYPE##_ARRAY_TYPE; \
static const char* Designator() { return #type " array"; } \
static inline Handle<Object> ToHandle(Isolate* isolate, \
elementType scalar); \
static inline elementType defaultValue(); \
}; \
\
typedef FixedTypedArray<Type##ArrayTraits> Fixed##Type##Array;
TYPED_ARRAYS(FIXED_TYPED_ARRAY_TRAITS)
#undef FIXED_TYPED_ARRAY_TRAITS
class TemplateList : public FixedArray {
public:
static Handle<TemplateList> New(Isolate* isolate, int size);
inline int length() const;
inline Object* get(int index) const;
inline void set(int index, Object* value);
static Handle<TemplateList> Add(Isolate* isolate, Handle<TemplateList> list,
Handle<Object> value);
DECL_CAST(TemplateList)
private:
static const int kLengthIndex = 0;
static const int kFirstElementIndex = kLengthIndex + 1;
DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateList);
};
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_FIXED_ARRAY_H_
......@@ -5,10 +5,9 @@
#ifndef V8_OBJECTS_HASH_TABLE_H_
#define V8_OBJECTS_HASH_TABLE_H_
#include "src/objects.h"
#include "src/base/compiler-specific.h"
#include "src/globals.h"
#include "src/objects/fixed-array.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
......
......@@ -6,6 +6,7 @@
#define V8_OBJECTS_JS_ARRAY_H_
#include "src/objects.h"
#include "src/objects/fixed-array.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
......
......@@ -6,6 +6,7 @@
#define V8_OBJECTS_LITERAL_OBJECTS_H_
#include "src/objects.h"
#include "src/objects/fixed-array.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
......
......@@ -6,6 +6,7 @@
#define V8_OBJECTS_MODULE_H_
#include "src/objects.h"
#include "src/objects/fixed-array.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
......
......@@ -7,6 +7,7 @@
#include "src/globals.h"
#include "src/objects.h"
#include "src/objects/fixed-array.h"
#include "src/utils.h"
// Has to be the last include (doesn't have include guards):
......
......@@ -6,6 +6,7 @@
#define V8_OBJECTS_SCRIPT_H_
#include "src/objects.h"
#include "src/objects/fixed-array.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
......
......@@ -12,6 +12,7 @@
#include "include/v8-profiler.h"
#include "src/base/platform/time.h"
#include "src/objects.h"
#include "src/objects/fixed-array.h"
#include "src/profiler/strings-storage.h"
#include "src/string-hasher.h"
#include "src/visitors.h"
......
......@@ -1165,6 +1165,8 @@
'objects/debug-objects.h',
'objects/descriptor-array.h',
'objects/dictionary.h',
'objects/fixed-array.h',
'objects/fixed-array-inl.h',
'objects/frame-array.h',
'objects/frame-array-inl.h',
'objects/hash-table-inl.h',
......@@ -2467,6 +2469,8 @@
'objects-inl.h',
'objects/code.h',
'objects/code-inl.h',
'objects/fixed-array.h',
'objects/fixed-array-inl.h',
'objects/js-array.h',
'objects/js-array-inl.h',
'objects/js-regexp.h',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment