Reland "[parser] Inline byte scope data into PreparseData object"
This is a reland of e2d44ede95
Original change's description:
> [parser] Inline byte scope data into PreparseData object
>
> Each PreparseData object had at least one pointer to a PodArray for its
> serialized scope data. These objects usually have only tens of bytes of
> payload. By inlining the byte data we save 3 words per PreparseData object.
> This optimization saves 140KB of data on cnn.com.
>
>
> - Store data_length and inner_length as int32 saving a words on 64bit
> - Inline store byte data into PreparseData
> - OnHeapConsumedPreparseData directly uses the PreparseData object
> - get_inner, set_inner no longer allow Null sentinels
>
> Change-Id: I1f62154d05ea2f98a6574efa738b32a8a84319d5
> Reviewed-on: https://chromium-review.googlesource.com/c/1406673
> Reviewed-by: Leszek Swirski <leszeks@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Commit-Queue: Camillo Bruni <cbruni@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#58751}
Change-Id: I1f0a22c641d0d67f435b01c82daf8da7f144bff4
Reviewed-on: https://chromium-review.googlesource.com/c/1407066
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58785}
This commit is contained in:
parent
c8567109f5
commit
a6f4462987
@ -111,8 +111,6 @@ const unsigned kRegCodeMask = 0x1f;
|
|||||||
const unsigned kShiftAmountWRegMask = 0x1f;
|
const unsigned kShiftAmountWRegMask = 0x1f;
|
||||||
const unsigned kShiftAmountXRegMask = 0x3f;
|
const unsigned kShiftAmountXRegMask = 0x3f;
|
||||||
// Standard machine types defined by AAPCS64.
|
// Standard machine types defined by AAPCS64.
|
||||||
const unsigned kByteSize = 8;
|
|
||||||
const unsigned kByteSizeInBytes = kByteSize >> 3;
|
|
||||||
const unsigned kHalfWordSize = 16;
|
const unsigned kHalfWordSize = 16;
|
||||||
const unsigned kHalfWordSizeLog2 = 4;
|
const unsigned kHalfWordSizeLog2 = 4;
|
||||||
const unsigned kHalfWordSizeInBytes = kHalfWordSize >> 3;
|
const unsigned kHalfWordSizeInBytes = kHalfWordSize >> 3;
|
||||||
|
@ -119,6 +119,7 @@ constexpr uint32_t kMaxUInt32 = 0xFFFFFFFFu;
|
|||||||
constexpr int kMinUInt32 = 0;
|
constexpr int kMinUInt32 = 0;
|
||||||
|
|
||||||
constexpr int kUInt8Size = sizeof(uint8_t);
|
constexpr int kUInt8Size = sizeof(uint8_t);
|
||||||
|
constexpr int kByteSize = sizeof(byte);
|
||||||
constexpr int kCharSize = sizeof(char);
|
constexpr int kCharSize = sizeof(char);
|
||||||
constexpr int kShortSize = sizeof(short); // NOLINT
|
constexpr int kShortSize = sizeof(short); // NOLINT
|
||||||
constexpr int kUInt16Size = sizeof(uint16_t);
|
constexpr int kUInt16Size = sizeof(uint16_t);
|
||||||
|
@ -2638,15 +2638,15 @@ Handle<ModuleInfo> Factory::NewModuleInfo() {
|
|||||||
ModuleInfo::kLength, TENURED);
|
ModuleInfo::kLength, TENURED);
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<PreparseData> Factory::NewPreparseData(int length) {
|
Handle<PreparseData> Factory::NewPreparseData(int data_length,
|
||||||
int size = PreparseData::SizeFor(length);
|
int children_length) {
|
||||||
|
int size = PreparseData::SizeFor(data_length, children_length);
|
||||||
Handle<PreparseData> result(PreparseData::cast(AllocateRawWithImmortalMap(
|
Handle<PreparseData> result(PreparseData::cast(AllocateRawWithImmortalMap(
|
||||||
size, TENURED, *preparse_data_map())),
|
size, TENURED, *preparse_data_map())),
|
||||||
isolate());
|
isolate());
|
||||||
result->set_scope_data(PodArray<uint8_t>::cast(*empty_byte_array()));
|
result->set_data_length(data_length);
|
||||||
result->set_length(length);
|
result->set_children_length(children_length);
|
||||||
MemsetTagged(result->child_data_start(), *null_value(), length);
|
MemsetTagged(result->inner_data_start(), *null_value(), children_length);
|
||||||
|
|
||||||
result->clear_padding();
|
result->clear_padding();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -750,7 +750,7 @@ class V8_EXPORT_PRIVATE Factory {
|
|||||||
|
|
||||||
Handle<ModuleInfo> NewModuleInfo();
|
Handle<ModuleInfo> NewModuleInfo();
|
||||||
|
|
||||||
Handle<PreparseData> NewPreparseData(int length);
|
Handle<PreparseData> NewPreparseData(int data_length, int children_length);
|
||||||
|
|
||||||
Handle<UncompiledDataWithoutPreparseData>
|
Handle<UncompiledDataWithoutPreparseData>
|
||||||
NewUncompiledDataWithoutPreparseData(Handle<String> inferred_name,
|
NewUncompiledDataWithoutPreparseData(Handle<String> inferred_name,
|
||||||
|
@ -401,7 +401,6 @@ class ObjectStatsCollectorImpl {
|
|||||||
void RecordVirtualExternalStringDetails(ExternalString script);
|
void RecordVirtualExternalStringDetails(ExternalString script);
|
||||||
void RecordVirtualSharedFunctionInfoDetails(SharedFunctionInfo info);
|
void RecordVirtualSharedFunctionInfoDetails(SharedFunctionInfo info);
|
||||||
void RecordVirtualJSFunctionDetails(JSFunction function);
|
void RecordVirtualJSFunctionDetails(JSFunction function);
|
||||||
void RecordVirtualPreparseDataDetails(PreparseData data);
|
|
||||||
|
|
||||||
void RecordVirtualArrayBoilerplateDescription(
|
void RecordVirtualArrayBoilerplateDescription(
|
||||||
ArrayBoilerplateDescription description);
|
ArrayBoilerplateDescription description);
|
||||||
@ -650,18 +649,6 @@ void ObjectStatsCollectorImpl::RecordVirtualFeedbackVectorDetails(
|
|||||||
CHECK_EQ(calculated_size, vector->Size());
|
CHECK_EQ(calculated_size, vector->Size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectStatsCollectorImpl::RecordVirtualPreparseDataDetails(
|
|
||||||
PreparseData data) {
|
|
||||||
if (virtual_objects_.find(data) != virtual_objects_.end()) return;
|
|
||||||
// Manually insert the PreparseData since we're combining the size with it's
|
|
||||||
// byte_data size.
|
|
||||||
virtual_objects_.insert(data);
|
|
||||||
virtual_objects_.insert(data->scope_data());
|
|
||||||
size_t size = data->Size() + data->scope_data()->Size();
|
|
||||||
DCHECK_LE(0, data->scope_data()->length());
|
|
||||||
stats_->RecordObjectStats(PREPARSE_DATA_TYPE, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectStatsCollectorImpl::RecordVirtualFixedArrayDetails(
|
void ObjectStatsCollectorImpl::RecordVirtualFixedArrayDetails(
|
||||||
FixedArray array) {
|
FixedArray array) {
|
||||||
if (IsCowArray(array)) {
|
if (IsCowArray(array)) {
|
||||||
@ -706,8 +693,6 @@ void ObjectStatsCollectorImpl::CollectStatistics(
|
|||||||
} else if (obj->IsArrayBoilerplateDescription()) {
|
} else if (obj->IsArrayBoilerplateDescription()) {
|
||||||
RecordVirtualArrayBoilerplateDescription(
|
RecordVirtualArrayBoilerplateDescription(
|
||||||
ArrayBoilerplateDescription::cast(obj));
|
ArrayBoilerplateDescription::cast(obj));
|
||||||
} else if (obj->IsPreparseData()) {
|
|
||||||
RecordVirtualPreparseDataDetails(PreparseData::cast(obj));
|
|
||||||
} else if (obj->IsFixedArrayExact()) {
|
} else if (obj->IsFixedArrayExact()) {
|
||||||
// Has to go last as it triggers too eagerly.
|
// Has to go last as it triggers too eagerly.
|
||||||
RecordVirtualFixedArrayDetails(FixedArray::cast(obj));
|
RecordVirtualFixedArrayDetails(FixedArray::cast(obj));
|
||||||
|
@ -505,18 +505,21 @@ class FeedbackVector::BodyDescriptor final : public BodyDescriptorBase {
|
|||||||
class PreparseData::BodyDescriptor final : public BodyDescriptorBase {
|
class PreparseData::BodyDescriptor final : public BodyDescriptorBase {
|
||||||
public:
|
public:
|
||||||
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
||||||
return offset == kScopeDataOffset || offset >= kChildDataStartOffset;
|
return offset >= PreparseData::cast(obj)->inner_start_offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ObjectVisitor>
|
template <typename ObjectVisitor>
|
||||||
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
||||||
ObjectVisitor* v) {
|
ObjectVisitor* v) {
|
||||||
IteratePointer(obj, kScopeDataOffset, v);
|
PreparseData data = PreparseData::cast(obj);
|
||||||
IteratePointers(obj, kChildDataStartOffset, object_size, v);
|
int start_offset = data->inner_start_offset();
|
||||||
|
int end_offset = start_offset + data->children_length() * kTaggedSize;
|
||||||
|
IteratePointers(obj, start_offset, end_offset, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int SizeOf(Map map, HeapObject obj) {
|
static inline int SizeOf(Map map, HeapObject obj) {
|
||||||
return PreparseData::SizeFor(PreparseData::cast(obj)->length());
|
PreparseData data = PreparseData::cast(obj);
|
||||||
|
return PreparseData::SizeFor(data->data_length(), data->children_length());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2033,12 +2033,12 @@ void StackFrameInfo::StackFrameInfoVerify(Isolate* isolate) {
|
|||||||
|
|
||||||
void PreparseData::PreparseDataVerify(Isolate* isolate) {
|
void PreparseData::PreparseDataVerify(Isolate* isolate) {
|
||||||
CHECK(IsPreparseData());
|
CHECK(IsPreparseData());
|
||||||
CHECK(scope_data()->IsByteArray());
|
CHECK_LE(0, data_length());
|
||||||
CHECK_GE(length(), 0);
|
CHECK_LE(0, children_length());
|
||||||
|
|
||||||
for (int i = 0; i < length(); ++i) {
|
for (int i = 0; i < children_length(); ++i) {
|
||||||
Object child = child_data(i);
|
Object child = get_child_raw(i);
|
||||||
CHECK(child->IsPreparseData() || child->IsNull());
|
CHECK(child->IsNull() || child->IsPreparseData());
|
||||||
VerifyPointer(isolate, child);
|
VerifyPointer(isolate, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1084,7 +1084,8 @@ int HeapObject::SizeFromMap(Map map) const {
|
|||||||
return BigInt::SizeFor(BigInt::unchecked_cast(*this)->length());
|
return BigInt::SizeFor(BigInt::unchecked_cast(*this)->length());
|
||||||
}
|
}
|
||||||
if (instance_type == PREPARSE_DATA_TYPE) {
|
if (instance_type == PREPARSE_DATA_TYPE) {
|
||||||
return PreparseData::SizeFor(PreparseData::unchecked_cast(*this)->length());
|
PreparseData data = PreparseData::unchecked_cast(*this);
|
||||||
|
return PreparseData::SizeFor(data->data_length(), data->children_length());
|
||||||
}
|
}
|
||||||
if (instance_type == CODE_TYPE) {
|
if (instance_type == CODE_TYPE) {
|
||||||
return Code::unchecked_cast(*this)->CodeSize();
|
return Code::unchecked_cast(*this)->CodeSize();
|
||||||
|
@ -2252,10 +2252,10 @@ void LayoutDescriptor::Print(std::ostream& os) { // NOLINT
|
|||||||
|
|
||||||
void PreparseData::PreparseDataPrint(std::ostream& os) { // NOLINT
|
void PreparseData::PreparseDataPrint(std::ostream& os) { // NOLINT
|
||||||
PrintHeader(os, "PreparseData");
|
PrintHeader(os, "PreparseData");
|
||||||
os << "\n - scope_data: " << Brief(scope_data());
|
os << "\n - data_length: " << data_length();
|
||||||
os << "\n - length: " << length();
|
os << "\n - children_length: " << children_length();
|
||||||
for (int i = 0; i < length(); ++i) {
|
for (int i = 0; i < children_length(); ++i) {
|
||||||
os << "\n - [" << i << "]: " << Brief(child_data(i));
|
os << "\n - [" << i << "]: " << Brief(get_child(i));
|
||||||
}
|
}
|
||||||
os << "\n";
|
os << "\n";
|
||||||
}
|
}
|
||||||
|
@ -3600,7 +3600,8 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
|
|||||||
|
|
||||||
case PREPARSE_DATA_TYPE: {
|
case PREPARSE_DATA_TYPE: {
|
||||||
PreparseData data = PreparseData::cast(*this);
|
PreparseData data = PreparseData::cast(*this);
|
||||||
os << "<PreparseData[" << data->length() << "]>";
|
os << "<PreparseData[data=" << data->data_length()
|
||||||
|
<< " children=" << data->children_length() << "]>";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,35 +24,64 @@ namespace internal {
|
|||||||
OBJECT_CONSTRUCTORS_IMPL(PreparseData, HeapObject)
|
OBJECT_CONSTRUCTORS_IMPL(PreparseData, HeapObject)
|
||||||
|
|
||||||
CAST_ACCESSOR(PreparseData)
|
CAST_ACCESSOR(PreparseData)
|
||||||
ACCESSORS(PreparseData, scope_data, PodArray<uint8_t>, kScopeDataOffset)
|
INT_ACCESSORS(PreparseData, data_length, kDataLengthOffset)
|
||||||
INT_ACCESSORS(PreparseData, length, kLengthOffset)
|
INT_ACCESSORS(PreparseData, children_length, kInnerLengthOffset)
|
||||||
|
|
||||||
Object PreparseData::child_data(int index) const {
|
int PreparseData::inner_start_offset() const {
|
||||||
DCHECK_GE(index, 0);
|
return InnerOffset(data_length());
|
||||||
DCHECK_LT(index, this->length());
|
|
||||||
int offset = kChildDataStartOffset + index * kTaggedSize;
|
|
||||||
return RELAXED_READ_FIELD(*this, offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreparseData::set_child_data(int index, Object value,
|
ObjectSlot PreparseData::inner_data_start() const {
|
||||||
WriteBarrierMode mode) {
|
return RawField(inner_start_offset());
|
||||||
DCHECK_GE(index, 0);
|
|
||||||
DCHECK_LT(index, this->length());
|
|
||||||
int offset = kChildDataStartOffset + index * kTaggedSize;
|
|
||||||
RELAXED_WRITE_FIELD(*this, offset, value);
|
|
||||||
CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectSlot PreparseData::child_data_start() const {
|
|
||||||
return RawField(kChildDataStartOffset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreparseData::clear_padding() {
|
void PreparseData::clear_padding() {
|
||||||
if (FIELD_SIZE(kOptionalPaddingOffset) != 0) {
|
int data_end_offset = kDataStartOffset + data_length();
|
||||||
DCHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset));
|
int padding_size = inner_start_offset() - data_end_offset;
|
||||||
memset(reinterpret_cast<void*>(address() + kOptionalPaddingOffset), 0,
|
DCHECK_LE(0, padding_size);
|
||||||
FIELD_SIZE(kOptionalPaddingOffset));
|
if (padding_size == 0) return;
|
||||||
}
|
memset(reinterpret_cast<void*>(address() + data_end_offset), 0, padding_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte PreparseData::get(int index) const {
|
||||||
|
DCHECK_LE(0, index);
|
||||||
|
DCHECK_LT(index, data_length());
|
||||||
|
int offset = kDataStartOffset + index * kByteSize;
|
||||||
|
return READ_BYTE_FIELD(*this, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreparseData::set(int index, byte value) {
|
||||||
|
DCHECK_LE(0, index);
|
||||||
|
DCHECK_LT(index, data_length());
|
||||||
|
int offset = kDataStartOffset + index * kByteSize;
|
||||||
|
WRITE_BYTE_FIELD(*this, offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreparseData::copy_in(int index, const byte* buffer, int length) {
|
||||||
|
DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
|
||||||
|
index + length <= this->data_length());
|
||||||
|
Address dst_addr = FIELD_ADDR(this, kDataStartOffset + index * kByteSize);
|
||||||
|
memcpy(reinterpret_cast<void*>(dst_addr), buffer, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
PreparseData PreparseData::get_child(int index) const {
|
||||||
|
return PreparseData::cast(get_child_raw(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
Object PreparseData::get_child_raw(int index) const {
|
||||||
|
DCHECK_LE(0, index);
|
||||||
|
DCHECK_LT(index, this->children_length());
|
||||||
|
int offset = inner_start_offset() + index * kTaggedSize;
|
||||||
|
return RELAXED_READ_FIELD(*this, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreparseData::set_child(int index, PreparseData value,
|
||||||
|
WriteBarrierMode mode) {
|
||||||
|
DCHECK_LE(0, index);
|
||||||
|
DCHECK_LT(index, this->children_length());
|
||||||
|
int offset = inner_start_offset() + index * kTaggedSize;
|
||||||
|
RELAXED_WRITE_FIELD(*this, offset, value);
|
||||||
|
CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
OBJECT_CONSTRUCTORS_IMPL(UncompiledData, HeapObject)
|
OBJECT_CONSTRUCTORS_IMPL(UncompiledData, HeapObject)
|
||||||
@ -65,11 +94,10 @@ INT32_ACCESSORS(UncompiledData, end_position, kEndPositionOffset)
|
|||||||
INT32_ACCESSORS(UncompiledData, function_literal_id, kFunctionLiteralIdOffset)
|
INT32_ACCESSORS(UncompiledData, function_literal_id, kFunctionLiteralIdOffset)
|
||||||
|
|
||||||
void UncompiledData::clear_padding() {
|
void UncompiledData::clear_padding() {
|
||||||
if (FIELD_SIZE(kOptionalPaddingOffset) != 0) {
|
if (FIELD_SIZE(kOptionalPaddingOffset) == 0) return;
|
||||||
DCHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset));
|
DCHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset));
|
||||||
memset(reinterpret_cast<void*>(address() + kOptionalPaddingOffset), 0,
|
memset(reinterpret_cast<void*>(address() + kOptionalPaddingOffset), 0,
|
||||||
FIELD_SIZE(kOptionalPaddingOffset));
|
FIELD_SIZE(kOptionalPaddingOffset));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CAST_ACCESSOR(UncompiledDataWithoutPreparseData)
|
CAST_ACCESSOR(UncompiledDataWithoutPreparseData)
|
||||||
|
@ -27,16 +27,37 @@ class WasmExportedFunctionData;
|
|||||||
|
|
||||||
// Data collected by the pre-parser storing information about scopes and inner
|
// Data collected by the pre-parser storing information about scopes and inner
|
||||||
// functions.
|
// functions.
|
||||||
|
//
|
||||||
|
// PreparseData Layout:
|
||||||
|
// +-------------------------------+
|
||||||
|
// | data_length | children_length |
|
||||||
|
// +-------------------------------+
|
||||||
|
// | Scope Byte Data ... |
|
||||||
|
// | ... |
|
||||||
|
// +-------------------------------+
|
||||||
|
// | [Padding] |
|
||||||
|
// +-------------------------------+
|
||||||
|
// | Inner PreparseData 1 |
|
||||||
|
// +-------------------------------+
|
||||||
|
// | ... |
|
||||||
|
// +-------------------------------+
|
||||||
|
// | Inner PreparseData N |
|
||||||
|
// +-------------------------------+
|
||||||
class PreparseData : public HeapObject {
|
class PreparseData : public HeapObject {
|
||||||
public:
|
public:
|
||||||
DECL_ACCESSORS(scope_data, PodArray<uint8_t>)
|
DECL_INT_ACCESSORS(data_length)
|
||||||
DECL_INT_ACCESSORS(length)
|
DECL_INT_ACCESSORS(children_length)
|
||||||
|
|
||||||
inline Object child_data(int index) const;
|
inline int inner_start_offset() const;
|
||||||
inline void set_child_data(int index, Object value,
|
inline ObjectSlot inner_data_start() const;
|
||||||
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
|
||||||
|
|
||||||
inline ObjectSlot child_data_start() const;
|
inline byte get(int index) const;
|
||||||
|
inline void set(int index, byte value);
|
||||||
|
inline void copy_in(int index, const byte* buffer, int length);
|
||||||
|
|
||||||
|
inline PreparseData get_child(int index) const;
|
||||||
|
inline void set_child(int index, PreparseData value,
|
||||||
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
||||||
|
|
||||||
// Clear uninitialized padding space.
|
// Clear uninitialized padding space.
|
||||||
inline void clear_padding();
|
inline void clear_padding();
|
||||||
@ -46,23 +67,30 @@ class PreparseData : public HeapObject {
|
|||||||
DECL_VERIFIER(PreparseData)
|
DECL_VERIFIER(PreparseData)
|
||||||
|
|
||||||
// Layout description.
|
// Layout description.
|
||||||
#define PREPARSE_DATA_FIELDS(V) \
|
#define PREPARSE_DATA_FIELDS(V) \
|
||||||
V(kScopeDataOffset, kTaggedSize) \
|
V(kDataLengthOffset, kInt32Size) \
|
||||||
V(kLengthOffset, kIntSize) \
|
V(kInnerLengthOffset, kInt32Size) \
|
||||||
V(kOptionalPaddingOffset, POINTER_SIZE_PADDING(kOptionalPaddingOffset)) \
|
/* Header size. */ \
|
||||||
/* Header size. */ \
|
V(kDataStartOffset, 0) \
|
||||||
V(kChildDataStartOffset, 0)
|
V(kHeaderSize, 0)
|
||||||
|
|
||||||
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, PREPARSE_DATA_FIELDS)
|
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, PREPARSE_DATA_FIELDS)
|
||||||
#undef PREPARSE_DATA_FIELDS
|
#undef PREPARSE_DATA_FIELDS
|
||||||
|
|
||||||
class BodyDescriptor;
|
class BodyDescriptor;
|
||||||
|
|
||||||
static constexpr int SizeFor(int length) {
|
static int InnerOffset(int data_length) {
|
||||||
return kChildDataStartOffset + length * kTaggedSize;
|
return RoundUp(kDataStartOffset + data_length * kByteSize, kTaggedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int SizeFor(int data_length, int children_length) {
|
||||||
|
return InnerOffset(data_length) + children_length * kTaggedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBJECT_CONSTRUCTORS(PreparseData, HeapObject);
|
OBJECT_CONSTRUCTORS(PreparseData, HeapObject);
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline Object get_child_raw(int index) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Abstract class representing extra data for an uncompiled function, which is
|
// Abstract class representing extra data for an uncompiled function, which is
|
||||||
@ -84,7 +112,6 @@ class UncompiledData : public HeapObject {
|
|||||||
[](HeapObject object, ObjectSlot slot, HeapObject target) {});
|
[](HeapObject object, ObjectSlot slot, HeapObject target) {});
|
||||||
|
|
||||||
// Layout description.
|
// Layout description.
|
||||||
|
|
||||||
#define UNCOMPILED_DATA_FIELDS(V) \
|
#define UNCOMPILED_DATA_FIELDS(V) \
|
||||||
V(kStartOfPointerFieldsOffset, 0) \
|
V(kStartOfPointerFieldsOffset, 0) \
|
||||||
V(kInferredNameOffset, kTaggedSize) \
|
V(kInferredNameOffset, kTaggedSize) \
|
||||||
|
@ -47,7 +47,7 @@ class PreparseDataBuilder::ByteData : public ZoneObject,
|
|||||||
void OverwriteFirstUint32(uint32_t data);
|
void OverwriteFirstUint32(uint32_t data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Handle<PodArray<uint8_t>> Serialize(Isolate* isolate);
|
void StoreInto(PreparseData data);
|
||||||
|
|
||||||
size_t size() const { return backing_store_.size(); }
|
size_t size() const { return backing_store_.size(); }
|
||||||
|
|
||||||
@ -60,6 +60,21 @@ class PreparseDataBuilder::ByteData : public ZoneObject,
|
|||||||
ZoneChunkList<uint8_t> backing_store_;
|
ZoneChunkList<uint8_t> backing_store_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Wraps a ZoneVector<uint8_t> to have with functions named the same as
|
||||||
|
// PodArray<uint8_t>.
|
||||||
|
class ZoneVectorWrapper {
|
||||||
|
public:
|
||||||
|
ZoneVectorWrapper() = default;
|
||||||
|
explicit ZoneVectorWrapper(ZoneVector<uint8_t>* data) : data_(data) {}
|
||||||
|
|
||||||
|
int data_length() const { return static_cast<int>(data_->size()); }
|
||||||
|
|
||||||
|
uint8_t get(int index) const { return data_->at(index); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ZoneVector<uint8_t>* data_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
template <class Data>
|
template <class Data>
|
||||||
class BaseConsumedPreparseData : public ConsumedPreparseData {
|
class BaseConsumedPreparseData : public ConsumedPreparseData {
|
||||||
public:
|
public:
|
||||||
@ -93,19 +108,19 @@ class BaseConsumedPreparseData : public ConsumedPreparseData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void SetPosition(int position) {
|
void SetPosition(int position) {
|
||||||
DCHECK_LE(position, data_.length());
|
DCHECK_LE(position, data_.data_length());
|
||||||
index_ = position;
|
index_ = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RemainingBytes() const {
|
size_t RemainingBytes() const {
|
||||||
DCHECK(has_data_);
|
DCHECK(has_data_);
|
||||||
DCHECK_LE(index_, data_.length());
|
DCHECK_LE(index_, data_.data_length());
|
||||||
return data_.length() - index_;
|
return data_.data_length() - index_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasRemainingBytes(size_t bytes) const {
|
bool HasRemainingBytes(size_t bytes) const {
|
||||||
DCHECK(has_data_);
|
DCHECK(has_data_);
|
||||||
return index_ <= data_.length() && bytes <= RemainingBytes();
|
return index_ <= data_.data_length() && bytes <= RemainingBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ReadUint32() {
|
int32_t ReadUint32() {
|
||||||
@ -188,33 +203,18 @@ class BaseConsumedPreparseData : public ConsumedPreparseData {
|
|||||||
|
|
||||||
// Implementation of ConsumedPreparseData for on-heap data.
|
// Implementation of ConsumedPreparseData for on-heap data.
|
||||||
class OnHeapConsumedPreparseData final
|
class OnHeapConsumedPreparseData final
|
||||||
: public BaseConsumedPreparseData<PodArray<uint8_t>> {
|
: public BaseConsumedPreparseData<PreparseData> {
|
||||||
public:
|
public:
|
||||||
OnHeapConsumedPreparseData(Isolate* isolate, Handle<PreparseData> data);
|
OnHeapConsumedPreparseData(Isolate* isolate, Handle<PreparseData> data);
|
||||||
|
|
||||||
PodArray<uint8_t> GetScopeData() final;
|
PreparseData GetScopeData() final;
|
||||||
ProducedPreparseData* GetChildData(Zone* zone, int child_index) final;
|
ProducedPreparseData* GetChildData(Zone* zone, int index) final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Isolate* isolate_;
|
Isolate* isolate_;
|
||||||
Handle<PreparseData> data_;
|
Handle<PreparseData> data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wraps a ZoneVector<uint8_t> to have with functions named the same as
|
|
||||||
// PodArray<uint8_t>.
|
|
||||||
class ZoneVectorWrapper {
|
|
||||||
public:
|
|
||||||
ZoneVectorWrapper() = default;
|
|
||||||
explicit ZoneVectorWrapper(ZoneVector<uint8_t>* data) : data_(data) {}
|
|
||||||
|
|
||||||
int length() const { return static_cast<int>(data_->size()); }
|
|
||||||
|
|
||||||
uint8_t get(int index) const { return data_->at(index); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
ZoneVector<uint8_t>* data_ = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A serialized PreparseData in zone memory (as apposed to being on-heap).
|
// A serialized PreparseData in zone memory (as apposed to being on-heap).
|
||||||
class ZonePreparseData : public ZoneObject {
|
class ZonePreparseData : public ZoneObject {
|
||||||
public:
|
public:
|
||||||
|
@ -135,19 +135,12 @@ void PreparseDataBuilder::ByteData::WriteQuarter(uint8_t data) {
|
|||||||
backing_store_.back() |= (data << shift_amount);
|
backing_store_.back() |= (data << shift_amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<PodArray<uint8_t>> PreparseDataBuilder::ByteData::Serialize(
|
void PreparseDataBuilder::ByteData::StoreInto(PreparseData data) {
|
||||||
Isolate* isolate) {
|
|
||||||
Handle<PodArray<uint8_t>> array = PodArray<uint8_t>::New(
|
|
||||||
isolate, static_cast<int>(backing_store_.size()), TENURED);
|
|
||||||
|
|
||||||
DisallowHeapAllocation no_gc;
|
DisallowHeapAllocation no_gc;
|
||||||
PodArray<uint8_t> raw_array = *array;
|
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (uint8_t item : backing_store_) {
|
for (uint8_t item : backing_store_) {
|
||||||
raw_array->set(i++, item);
|
data->set(i++, item);
|
||||||
}
|
}
|
||||||
return array;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PreparseDataBuilder::PreparseDataBuilder(Zone* zone,
|
PreparseDataBuilder::PreparseDataBuilder(Zone* zone,
|
||||||
@ -252,17 +245,15 @@ Handle<PreparseData> PreparseDataBuilder::Serialize(Isolate* isolate) {
|
|||||||
DCHECK(!ThisOrParentBailedOut());
|
DCHECK(!ThisOrParentBailedOut());
|
||||||
|
|
||||||
int child_data_length = static_cast<int>(data_for_inner_functions_.size());
|
int child_data_length = static_cast<int>(data_for_inner_functions_.size());
|
||||||
Handle<PreparseData> data =
|
Handle<PreparseData> data = isolate->factory()->NewPreparseData(
|
||||||
isolate->factory()->NewPreparseData(child_data_length);
|
static_cast<int>(byte_data_->size()), child_data_length);
|
||||||
|
byte_data_->StoreInto(*data);
|
||||||
Handle<PodArray<uint8_t>> scope_data_array = byte_data_->Serialize(isolate);
|
|
||||||
data->set_scope_data(*scope_data_array);
|
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const auto& item : data_for_inner_functions_) {
|
for (const auto& item : data_for_inner_functions_) {
|
||||||
DCHECK_NOT_NULL(item);
|
DCHECK_NOT_NULL(item);
|
||||||
Handle<PreparseData> child_data = item->Serialize(isolate);
|
Handle<PreparseData> child_data = item->Serialize(isolate);
|
||||||
data->set_child_data(i++, *child_data);
|
data->set_child(i++, *child_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@ -588,25 +579,18 @@ void BaseConsumedPreparseData<Data>::VerifyDataStart() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PodArray<uint8_t> OnHeapConsumedPreparseData::GetScopeData() {
|
PreparseData OnHeapConsumedPreparseData::GetScopeData() { return *data_; }
|
||||||
return data_->scope_data();
|
|
||||||
}
|
|
||||||
|
|
||||||
ProducedPreparseData* OnHeapConsumedPreparseData::GetChildData(
|
ProducedPreparseData* OnHeapConsumedPreparseData::GetChildData(Zone* zone,
|
||||||
Zone* zone, int child_index) {
|
int index) {
|
||||||
CHECK_GT(data_->length(), child_index);
|
DisallowHeapAllocation no_gc;
|
||||||
Object child_data = data_->child_data(child_index);
|
Handle<PreparseData> child_data_handle(data_->get_child(index), isolate_);
|
||||||
if (!child_data->IsPreparseData()) return nullptr;
|
|
||||||
Handle<PreparseData> child_data_handle(PreparseData::cast(child_data),
|
|
||||||
isolate_);
|
|
||||||
return ProducedPreparseData::For(child_data_handle, zone);
|
return ProducedPreparseData::For(child_data_handle, zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
OnHeapConsumedPreparseData::OnHeapConsumedPreparseData(
|
OnHeapConsumedPreparseData::OnHeapConsumedPreparseData(
|
||||||
Isolate* isolate, Handle<PreparseData> data)
|
Isolate* isolate, Handle<PreparseData> data)
|
||||||
: BaseConsumedPreparseData<PodArray<uint8_t>>(),
|
: BaseConsumedPreparseData<PreparseData>(), isolate_(isolate), data_(data) {
|
||||||
isolate_(isolate),
|
|
||||||
data_(data) {
|
|
||||||
DCHECK_NOT_NULL(isolate);
|
DCHECK_NOT_NULL(isolate);
|
||||||
DCHECK(data->IsPreparseData());
|
DCHECK(data->IsPreparseData());
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -621,22 +605,17 @@ ZonePreparseData::ZonePreparseData(Zone* zone,
|
|||||||
children_(child_length, zone) {}
|
children_(child_length, zone) {}
|
||||||
|
|
||||||
Handle<PreparseData> ZonePreparseData::Serialize(Isolate* isolate) {
|
Handle<PreparseData> ZonePreparseData::Serialize(Isolate* isolate) {
|
||||||
|
int data_size = static_cast<int>(byte_data()->size());
|
||||||
int child_data_length = child_length();
|
int child_data_length = child_length();
|
||||||
Handle<PreparseData> result =
|
Handle<PreparseData> result =
|
||||||
isolate->factory()->NewPreparseData(child_data_length);
|
isolate->factory()->NewPreparseData(data_size, child_data_length);
|
||||||
|
result->copy_in(0, byte_data()->data(), data_size);
|
||||||
Handle<PodArray<uint8_t>> scope_data_array = PodArray<uint8_t>::New(
|
|
||||||
isolate, static_cast<int>(byte_data()->size()), TENURED);
|
|
||||||
scope_data_array->copy_in(0, byte_data()->data(),
|
|
||||||
static_cast<int>(byte_data()->size()));
|
|
||||||
result->set_scope_data(*scope_data_array);
|
|
||||||
|
|
||||||
for (int i = 0; i < child_data_length; i++) {
|
for (int i = 0; i < child_data_length; i++) {
|
||||||
ZonePreparseData* child = get_child(i);
|
ZonePreparseData* child = get_child(i);
|
||||||
if (child) {
|
DCHECK_NOT_NULL(child);
|
||||||
Handle<PreparseData> child_data = child->Serialize(isolate);
|
Handle<PreparseData> child_data = child->Serialize(isolate);
|
||||||
result->set_child_data(i, *child_data);
|
result->set_child(i, *child_data);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -862,7 +862,9 @@ TEST(ProducingAndConsumingByteData) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
// Serialize as an OnHeapConsumedPreparseData, and read back data.
|
// Serialize as an OnHeapConsumedPreparseData, and read back data.
|
||||||
i::Handle<i::PodArray<uint8_t>> data_on_heap = bytes.Serialize(isolate);
|
i::Handle<i::PreparseData> data_on_heap =
|
||||||
|
isolate->factory()->NewPreparseData(static_cast<int>(bytes.size()), 0);
|
||||||
|
bytes.StoreInto(*data_on_heap);
|
||||||
i::OnHeapConsumedPreparseData::ByteData bytes_for_reading;
|
i::OnHeapConsumedPreparseData::ByteData bytes_for_reading;
|
||||||
i::OnHeapConsumedPreparseData::ByteData::ReadingScope reading_scope(
|
i::OnHeapConsumedPreparseData::ByteData::ReadingScope reading_scope(
|
||||||
&bytes_for_reading, *data_on_heap);
|
&bytes_for_reading, *data_on_heap);
|
||||||
|
Loading…
Reference in New Issue
Block a user