Commit 61b217b1 authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[parser] Use shared data buffer for PreparseData generation

By using a shared byte buffer on the preparser we can drastically
reduce the number of ZoneChunkLists.

Each PreparseDataBuilder now explicitly keeps track of all inner
builders/functions and writes out the data in consecutive order.

Change-Id: I0aada118d869b150108c1f633d9960474ad2f9a1
Reviewed-on: https://chromium-review.googlesource.com/c/1411600
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58926}
parent 1a95d4de
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "src/objects/module-inl.h" #include "src/objects/module-inl.h"
#include "src/objects/scope-info.h" #include "src/objects/scope-info.h"
#include "src/parsing/parse-info.h" #include "src/parsing/parse-info.h"
#include "src/parsing/parser.h"
#include "src/parsing/preparse-data.h" #include "src/parsing/preparse-data.h"
#include "src/zone/zone-list-inl.h" #include "src/zone/zone-list-inl.h"
...@@ -1417,28 +1418,29 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory, ...@@ -1417,28 +1418,29 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
was_lazily_parsed_ = !aborted; was_lazily_parsed_ = !aborted;
} }
void Scope::SavePreparseData() { void Scope::SavePreparseData(Parser* parser) {
if (PreparseDataBuilder::ScopeIsSkippableFunctionScope(this)) { if (PreparseDataBuilder::ScopeIsSkippableFunctionScope(this)) {
AsDeclarationScope()->SavePreparseDataForDeclarationScope(); AsDeclarationScope()->SavePreparseDataForDeclarationScope(parser);
} }
for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
scope->SavePreparseData(); scope->SavePreparseData(parser);
} }
} }
void DeclarationScope::SavePreparseDataForDeclarationScope() { void DeclarationScope::SavePreparseDataForDeclarationScope(Parser* parser) {
if (preparse_data_builder_ == nullptr) return; if (preparse_data_builder_ == nullptr) return;
preparse_data_builder_->SaveScopeAllocationData(this); preparse_data_builder_->SaveScopeAllocationData(this, parser);
} }
void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) { void DeclarationScope::AnalyzePartially(Parser* parser,
AstNodeFactory* ast_node_factory) {
DCHECK(!force_eager_compilation_); DCHECK(!force_eager_compilation_);
UnresolvedList new_unresolved_list; UnresolvedList new_unresolved_list;
if (!IsArrowFunction(function_kind_) && if (!IsArrowFunction(function_kind_) &&
(!outer_scope_->is_script_scope() || (!outer_scope_->is_script_scope() ||
(preparse_data_builder_ != nullptr && (preparse_data_builder_ != nullptr &&
preparse_data_builder_->ContainsInnerFunctions()))) { preparse_data_builder_->HasInnerFunctions()))) {
// Try to resolve unresolved variables for this Scope and migrate those // Try to resolve unresolved variables for this Scope and migrate those
// which cannot be resolved inside. It doesn't make sense to try to resolve // which cannot be resolved inside. It doesn't make sense to try to resolve
// them in the outer Scopes here, because they are incomplete. // them in the outer Scopes here, because they are incomplete.
...@@ -1449,7 +1451,7 @@ void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) { ...@@ -1449,7 +1451,7 @@ void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) {
function_ = ast_node_factory->CopyVariable(function_); function_ = ast_node_factory->CopyVariable(function_);
} }
SavePreparseData(); SavePreparseData(parser);
} }
#ifdef DEBUG #ifdef DEBUG
......
...@@ -21,6 +21,7 @@ class AstValueFactory; ...@@ -21,6 +21,7 @@ class AstValueFactory;
class AstRawString; class AstRawString;
class Declaration; class Declaration;
class ParseInfo; class ParseInfo;
class Parser;
class PreparseDataBuilder; class PreparseDataBuilder;
class SloppyBlockFunctionStatement; class SloppyBlockFunctionStatement;
class Statement; class Statement;
...@@ -571,7 +572,7 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { ...@@ -571,7 +572,7 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
// Walk the scope chain to find DeclarationScopes; call // Walk the scope chain to find DeclarationScopes; call
// SavePreparseDataForDeclarationScope for each. // SavePreparseDataForDeclarationScope for each.
void SavePreparseData(); void SavePreparseData(Parser* parser);
// Create a non-local variable with a given name. // Create a non-local variable with a given name.
// These variables are looked up dynamically at runtime. // These variables are looked up dynamically at runtime.
...@@ -949,7 +950,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope { ...@@ -949,7 +950,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
// this records variables which cannot be resolved inside the Scope (we don't // this records variables which cannot be resolved inside the Scope (we don't
// yet know what they will resolve to since the outer Scopes are incomplete) // yet know what they will resolve to since the outer Scopes are incomplete)
// and recreates them with the correct Zone with ast_node_factory. // and recreates them with the correct Zone with ast_node_factory.
void AnalyzePartially(AstNodeFactory* ast_node_factory); void AnalyzePartially(Parser* parser, AstNodeFactory* ast_node_factory);
// Allocate ScopeInfos for top scope and any inner scopes that need them. // Allocate ScopeInfos for top scope and any inner scopes that need them.
// Does nothing if ScopeInfo is already allocated. // Does nothing if ScopeInfo is already allocated.
...@@ -998,7 +999,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope { ...@@ -998,7 +999,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
// Save data describing the context allocation of the variables in this scope // Save data describing the context allocation of the variables in this scope
// and its subscopes (except scopes at the laziness boundary). The data is // and its subscopes (except scopes at the laziness boundary). The data is
// saved in produced_preparse_data_. // saved in produced_preparse_data_.
void SavePreparseDataForDeclarationScope(); void SavePreparseDataForDeclarationScope(Parser* parser);
void set_preparse_data_builder(PreparseDataBuilder* preparse_data_builder) { void set_preparse_data_builder(PreparseDataBuilder* preparse_data_builder) {
preparse_data_builder_ = preparse_data_builder; preparse_data_builder_ = preparse_data_builder;
......
...@@ -560,15 +560,20 @@ class PodArray : public ByteArray { ...@@ -560,15 +560,20 @@ class PodArray : public ByteArray {
ByteArray::copy_out(index * sizeof(T), reinterpret_cast<byte*>(result), ByteArray::copy_out(index * sizeof(T), reinterpret_cast<byte*>(result),
sizeof(T)); sizeof(T));
} }
void copy_in(int index, const T* buffer, int length) {
ByteArray::copy_in(index * sizeof(T), reinterpret_cast<const byte*>(buffer),
length * sizeof(T));
}
T get(int index) { T get(int index) {
T result; T result;
copy_out(index, &result); copy_out(index, &result);
return result; return result;
} }
void set(int index, const T& value) {
copy_in(index * sizeof(T), reinterpret_cast<const byte*>(&value), void set(int index, const T& value) { copy_in(index, &value, 1); }
sizeof(T));
}
inline int length() const; inline int length() const;
DECL_CAST(PodArray<T>) DECL_CAST(PodArray<T>)
......
...@@ -395,6 +395,7 @@ Parser::Parser(ParseInfo* info) ...@@ -395,6 +395,7 @@ Parser::Parser(ParseInfo* info)
target_stack_(nullptr), target_stack_(nullptr),
total_preparse_skipped_(0), total_preparse_skipped_(0),
consumed_preparse_data_(info->consumed_preparse_data()), consumed_preparse_data_(info->consumed_preparse_data()),
preparse_data_buffer_(),
parameters_end_pos_(info->parameters_end_pos()) { parameters_end_pos_(info->parameters_end_pos()) {
// Even though we were passed ParseInfo, we should not store it in // Even though we were passed ParseInfo, we should not store it in
// Parser - this makes sure that Isolate is not accidentally accessed via // Parser - this makes sure that Isolate is not accidentally accessed via
...@@ -2545,7 +2546,7 @@ bool Parser::SkipFunction(const AstRawString* function_name, FunctionKind kind, ...@@ -2545,7 +2546,7 @@ bool Parser::SkipFunction(const AstRawString* function_name, FunctionKind kind,
function_scope->end_position() - function_scope->start_position(); function_scope->end_position() - function_scope->start_position();
*num_parameters = logger->num_parameters(); *num_parameters = logger->num_parameters();
SkipFunctionLiterals(logger->num_inner_functions()); SkipFunctionLiterals(logger->num_inner_functions());
function_scope->AnalyzePartially(factory()); function_scope->AnalyzePartially(this, factory());
} }
return true; return true;
......
...@@ -282,6 +282,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { ...@@ -282,6 +282,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
SET_ALLOW(harmony_private_methods); SET_ALLOW(harmony_private_methods);
SET_ALLOW(eval_cache); SET_ALLOW(eval_cache);
#undef SET_ALLOW #undef SET_ALLOW
preparse_data_buffer_.reserve(128);
} }
return reusable_preparser_; return reusable_preparser_;
} }
...@@ -1055,8 +1056,13 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { ...@@ -1055,8 +1056,13 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
ParseInfo* info() const { return info_; } ParseInfo* info() const { return info_; }
std::vector<uint8_t>* preparse_data_buffer() {
return &preparse_data_buffer_;
}
// Parser's private field members. // Parser's private field members.
friend class PreParserZoneScope; // Uses reusable_preparser(). friend class PreParserZoneScope; // Uses reusable_preparser().
friend class PreparseDataBuilder; // Uses preparse_data_buffer()
ParseInfo* info_; ParseInfo* info_;
Scanner scanner_; Scanner scanner_;
...@@ -1082,6 +1088,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { ...@@ -1082,6 +1088,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
bool allow_lazy_; bool allow_lazy_;
bool temp_zoned_; bool temp_zoned_;
ConsumedPreparseData* consumed_preparse_data_; ConsumedPreparseData* consumed_preparse_data_;
std::vector<uint8_t> preparse_data_buffer_;
// If not kNoSourcePosition, indicates that the first function literal // If not kNoSourcePosition, indicates that the first function literal
// encountered is a dynamic function, see CreateDynamicFunction(). This field // encountered is a dynamic function, see CreateDynamicFunction(). This field
......
...@@ -15,51 +15,6 @@ namespace internal { ...@@ -15,51 +15,6 @@ namespace internal {
// Classes which are internal to prepared-scope-data.cc, but are exposed in // Classes which are internal to prepared-scope-data.cc, but are exposed in
// a header for tests. // a header for tests.
struct PreparseByteDataConstants {
#ifdef DEBUG
static constexpr int kMagicValue = 0xC0DE0DE;
static constexpr size_t kUint32Size = 5;
static constexpr size_t kUint8Size = 2;
static constexpr size_t kQuarterMarker = 0;
static constexpr size_t kPlaceholderSize = kUint32Size;
#else
static constexpr size_t kUint32Size = 4;
static constexpr size_t kUint8Size = 1;
static constexpr size_t kPlaceholderSize = 0;
#endif
static const size_t kSkippableFunctionDataSize =
4 * kUint32Size + 1 * kUint8Size;
};
class PreparseDataBuilder::ByteData : public ZoneObject,
public PreparseByteDataConstants {
public:
explicit ByteData(Zone* zone)
: free_quarters_in_last_byte_(0), backing_store_(zone) {}
void WriteUint32(uint32_t data);
void WriteUint8(uint8_t data);
void WriteQuarter(uint8_t data);
#ifdef DEBUG
// For overwriting previously written data at position 0.
void OverwriteFirstUint32(uint32_t data);
#endif
void StoreInto(PreparseData data);
size_t size() const { return backing_store_.size(); }
ZoneChunkList<uint8_t>::iterator begin() { return backing_store_.begin(); }
ZoneChunkList<uint8_t>::iterator end() { return backing_store_.end(); }
private:
uint8_t free_quarters_in_last_byte_;
ZoneChunkList<uint8_t> backing_store_;
};
// Wraps a ZoneVector<uint8_t> to have with functions named the same as // Wraps a ZoneVector<uint8_t> to have with functions named the same as
// PodArray<uint8_t>. // PodArray<uint8_t>.
class ZoneVectorWrapper { class ZoneVectorWrapper {
...@@ -124,6 +79,7 @@ class BaseConsumedPreparseData : public ConsumedPreparseData { ...@@ -124,6 +79,7 @@ class BaseConsumedPreparseData : public ConsumedPreparseData {
} }
int32_t ReadUint32() { int32_t ReadUint32() {
DCHECK(has_data_);
DCHECK(HasRemainingBytes(kUint32Size)); DCHECK(HasRemainingBytes(kUint32Size));
// Check that there indeed is an integer following. // Check that there indeed is an integer following.
DCHECK_EQ(data_.get(index_++), kUint32Size); DCHECK_EQ(data_.get(index_++), kUint32Size);
...@@ -208,7 +164,7 @@ class OnHeapConsumedPreparseData final ...@@ -208,7 +164,7 @@ class OnHeapConsumedPreparseData final
OnHeapConsumedPreparseData(Isolate* isolate, Handle<PreparseData> data); OnHeapConsumedPreparseData(Isolate* isolate, Handle<PreparseData> data);
PreparseData GetScopeData() final; PreparseData GetScopeData() final;
ProducedPreparseData* GetChildData(Zone* zone, int index) final; ProducedPreparseData* GetChildData(Zone* zone, int child_index) final;
private: private:
Isolate* isolate_; Isolate* isolate_;
...@@ -218,16 +174,16 @@ class OnHeapConsumedPreparseData final ...@@ -218,16 +174,16 @@ class OnHeapConsumedPreparseData final
// 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:
ZonePreparseData(Zone* zone, PreparseDataBuilder::ByteData* byte_data, ZonePreparseData(Zone* zone, Vector<uint8_t>* byte_data, int child_length);
int child_length);
Handle<PreparseData> Serialize(Isolate* isolate); Handle<PreparseData> Serialize(Isolate* isolate);
int child_length() const { return static_cast<int>(children_.size()); } int children_length() const { return static_cast<int>(children_.size()); }
ZonePreparseData* get_child(int index) { return children_[index]; } ZonePreparseData* get_child(int index) { return children_[index]; }
void set_child(int index, ZonePreparseData* child) { void set_child(int index, ZonePreparseData* child) {
DCHECK_NOT_NULL(child);
children_[index] = child; children_[index] = child;
} }
......
This diff is collapsed.
...@@ -17,6 +17,7 @@ namespace internal { ...@@ -17,6 +17,7 @@ namespace internal {
template <typename T> template <typename T>
class PodArray; class PodArray;
class Parser;
class PreParser; class PreParser;
class PreparseData; class PreparseData;
class ZonePreparseData; class ZonePreparseData;
...@@ -62,13 +63,30 @@ class ZonePreparseData; ...@@ -62,13 +63,30 @@ class ZonePreparseData;
*/ */
class PreparseDataBuilder : public ZoneObject { struct PreparseByteDataConstants {
public: #ifdef DEBUG
class ByteData; static constexpr int kMagicValue = 0xC0DE0DE;
static constexpr size_t kUint32Size = 5;
static constexpr size_t kUint8Size = 2;
static constexpr size_t kQuarterMarker = 0;
static constexpr size_t kPlaceholderSize = kUint32Size;
#else
static constexpr size_t kUint32Size = 4;
static constexpr size_t kUint8Size = 1;
static constexpr size_t kPlaceholderSize = 0;
#endif
static const size_t kSkippableFunctionDataSize =
4 * kUint32Size + 1 * kUint8Size;
};
class PreparseDataBuilder : public ZoneObject,
public PreparseByteDataConstants {
public:
// Create a PreparseDataBuilder object which will collect data as we // Create a PreparseDataBuilder object which will collect data as we
// parse. // parse.
PreparseDataBuilder(Zone* zone, PreparseDataBuilder* parent); explicit PreparseDataBuilder(Zone* zone, PreparseDataBuilder* parent_builder);
PreparseDataBuilder* parent() const { return parent_; } PreparseDataBuilder* parent() const { return parent_; }
...@@ -81,8 +99,8 @@ class PreparseDataBuilder : public ZoneObject { ...@@ -81,8 +99,8 @@ class PreparseDataBuilder : public ZoneObject {
: preparser_(preparser), builder_(nullptr) {} : preparser_(preparser), builder_(nullptr) {}
void Start(DeclarationScope* function_scope); void Start(DeclarationScope* function_scope);
void AddSkippableFunction(DeclarationScope* function_scope, void SetSkippableFunction(DeclarationScope* function_scope,
int end_position, int num_inner_functions); int num_inner_functions);
~DataGatheringScope(); ~DataGatheringScope();
private: private:
...@@ -92,9 +110,46 @@ class PreparseDataBuilder : public ZoneObject { ...@@ -92,9 +110,46 @@ class PreparseDataBuilder : public ZoneObject {
DISALLOW_COPY_AND_ASSIGN(DataGatheringScope); DISALLOW_COPY_AND_ASSIGN(DataGatheringScope);
}; };
class ByteData : public ZoneObject, public PreparseByteDataConstants {
public:
ByteData() : byte_data_(nullptr), free_quarters_in_last_byte_(0) {}
~ByteData() {}
void Start(std::vector<uint8_t>* buffer);
void Finalize(Zone* zone);
Handle<PreparseData> CopyToHeap(Isolate* isolate, int children_length);
ZonePreparseData* CopyToZone(Zone* zone, int children_length);
void WriteUint32(uint32_t data);
void WriteUint8(uint8_t data);
void WriteQuarter(uint8_t data);
#ifdef DEBUG
// For overwriting previously written data at position 0.
void SaveCurrentSizeAtFirstUint32();
int length() const;
#endif
private:
union {
// Only used during construction (is_finalized_ == false).
std::vector<uint8_t>* byte_data_;
// Once the data is finalized, it lives in a Zone, this implies
// is_finalized_ == true.
Vector<uint8_t> zone_byte_data_;
};
uint8_t free_quarters_in_last_byte_;
#ifdef DEBUG
bool is_finalized_ = false;
#endif
};
// Saves the information needed for allocating the Scope's (and its // Saves the information needed for allocating the Scope's (and its
// subscopes') variables. // subscopes') variables.
void SaveScopeAllocationData(DeclarationScope* scope); void SaveScopeAllocationData(DeclarationScope* scope, Parser* parser);
// In some cases, PreParser cannot produce the same Scope structure as // In some cases, PreParser cannot produce the same Scope structure as
// Parser. If it happens, we're unable to produce the data that would enable // Parser. If it happens, we're unable to produce the data that would enable
...@@ -116,8 +171,9 @@ class PreparseDataBuilder : public ZoneObject { ...@@ -116,8 +171,9 @@ class PreparseDataBuilder : public ZoneObject {
} }
#endif // DEBUG #endif // DEBUG
bool ContainsInnerFunctions() const; bool HasInnerFunctions() const;
bool HasData() const; bool HasData() const;
bool HasDataForParent() const;
static bool ScopeNeedsData(Scope* scope); static bool ScopeNeedsData(Scope* scope);
static bool ScopeIsSkippableFunctionScope(Scope* scope); static bool ScopeIsSkippableFunctionScope(Scope* scope);
...@@ -135,14 +191,21 @@ class PreparseDataBuilder : public ZoneObject { ...@@ -135,14 +191,21 @@ class PreparseDataBuilder : public ZoneObject {
void SaveDataForScope(Scope* scope); void SaveDataForScope(Scope* scope);
void SaveDataForVariable(Variable* var); void SaveDataForVariable(Variable* var);
void SaveDataForInnerScopes(Scope* scope); void SaveDataForInnerScopes(Scope* scope);
bool SaveDataForSkippableFunction(PreparseDataBuilder* builder);
void CopyByteData(Zone* zone);
PreparseDataBuilder* parent_; PreparseDataBuilder* parent_;
ByteData byte_data_;
ZoneChunkList<PreparseDataBuilder*> children_;
ByteData* byte_data_; DeclarationScope* function_scope_;
ZoneChunkList<PreparseDataBuilder*> data_for_inner_functions_; int num_inner_functions_;
int num_inner_with_data_;
// Whether we've given up producing the data for this function. // Whether we've given up producing the data for this function.
bool bailed_out_; bool bailed_out_ : 1;
bool has_data_ : 1;
DISALLOW_COPY_AND_ASSIGN(PreparseDataBuilder); DISALLOW_COPY_AND_ASSIGN(PreparseDataBuilder);
}; };
......
...@@ -342,8 +342,8 @@ PreParser::Expression PreParser::ParseFunctionLiteral( ...@@ -342,8 +342,8 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
CheckStrictOctalLiteral(start_position, end_position()); CheckStrictOctalLiteral(start_position, end_position());
} }
if (skippable_function) { if (skippable_function) {
preparse_data_builder_scope.AddSkippableFunction( preparse_data_builder_scope.SetSkippableFunction(
function_scope, end_position(), GetLastFunctionLiteralId() - func_id); function_scope, GetLastFunctionLiteralId() - func_id);
} }
} }
......
...@@ -801,7 +801,9 @@ TEST(ProducingAndConsumingByteData) { ...@@ -801,7 +801,9 @@ TEST(ProducingAndConsumingByteData) {
LocalContext env; LocalContext env;
i::Zone zone(isolate->allocator(), ZONE_NAME); i::Zone zone(isolate->allocator(), ZONE_NAME);
i::PreparseDataBuilder::ByteData bytes(&zone); std::vector<uint8_t> buffer;
i::PreparseDataBuilder::ByteData bytes;
bytes.Start(&buffer);
// Write some data. // Write some data.
bytes.WriteUint32(1983); // This will be overwritten. bytes.WriteUint32(1983); // This will be overwritten.
bytes.WriteUint32(2147483647); bytes.WriteUint32(2147483647);
...@@ -810,7 +812,9 @@ TEST(ProducingAndConsumingByteData) { ...@@ -810,7 +812,9 @@ TEST(ProducingAndConsumingByteData) {
bytes.WriteUint32(0); bytes.WriteUint32(0);
bytes.WriteUint8(0); bytes.WriteUint8(0);
#ifdef DEBUG #ifdef DEBUG
bytes.OverwriteFirstUint32(2017); bytes.SaveCurrentSizeAtFirstUint32();
int saved_size = 21;
CHECK_EQ(buffer.size(), saved_size);
#endif #endif
bytes.WriteUint8(100); bytes.WriteUint8(100);
// Write quarter bytes between uint8s and uint32s to verify they're stored // Write quarter bytes between uint8s and uint32s to verify they're stored
...@@ -828,16 +832,35 @@ TEST(ProducingAndConsumingByteData) { ...@@ -828,16 +832,35 @@ TEST(ProducingAndConsumingByteData) {
// End with a lonely quarter. // End with a lonely quarter.
bytes.WriteQuarter(2); bytes.WriteQuarter(2);
#ifdef DEBUG
CHECK_EQ(buffer.size(), 38);
#else
CHECK_EQ(buffer.size(), 25);
#endif
// Copy buffer for sanity checks later-on.
std::vector<uint8_t> copied_buffer(buffer);
// Move the data from the temporary buffer into the zone for later
// serialization.
bytes.Finalize(&zone);
CHECK_EQ(buffer.size(), 0);
CHECK_LT(0, copied_buffer.size());
{ {
// Serialize as a ZoneConsumedPreparseData, and read back data. // Serialize as a ZoneConsumedPreparseData, and read back data.
i::ZonePreparseData zone_serialized(&zone, &bytes, 0); i::ZonePreparseData* data_in_zone = bytes.CopyToZone(&zone, 0);
i::ZoneConsumedPreparseData::ByteData bytes_for_reading; i::ZoneConsumedPreparseData::ByteData bytes_for_reading;
i::ZoneVectorWrapper wrapper(zone_serialized.byte_data()); i::ZoneVectorWrapper wrapper(data_in_zone->byte_data());
i::ZoneConsumedPreparseData::ByteData::ReadingScope reading_scope( i::ZoneConsumedPreparseData::ByteData::ReadingScope reading_scope(
&bytes_for_reading, wrapper); &bytes_for_reading, wrapper);
for (int i = 0; i < static_cast<int>(copied_buffer.size()); i++) {
CHECK_EQ(copied_buffer.at(i), wrapper.get(i));
}
#ifdef DEBUG #ifdef DEBUG
CHECK_EQ(bytes_for_reading.ReadUint32(), 2017); CHECK_EQ(bytes_for_reading.ReadUint32(), saved_size);
#else #else
CHECK_EQ(bytes_for_reading.ReadUint32(), 1983); CHECK_EQ(bytes_for_reading.ReadUint32(), 1983);
#endif #endif
...@@ -858,19 +881,25 @@ TEST(ProducingAndConsumingByteData) { ...@@ -858,19 +881,25 @@ TEST(ProducingAndConsumingByteData) {
CHECK_EQ(bytes_for_reading.ReadQuarter(), 2); CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
CHECK_EQ(bytes_for_reading.ReadUint32(), 50); CHECK_EQ(bytes_for_reading.ReadUint32(), 50);
CHECK_EQ(bytes_for_reading.ReadQuarter(), 2); CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
// We should have consumed all data at this point.
CHECK(!bytes_for_reading.HasRemainingBytes(1));
} }
{ {
// Serialize as an OnHeapConsumedPreparseData, and read back data. // Serialize as an OnHeapConsumedPreparseData, and read back data.
i::Handle<i::PreparseData> data_on_heap = i::Handle<i::PreparseData> data_on_heap = bytes.CopyToHeap(isolate, 0);
isolate->factory()->NewPreparseData(static_cast<int>(bytes.size()), 0); CHECK_EQ(copied_buffer.size(), data_on_heap->data_length());
bytes.StoreInto(*data_on_heap); CHECK_EQ(data_on_heap->children_length(), 0);
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);
for (int i = 0; i < static_cast<int>(copied_buffer.size()); i++) {
CHECK_EQ(copied_buffer[i], data_on_heap->get(i));
}
#ifdef DEBUG #ifdef DEBUG
CHECK_EQ(bytes_for_reading.ReadUint32(), 2017); CHECK_EQ(bytes_for_reading.ReadUint32(), saved_size);
#else #else
CHECK_EQ(bytes_for_reading.ReadUint32(), 1983); CHECK_EQ(bytes_for_reading.ReadUint32(), 1983);
#endif #endif
...@@ -891,5 +920,7 @@ TEST(ProducingAndConsumingByteData) { ...@@ -891,5 +920,7 @@ TEST(ProducingAndConsumingByteData) {
CHECK_EQ(bytes_for_reading.ReadQuarter(), 2); CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
CHECK_EQ(bytes_for_reading.ReadUint32(), 50); CHECK_EQ(bytes_for_reading.ReadUint32(), 50);
CHECK_EQ(bytes_for_reading.ReadQuarter(), 2); CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
// We should have consumed all data at this point.
CHECK(!bytes_for_reading.HasRemainingBytes(1));
} }
} }
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