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

[parser] Skipping inner funcs: Make the data on heap smaller.

We were unnecessarily storing everything as uint32_t, even though many items in
the preparsed scope data can be stored as uint8_t. This CL also adds an
(internal) API which abstracts away the actual data storing, so the backing
store can be made even more efficient (e.g., use only 1-3 bytes for some
uint32_t values, if they fit) without affecting other parts of the code.

BUG=v8:5516,chromium:762492

Change-Id: I7cd4d91dc11f87f8aec9c7584044a6f2a59b73ba
Reviewed-on: https://chromium-review.googlesource.com/684182
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48231}
parent d2e22dbf
......@@ -1743,7 +1743,7 @@ Handle<ModuleInfo> Factory::NewModuleInfo() {
Handle<PreParsedScopeData> Factory::NewPreParsedScopeData() {
Handle<PreParsedScopeData> result =
Handle<PreParsedScopeData>::cast(NewStruct(TUPLE2_TYPE, TENURED));
result->set_scope_data(PodArray<uint32_t>::cast(*empty_byte_array()));
result->set_scope_data(PodArray<uint8_t>::cast(*empty_byte_array()));
result->set_child_data(*empty_fixed_array());
return result;
}
......
......@@ -16,7 +16,7 @@ namespace v8 {
namespace internal {
CAST_ACCESSOR(PreParsedScopeData)
ACCESSORS(PreParsedScopeData, scope_data, PodArray<uint32_t>, kScopeDataOffset)
ACCESSORS(PreParsedScopeData, scope_data, PodArray<uint8_t>, kScopeDataOffset)
ACCESSORS(PreParsedScopeData, child_data, FixedArray, kChildDataOffset)
TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
......
......@@ -19,7 +19,7 @@ class DebugInfo;
class PreParsedScopeData : public Struct {
public:
DECL_ACCESSORS(scope_data, PodArray<uint32_t>)
DECL_ACCESSORS(scope_data, PodArray<uint8_t>)
DECL_ACCESSORS(child_data, FixedArray)
static const int kScopeDataOffset = Struct::kHeaderSize;
......
This diff is collapsed.
......@@ -67,29 +67,31 @@ class PreParsedScopeData;
class ProducedPreParsedScopeData : public ZoneObject {
public:
class ByteData : public ZoneObject {
public:
explicit ByteData(Zone* zone) : backing_store_(zone) {}
void WriteUint32(uint32_t data);
void WriteUint8(uint8_t data);
// For overwriting previously written data at position 0.
void OverwriteFirstUint32(uint32_t data);
Handle<PodArray<uint8_t>> Serialize(Isolate* isolate) const;
size_t size() const { return backing_store_.size(); }
private:
ZoneDeque<uint8_t> backing_store_;
};
// Create a ProducedPreParsedScopeData object which will collect data as we
// parse.
explicit ProducedPreParsedScopeData(Zone* zone,
ProducedPreParsedScopeData* parent)
: parent_(parent),
backing_store_(zone),
data_for_inner_functions_(zone),
scope_data_start_(-1),
bailed_out_(false) {
if (parent != nullptr) {
parent->data_for_inner_functions_.push_back(this);
}
}
ProducedPreParsedScopeData(Zone* zone, ProducedPreParsedScopeData* parent);
// Create a ProducedPreParsedScopeData which is just a proxy for a previous
// produced PreParsedScopeData.
ProducedPreParsedScopeData(Handle<PreParsedScopeData> data, Zone* zone)
: parent_(nullptr),
backing_store_(zone),
data_for_inner_functions_(zone),
scope_data_start_(-1),
bailed_out_(false),
previously_produced_preparsed_scope_data_(data) {}
ProducedPreParsedScopeData(Handle<PreParsedScopeData> data, Zone* zone);
ProducedPreParsedScopeData* parent() const { return parent_; }
......@@ -160,14 +162,8 @@ class ProducedPreParsedScopeData : public ZoneObject {
ProducedPreParsedScopeData* parent_;
// TODO(marja): Make the backing store more efficient once we know exactly
// what data is needed.
ZoneDeque<uint32_t> backing_store_;
ByteData* byte_data_;
ZoneDeque<ProducedPreParsedScopeData*> data_for_inner_functions_;
// The backing store contains data about inner functions and then data about
// this scope's (and its subscopes') variables. scope_data_start_ marks where
// the latter starts.
int scope_data_start_;
// Whether we've given up producing the data for this function.
bool bailed_out_;
......@@ -181,10 +177,44 @@ class ProducedPreParsedScopeData : public ZoneObject {
class ConsumedPreParsedScopeData {
public:
// Real data starts from index 1 (see data format description in the .cc
// file).
ConsumedPreParsedScopeData() : index_(1), child_index_(0) {}
~ConsumedPreParsedScopeData() {}
class ByteData {
public:
ByteData() : data_(nullptr), index_(0) {}
// Reading from the ByteData is only allowed when a ReadingScope is on the
// stack. This ensures that we have a DisallowHeapAllocation in place
// whenever ByteData holds a raw pointer into the heap.
class ReadingScope {
public:
ReadingScope(ByteData* consumed_data, PodArray<uint8_t>* data)
: consumed_data_(consumed_data) {
consumed_data->data_ = data;
}
explicit ReadingScope(ConsumedPreParsedScopeData* parent);
~ReadingScope() { consumed_data_->data_ = nullptr; }
private:
ByteData* consumed_data_;
DisallowHeapAllocation no_gc;
};
void SetPosition(int position) { index_ = position; }
int32_t ReadUint32();
uint8_t ReadUint8();
size_t RemainingBytes() const {
DCHECK_NOT_NULL(data_);
return data_->length() - index_;
}
// private:
PodArray<uint8_t>* data_;
int index_;
};
ConsumedPreParsedScopeData();
~ConsumedPreParsedScopeData();
void SetData(Handle<PreParsedScopeData> data);
......@@ -205,14 +235,14 @@ class ConsumedPreParsedScopeData {
void SkipFunctionDataForTesting();
private:
void RestoreData(Scope* scope, PodArray<uint32_t>* scope_data);
void RestoreDataForVariable(Variable* var, PodArray<uint32_t>* scope_data);
void RestoreDataForInnerScopes(Scope* scope, PodArray<uint32_t>* scope_data);
void RestoreData(Scope* scope);
void RestoreDataForVariable(Variable* var);
void RestoreDataForInnerScopes(Scope* scope);
Handle<PreParsedScopeData> data_;
std::unique_ptr<ByteData> scope_data_;
// When consuming the data, these indexes point to the data we're going to
// consume next.
int index_;
int child_index_;
DISALLOW_COPY_AND_ASSIGN(ConsumedPreParsedScopeData);
......
......@@ -799,3 +799,35 @@ TEST(Regress753896) {
// error is not detected inside lazy functions, but it might be in the future.
i::parsing::ParseProgram(&info, isolate);
}
TEST(ProducingAndConsumingByteData) {
i::Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate);
LocalContext env;
i::Zone zone(isolate->allocator(), ZONE_NAME);
i::ProducedPreParsedScopeData::ByteData bytes(&zone);
// Write some data.
bytes.WriteUint32(1983); // This will be overwritten.
bytes.WriteUint32(2147483647);
bytes.WriteUint8(4);
bytes.WriteUint8(255);
bytes.WriteUint32(0);
bytes.WriteUint8(0);
bytes.OverwriteFirstUint32(2017);
bytes.WriteUint8(100);
i::Handle<i::PodArray<uint8_t>> data_on_heap = bytes.Serialize(isolate);
i::ConsumedPreParsedScopeData::ByteData bytes_for_reading;
i::ConsumedPreParsedScopeData::ByteData::ReadingScope reading_scope(
&bytes_for_reading, *data_on_heap);
// Read the data back.
CHECK_EQ(bytes_for_reading.ReadUint32(), 2017);
CHECK_EQ(bytes_for_reading.ReadUint32(), 2147483647);
CHECK_EQ(bytes_for_reading.ReadUint8(), 4);
CHECK_EQ(bytes_for_reading.ReadUint8(), 255);
CHECK_EQ(bytes_for_reading.ReadUint32(), 0);
CHECK_EQ(bytes_for_reading.ReadUint8(), 0);
CHECK_EQ(bytes_for_reading.ReadUint8(), 100);
}
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