Commit 6ebe4979 authored by Samuel Groß's avatar Samuel Groß Committed by V8 LUCI CQ

Introduce Fixed{U}Int{8,16,32,64}Array types

This CL introduces new FixedArray subclasses that behave like
fixed-sized arrays of integers. Under the hood, these are just
ByteArrays with integer element accessors.

These new classes will be used in follow-up CLs which moves various
integer arrays from the native heap onto the V8 heap.

Bug: chromium:1335046
Change-Id: Ie7497b4464c1a037e4eaf49e8bf7ac4da62512de
Cq-Include-Trybots: luci.v8.try:v8_linux64_heap_sandbox_dbg_ng,v8_linux_arm64_sim_heap_sandbox_dbg_ng
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3838775Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarJakob Linke <jgruber@chromium.org>
Commit-Queue: Samuel Groß <saelo@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82678}
parent a9990e08
...@@ -85,13 +85,13 @@ void BasicBlockProfilerData::CopyFromJSHeap( ...@@ -85,13 +85,13 @@ void BasicBlockProfilerData::CopyFromJSHeap(
function_name_ = js_heap_data.name().ToCString().get(); function_name_ = js_heap_data.name().ToCString().get();
schedule_ = js_heap_data.schedule().ToCString().get(); schedule_ = js_heap_data.schedule().ToCString().get();
code_ = js_heap_data.code().ToCString().get(); code_ = js_heap_data.code().ToCString().get();
ByteArray counts(js_heap_data.counts()); FixedUInt32Array counts = FixedUInt32Array::cast(js_heap_data.counts());
for (int i = 0; i < counts.length() / kBlockCountSlotSize; ++i) { for (int i = 0; i < counts.length() / kBlockCountSlotSize; ++i) {
counts_.push_back(counts.get_uint32(i)); counts_.push_back(counts.get(i));
} }
ByteArray block_ids(js_heap_data.block_ids()); FixedInt32Array block_ids(js_heap_data.block_ids());
for (int i = 0; i < block_ids.length() / kBlockIdSlotSize; ++i) { for (int i = 0; i < block_ids.length() / kBlockIdSlotSize; ++i) {
block_ids_.push_back(block_ids.get_int(i)); block_ids_.push_back(block_ids.get(i));
} }
PodArray<std::pair<int32_t, int32_t>> branches = js_heap_data.branches(); PodArray<std::pair<int32_t, int32_t>> branches = js_heap_data.branches();
for (int i = 0; i < branches.length(); ++i) { for (int i = 0; i < branches.length(); ++i) {
...@@ -107,10 +107,10 @@ Handle<OnHeapBasicBlockProfilerData> BasicBlockProfilerData::CopyToJSHeap( ...@@ -107,10 +107,10 @@ Handle<OnHeapBasicBlockProfilerData> BasicBlockProfilerData::CopyToJSHeap(
CHECK(id_array_size_in_bytes >= 0 && CHECK(id_array_size_in_bytes >= 0 &&
static_cast<size_t>(id_array_size_in_bytes) / kBlockIdSlotSize == static_cast<size_t>(id_array_size_in_bytes) / kBlockIdSlotSize ==
n_blocks()); // Overflow n_blocks()); // Overflow
Handle<ByteArray> block_ids = isolate->factory()->NewByteArray( Handle<FixedInt32Array> block_ids = FixedInt32Array::New(
id_array_size_in_bytes, AllocationType::kOld); isolate, id_array_size_in_bytes, AllocationType::kOld);
for (int i = 0; i < static_cast<int>(n_blocks()); ++i) { for (int i = 0; i < static_cast<int>(n_blocks()); ++i) {
block_ids->set_int(i, block_ids_[i]); block_ids->set(i, block_ids_[i]);
} }
int counts_array_size_in_bytes = int counts_array_size_in_bytes =
...@@ -118,10 +118,10 @@ Handle<OnHeapBasicBlockProfilerData> BasicBlockProfilerData::CopyToJSHeap( ...@@ -118,10 +118,10 @@ Handle<OnHeapBasicBlockProfilerData> BasicBlockProfilerData::CopyToJSHeap(
CHECK(counts_array_size_in_bytes >= 0 && CHECK(counts_array_size_in_bytes >= 0 &&
static_cast<size_t>(counts_array_size_in_bytes) / kBlockCountSlotSize == static_cast<size_t>(counts_array_size_in_bytes) / kBlockCountSlotSize ==
n_blocks()); // Overflow n_blocks()); // Overflow
Handle<ByteArray> counts = isolate->factory()->NewByteArray( Handle<FixedUInt32Array> counts = FixedUInt32Array::New(
counts_array_size_in_bytes, AllocationType::kOld); isolate, counts_array_size_in_bytes, AllocationType::kOld);
for (int i = 0; i < static_cast<int>(n_blocks()); ++i) { for (int i = 0; i < static_cast<int>(n_blocks()); ++i) {
counts->set_uint32(i, counts_[i]); counts->set(i, counts_[i]);
} }
Handle<PodArray<std::pair<int32_t, int32_t>>> branches = Handle<PodArray<std::pair<int32_t, int32_t>>> branches =
...@@ -147,10 +147,10 @@ void BasicBlockProfiler::ResetCounts(Isolate* isolate) { ...@@ -147,10 +147,10 @@ void BasicBlockProfiler::ResetCounts(Isolate* isolate) {
Handle<ArrayList> list(isolate->heap()->basic_block_profiling_data(), Handle<ArrayList> list(isolate->heap()->basic_block_profiling_data(),
isolate); isolate);
for (int i = 0; i < list->Length(); ++i) { for (int i = 0; i < list->Length(); ++i) {
Handle<ByteArray> counts( Handle<FixedUInt32Array> counts(
OnHeapBasicBlockProfilerData::cast(list->Get(i)).counts(), isolate); OnHeapBasicBlockProfilerData::cast(list->Get(i)).counts(), isolate);
for (int j = 0; j < counts->length() / kBlockCountSlotSize; ++j) { for (int j = 0; j < counts->length() / kBlockCountSlotSize; ++j) {
counts->set_uint32(j, 0); counts->set(j, 0);
} }
} }
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "src/base/export-template.h" #include "src/base/export-template.h"
#include "src/base/strings.h" #include "src/base/strings.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/objects/fixed-array.h"
#include "src/objects/function-kind.h" #include "src/objects/function-kind.h"
#include "src/objects/instance-type.h" #include "src/objects/instance-type.h"
#include "src/roots/roots.h" #include "src/roots/roots.h"
...@@ -28,8 +29,6 @@ class RegExpBoilerplateDescription; ...@@ -28,8 +29,6 @@ class RegExpBoilerplateDescription;
class TemplateObjectDescription; class TemplateObjectDescription;
class SourceTextModuleInfo; class SourceTextModuleInfo;
class PreparseData; class PreparseData;
template <class T>
class PodArray;
class UncompiledDataWithoutPreparseData; class UncompiledDataWithoutPreparseData;
class UncompiledDataWithPreparseData; class UncompiledDataWithPreparseData;
class BytecodeArray; class BytecodeArray;
......
...@@ -597,104 +597,106 @@ void ArrayList::Clear(int index, Object undefined) { ...@@ -597,104 +597,106 @@ void ArrayList::Clear(int index, Object undefined) {
int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kTaggedSize); } int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kTaggedSize); }
byte ByteArray::get(int index) const { byte ByteArray::get(int offset) const {
DCHECK_GE(index, 0); DCHECK_GE(offset, 0);
DCHECK_LT(index, length()); DCHECK_LT(offset, length());
return ReadField<byte>(kHeaderSize + index * kCharSize); return ReadField<byte>(kHeaderSize + offset);
} }
void ByteArray::set(int index, byte value) { void ByteArray::set(int offset, byte value) {
DCHECK_GE(index, 0); DCHECK_GE(offset, 0);
DCHECK_LT(index, length()); DCHECK_LT(offset, length());
WriteField<byte>(kHeaderSize + index * kCharSize, value); WriteField<byte>(kHeaderSize + offset, value);
} }
void ByteArray::copy_in(int index, const byte* buffer, int slice_length) { int ByteArray::get_int(int offset) const {
DCHECK_GE(index, 0); DCHECK_GE(offset, 0);
DCHECK_LE(offset + sizeof(int), length());
return ReadField<int>(kHeaderSize + offset);
}
void ByteArray::set_int(int offset, int value) {
DCHECK_GE(offset, 0);
DCHECK_LE(offset + sizeof(int), length());
WriteField<int>(kHeaderSize + offset, value);
}
void ByteArray::copy_in(int offset, const byte* buffer, int slice_length) {
DCHECK_GE(offset, 0);
DCHECK_GE(slice_length, 0); DCHECK_GE(slice_length, 0);
DCHECK_LE(slice_length, kMaxInt - index); DCHECK_LE(slice_length, kMaxInt - offset);
DCHECK_LE(index + slice_length, length()); DCHECK_LE(offset + slice_length, length());
Address dst_addr = field_address(kHeaderSize + index * kCharSize); Address dst_addr = field_address(kHeaderSize + offset);
memcpy(reinterpret_cast<void*>(dst_addr), buffer, slice_length); memcpy(reinterpret_cast<void*>(dst_addr), buffer, slice_length);
} }
void ByteArray::copy_out(int index, byte* buffer, int slice_length) { void ByteArray::copy_out(int offset, byte* buffer, int slice_length) {
DCHECK_GE(index, 0); DCHECK_GE(offset, 0);
DCHECK_GE(slice_length, 0); DCHECK_GE(slice_length, 0);
DCHECK_LE(slice_length, kMaxInt - index); DCHECK_LE(slice_length, kMaxInt - offset);
DCHECK_LE(index + slice_length, length()); DCHECK_LE(offset + slice_length, length());
Address src_addr = field_address(kHeaderSize + index * kCharSize); Address src_addr = field_address(kHeaderSize + offset);
memcpy(buffer, reinterpret_cast<void*>(src_addr), slice_length); memcpy(buffer, reinterpret_cast<void*>(src_addr), slice_length);
} }
int ByteArray::get_int(int index) const { void ByteArray::clear_padding() {
DCHECK_GE(index, 0); int data_size = length() + kHeaderSize;
DCHECK_LT(index, length() / kIntSize); memset(reinterpret_cast<void*>(address() + data_size), 0, Size() - data_size);
return ReadField<int>(kHeaderSize + index * kIntSize);
}
void ByteArray::set_int(int index, int value) {
DCHECK_GE(index, 0);
DCHECK_LT(index, length() / kIntSize);
WriteField<int>(kHeaderSize + index * kIntSize, value);
} }
uint32_t ByteArray::get_uint32(int index) const { ByteArray ByteArray::FromDataStartAddress(Address address) {
DCHECK_GE(index, 0); DCHECK_TAG_ALIGNED(address);
DCHECK_LT(index, length() / kUInt32Size); return ByteArray::cast(Object(address - kHeaderSize + kHeapObjectTag));
return ReadField<uint32_t>(kHeaderSize + index * kUInt32Size);
} }
void ByteArray::set_uint32(int index, uint32_t value) { int ByteArray::DataSize() const { return RoundUp(length(), kTaggedSize); }
DCHECK_GE(index, 0);
DCHECK_LT(index, length() / kUInt32Size);
WriteField<uint32_t>(kHeaderSize + index * kUInt32Size, value);
}
uint32_t ByteArray::get_uint32_relaxed(int index) const { byte* ByteArray::GetDataStartAddress() {
DCHECK_GE(index, 0); return reinterpret_cast<byte*>(address() + kHeaderSize);
DCHECK_LT(index, length() / kUInt32Size);
return RELAXED_READ_UINT32_FIELD(*this, kHeaderSize + index * kUInt32Size);
} }
void ByteArray::set_uint32_relaxed(int index, uint32_t value) { byte* ByteArray::GetDataEndAddress() {
DCHECK_GE(index, 0); return GetDataStartAddress() + length();
DCHECK_LT(index, length() / kUInt32Size);
RELAXED_WRITE_UINT32_FIELD(*this, kHeaderSize + index * kUInt32Size, value);
} }
uint16_t ByteArray::get_uint16(int index) const { template <typename T>
DCHECK_GE(index, 0); FixedIntegerArray<T>::FixedIntegerArray(Address ptr) : ByteArray(ptr) {
DCHECK_LT(index, length() / kUInt16Size); DCHECK_EQ(ByteArray::length() % sizeof(T), 0);
return ReadField<uint16_t>(kHeaderSize + index * kUInt16Size);
} }
void ByteArray::set_uint16(int index, uint16_t value) { template <typename T>
DCHECK_GE(index, 0); FixedIntegerArray<T> FixedIntegerArray<T>::cast(Object object) {
DCHECK_LT(index, length() / kUInt16Size); return FixedIntegerArray<T>(object.ptr());
WriteField<uint16_t>(kHeaderSize + index * kUInt16Size, value);
} }
void ByteArray::clear_padding() { // static
int data_size = length() + kHeaderSize; template <typename T>
memset(reinterpret_cast<void*>(address() + data_size), 0, Size() - data_size); Handle<FixedIntegerArray<T>> FixedIntegerArray<T>::New(
Isolate* isolate, int length, AllocationType allocation) {
return Handle<FixedIntegerArray<T>>::cast(
isolate->factory()->NewByteArray(length * sizeof(T), allocation));
} }
ByteArray ByteArray::FromDataStartAddress(Address address) { template <typename T>
DCHECK_TAG_ALIGNED(address); T FixedIntegerArray<T>::get(int index) const {
return ByteArray::cast(Object(address - kHeaderSize + kHeapObjectTag)); static_assert(std::is_integral<T>::value);
DCHECK_GE(index, 0);
DCHECK_LT(index, length());
return ReadField<T>(kHeaderSize + index * sizeof(T));
} }
int ByteArray::DataSize() const { return RoundUp(length(), kTaggedSize); } template <typename T>
void FixedIntegerArray<T>::set(int index, T value) {
int ByteArray::ByteArraySize() { return SizeFor(length()); } static_assert(std::is_integral<T>::value);
DCHECK_GE(index, 0);
byte* ByteArray::GetDataStartAddress() { DCHECK_LT(index, length());
return reinterpret_cast<byte*>(address() + kHeaderSize); WriteField<T>(kHeaderSize + index * sizeof(T), value);
} }
byte* ByteArray::GetDataEndAddress() { template <typename T>
return GetDataStartAddress() + length(); int FixedIntegerArray<T>::length() const {
DCHECK_EQ(ByteArray::length() % sizeof(T), 0);
return ByteArray::length() / sizeof(T);
} }
template <class T> template <class T>
......
...@@ -329,7 +329,7 @@ class WeakFixedArray ...@@ -329,7 +329,7 @@ class WeakFixedArray
int AllocatedSize(); int AllocatedSize();
static int OffsetOfElementAt(int index) { static int OffsetOfElementAt(int index) {
static_assert(kObjectsOffset == SizeFor(0)); static_assert(kHeaderSize == SizeFor(0));
return SizeFor(index); return SizeFor(index);
} }
...@@ -518,33 +518,23 @@ inline int Search(T* array, Name name, int valid_entries = 0, ...@@ -518,33 +518,23 @@ inline int Search(T* array, Name name, int valid_entries = 0,
int* out_insertion_index = nullptr, int* out_insertion_index = nullptr,
bool concurrent_search = false); bool concurrent_search = false);
// ByteArray represents fixed sized byte arrays. Used for the relocation info // ByteArray represents fixed sized arrays containing raw bytes that will not
// that is attached to code objects. // be scanned by the garbage collector.
class ByteArray : public TorqueGeneratedByteArray<ByteArray, FixedArrayBase> { class ByteArray : public TorqueGeneratedByteArray<ByteArray, FixedArrayBase> {
public: public:
inline int Size(); inline int Size();
// Setter and getter. // Get/set the contents of this array.
inline byte get(int index) const; inline byte get(int offset) const;
inline void set(int index, byte value); inline void set(int offset, byte value);
inline int get_int(int offset) const;
inline void set_int(int offset, int value);
// Copy in / copy out whole byte slices. // Copy in / copy out whole byte slices.
inline void copy_out(int index, byte* buffer, int slice_length); inline void copy_out(int index, byte* buffer, int slice_length);
inline void copy_in(int index, const byte* buffer, int slice_length); inline void copy_in(int index, const byte* buffer, int slice_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);
inline uint32_t get_uint32_relaxed(int index) const;
inline void set_uint32_relaxed(int index, uint32_t value);
inline uint16_t get_uint16(int index) const;
inline void set_uint16(int index, uint16_t value);
// Clear uninitialized padding space. This ensures that the snapshot content // Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic. // is deterministic.
inline void clear_padding(); inline void clear_padding();
...@@ -572,8 +562,10 @@ class ByteArray : public TorqueGeneratedByteArray<ByteArray, FixedArrayBase> { ...@@ -572,8 +562,10 @@ class ByteArray : public TorqueGeneratedByteArray<ByteArray, FixedArrayBase> {
// Returns a pointer to the ByteArray object for a given data start address. // Returns a pointer to the ByteArray object for a given data start address.
static inline ByteArray FromDataStartAddress(Address address); static inline ByteArray FromDataStartAddress(Address address);
// Code Generation support.
static int OffsetOfElementAt(int index) { return kHeaderSize + index; }
// Dispatched behavior. // Dispatched behavior.
inline int ByteArraySize();
DECL_PRINTER(ByteArray) DECL_PRINTER(ByteArray)
// Layout description. // Layout description.
...@@ -591,6 +583,41 @@ class ByteArray : public TorqueGeneratedByteArray<ByteArray, FixedArrayBase> { ...@@ -591,6 +583,41 @@ class ByteArray : public TorqueGeneratedByteArray<ByteArray, FixedArrayBase> {
inline ByteArray(Address ptr, HeapObject::AllowInlineSmiStorage allow_smi); inline ByteArray(Address ptr, HeapObject::AllowInlineSmiStorage allow_smi);
}; };
// Convenience class for treating a ByteArray as array of fixed-size integers.
template <typename T>
class FixedIntegerArray : public ByteArray {
static_assert(std::is_integral<T>::value);
public:
static Handle<FixedIntegerArray<T>> New(
Isolate* isolate, int length,
AllocationType allocation = AllocationType::kYoung);
// Get/set the contents of this array.
T get(int index) const;
void set(int index, T value);
// Code Generation support.
static constexpr int OffsetOfElementAt(int index) {
return kHeaderSize + index * sizeof(T);
}
inline int length() const;
DECL_CAST(FixedIntegerArray<T>)
OBJECT_CONSTRUCTORS(FixedIntegerArray<T>, ByteArray);
};
using FixedInt8Array = FixedIntegerArray<int8_t>;
using FixedUInt8Array = FixedIntegerArray<uint8_t>;
using FixedInt16Array = FixedIntegerArray<int16_t>;
using FixedUInt16Array = FixedIntegerArray<uint16_t>;
using FixedInt32Array = FixedIntegerArray<int32_t>;
using FixedUInt32Array = FixedIntegerArray<uint32_t>;
using FixedInt64Array = FixedIntegerArray<int64_t>;
using FixedUInt64Array = FixedIntegerArray<uint64_t>;
// Wrapper class for ByteArray which can store arbitrary C++ classes, as long // Wrapper class for ByteArray which can store arbitrary C++ classes, as long
// as they can be copied with memcpy. // as they can be copied with memcpy.
template <class T> template <class T>
......
...@@ -289,11 +289,6 @@ namespace InstanceTypeChecker { ...@@ -289,11 +289,6 @@ namespace InstanceTypeChecker {
INSTANCE_TYPE_CHECKERS(IS_TYPE_FUNCTION_DECL) INSTANCE_TYPE_CHECKERS(IS_TYPE_FUNCTION_DECL)
#define TYPED_ARRAY_IS_TYPE_FUNCTION_DECL(Type, ...) \
IS_TYPE_FUNCTION_DECL(Fixed##Type##Array)
TYPED_ARRAYS(TYPED_ARRAY_IS_TYPE_FUNCTION_DECL)
#undef TYPED_ARRAY_IS_TYPE_FUNCTION_DECL
IS_TYPE_FUNCTION_DECL(CodeT) IS_TYPE_FUNCTION_DECL(CodeT)
#undef IS_TYPE_FUNCTION_DECL #undef IS_TYPE_FUNCTION_DECL
......
...@@ -151,11 +151,17 @@ extern class UncompiledDataWithPreparseDataAndJob extends ...@@ -151,11 +151,17 @@ extern class UncompiledDataWithPreparseDataAndJob extends
type PodArrayOfIntegerPairs extends ByteArray type PodArrayOfIntegerPairs extends ByteArray
constexpr 'PodArray<std::pair<int32_t, int32_t>>'; constexpr 'PodArray<std::pair<int32_t, int32_t>>';
@useParentTypeChecker
type FixedInt32Array extends ByteArray constexpr 'FixedInt32Array';
@useParentTypeChecker
type FixedUInt32Array extends ByteArray constexpr 'FixedUInt32Array';
@export @export
class OnHeapBasicBlockProfilerData extends HeapObject { class OnHeapBasicBlockProfilerData extends HeapObject {
block_ids: ByteArray; // Stored as 4-byte ints block_ids: FixedInt32Array;
counts: ByteArray; // Stored as 4-byte unsigned ints counts: FixedUInt32Array;
branches: PodArrayOfIntegerPairs; // Stored as pairs of 4-byte ints branches: PodArrayOfIntegerPairs;
name: String; name: String;
schedule: String; schedule: String;
code: String; code: String;
......
...@@ -129,37 +129,36 @@ int RangeArrayLengthFor(const ZoneList<CharacterRange>* ranges) { ...@@ -129,37 +129,36 @@ int RangeArrayLengthFor(const ZoneList<CharacterRange>* ranges) {
: ranges_length * 2; : ranges_length * 2;
} }
bool Equals(const ZoneList<CharacterRange>* lhs, const Handle<ByteArray>& rhs) { bool Equals(const ZoneList<CharacterRange>* lhs,
DCHECK_EQ(rhs->length() % kUInt16Size, 0); // uc16 elements. const Handle<FixedUInt16Array>& rhs) {
const int rhs_length = rhs->length() / kUInt16Size; const int rhs_length = rhs->length();
if (rhs_length != RangeArrayLengthFor(lhs)) return false; if (rhs_length != RangeArrayLengthFor(lhs)) return false;
for (int i = 0; i < lhs->length(); i++) { for (int i = 0; i < lhs->length(); i++) {
const CharacterRange& r = lhs->at(i); const CharacterRange& r = lhs->at(i);
if (rhs->get_uint16(i * 2 + 0) != r.from()) return false; if (rhs->get(i * 2 + 0) != r.from()) return false;
if (i * 2 + 1 == rhs_length) break; if (i * 2 + 1 == rhs_length) break;
if (rhs->get_uint16(i * 2 + 1) != r.to() + 1) return false; if (rhs->get(i * 2 + 1) != r.to() + 1) return false;
} }
return true; return true;
} }
Handle<ByteArray> MakeRangeArray(Isolate* isolate, Handle<FixedUInt16Array> MakeRangeArray(
const ZoneList<CharacterRange>* ranges) { Isolate* isolate, const ZoneList<CharacterRange>* ranges) {
const int ranges_length = ranges->length(); const int ranges_length = ranges->length();
const int byte_array_length = RangeArrayLengthFor(ranges); const int range_array_length = RangeArrayLengthFor(ranges);
const int size_in_bytes = byte_array_length * kUInt16Size; Handle<FixedUInt16Array> range_array =
Handle<ByteArray> range_array = FixedUInt16Array::New(isolate, range_array_length);
isolate->factory()->NewByteArray(size_in_bytes);
for (int i = 0; i < ranges_length; i++) { for (int i = 0; i < ranges_length; i++) {
const CharacterRange& r = ranges->at(i); const CharacterRange& r = ranges->at(i);
DCHECK_LE(r.from(), kMaxUInt16); DCHECK_LE(r.from(), kMaxUInt16);
range_array->set_uint16(i * 2 + 0, r.from()); range_array->set(i * 2 + 0, r.from());
const base::uc32 to = MaskEndOfRangeMarker(r.to()); const base::uc32 to = MaskEndOfRangeMarker(r.to());
if (i == ranges_length - 1 && to == kMaxUInt16) { if (i == ranges_length - 1 && to == kMaxUInt16) {
DCHECK_EQ(byte_array_length, ranges_length * 2 - 1); DCHECK_EQ(range_array_length, ranges_length * 2 - 1);
break; // Avoid overflow by leaving the last range open-ended. break; // Avoid overflow by leaving the last range open-ended.
} }
DCHECK_LT(to, kMaxUInt16); DCHECK_LT(to, kMaxUInt16);
range_array->set_uint16(i * 2 + 1, to + 1); // Exclusive. range_array->set(i * 2 + 1, to + 1); // Exclusive.
} }
return range_array; return range_array;
} }
...@@ -171,11 +170,11 @@ Handle<ByteArray> NativeRegExpMacroAssembler::GetOrAddRangeArray( ...@@ -171,11 +170,11 @@ Handle<ByteArray> NativeRegExpMacroAssembler::GetOrAddRangeArray(
const uint32_t hash = Hash(ranges); const uint32_t hash = Hash(ranges);
if (range_array_cache_.count(hash) != 0) { if (range_array_cache_.count(hash) != 0) {
Handle<ByteArray> range_array = range_array_cache_[hash]; Handle<FixedUInt16Array> range_array = range_array_cache_[hash];
if (Equals(ranges, range_array)) return range_array; if (Equals(ranges, range_array)) return range_array;
} }
Handle<ByteArray> range_array = MakeRangeArray(isolate(), ranges); Handle<FixedUInt16Array> range_array = MakeRangeArray(isolate(), ranges);
range_array_cache_[hash] = range_array; range_array_cache_[hash] = range_array;
return range_array; return range_array;
} }
...@@ -189,27 +188,24 @@ uint32_t RegExpMacroAssembler::IsCharacterInRangeArray(uint32_t current_char, ...@@ -189,27 +188,24 @@ uint32_t RegExpMacroAssembler::IsCharacterInRangeArray(uint32_t current_char,
static constexpr uint32_t kTrue = 1; static constexpr uint32_t kTrue = 1;
static constexpr uint32_t kFalse = 0; static constexpr uint32_t kFalse = 0;
ByteArray ranges = ByteArray::cast(Object(raw_byte_array)); FixedUInt16Array ranges = FixedUInt16Array::cast(Object(raw_byte_array));
DCHECK_GE(ranges.length(), 1);
DCHECK_EQ(ranges.length() % kUInt16Size, 0); // uc16 elements.
const int length = ranges.length() / kUInt16Size;
DCHECK_GE(length, 1);
// Shortcut for fully out of range chars. // Shortcut for fully out of range chars.
if (current_char < ranges.get_uint16(0)) return kFalse; if (current_char < ranges.get(0)) return kFalse;
if (current_char >= ranges.get_uint16(length - 1)) { if (current_char >= ranges.get(ranges.length() - 1)) {
// The last range may be open-ended. // The last range may be open-ended.
return (length % 2) == 0 ? kFalse : kTrue; return (ranges.length() % 2) == 0 ? kFalse : kTrue;
} }
// Binary search for the matching range. `ranges` is encoded as // Binary search for the matching range. `ranges` is encoded as
// [from0, to0, from1, to1, ..., fromN, toN], or // [from0, to0, from1, to1, ..., fromN, toN], or
// [from0, to0, from1, to1, ..., fromN] (open-ended last interval). // [from0, to0, from1, to1, ..., fromN] (open-ended last interval).
int mid, lower = 0, upper = length; int mid, lower = 0, upper = ranges.length();
do { do {
mid = lower + (upper - lower) / 2; mid = lower + (upper - lower) / 2;
const base::uc16 elem = ranges.get_uint16(mid); const base::uc16 elem = ranges.get(mid);
if (current_char < elem) { if (current_char < elem) {
upper = mid; upper = mid;
} else if (current_char > elem) { } else if (current_char > elem) {
...@@ -220,7 +216,7 @@ uint32_t RegExpMacroAssembler::IsCharacterInRangeArray(uint32_t current_char, ...@@ -220,7 +216,7 @@ uint32_t RegExpMacroAssembler::IsCharacterInRangeArray(uint32_t current_char,
} }
} while (lower < upper); } while (lower < upper);
const bool current_char_ge_last_elem = current_char >= ranges.get_uint16(mid); const bool current_char_ge_last_elem = current_char >= ranges.get(mid);
const int current_range_start_index = const int current_range_start_index =
current_char_ge_last_elem ? mid : mid - 1; current_char_ge_last_elem ? mid : mid - 1;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define V8_REGEXP_REGEXP_MACRO_ASSEMBLER_H_ #define V8_REGEXP_REGEXP_MACRO_ASSEMBLER_H_
#include "src/base/strings.h" #include "src/base/strings.h"
#include "src/objects/fixed-array.h"
#include "src/regexp/regexp-ast.h" #include "src/regexp/regexp-ast.h"
#include "src/regexp/regexp.h" #include "src/regexp/regexp.h"
...@@ -351,7 +352,7 @@ class NativeRegExpMacroAssembler: public RegExpMacroAssembler { ...@@ -351,7 +352,7 @@ class NativeRegExpMacroAssembler: public RegExpMacroAssembler {
const byte* input_end, int* output, int output_size, const byte* input_end, int* output, int output_size,
Isolate* isolate, JSRegExp regexp); Isolate* isolate, JSRegExp regexp);
ZoneUnorderedMap<uint32_t, Handle<ByteArray>> range_array_cache_; ZoneUnorderedMap<uint32_t, Handle<FixedUInt16Array>> range_array_cache_;
}; };
} // namespace internal } // namespace internal
......
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