Split nodes and edges into separate arrays in heap snapshot serialization.
Review URL: https://chromiumcodereview.appspot.com/10037004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11315 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
5d164e4c7c
commit
48777a7f5b
@ -368,16 +368,20 @@ class V8EXPORT HeapSnapshot {
|
|||||||
* with the following structure:
|
* with the following structure:
|
||||||
*
|
*
|
||||||
* {
|
* {
|
||||||
* snapshot: {title: "...", uid: nnn},
|
* snapshot: {
|
||||||
* nodes: [
|
* title: "...",
|
||||||
* meta-info (JSON string),
|
* uid: nnn,
|
||||||
* nodes themselves
|
* meta: { meta-info },
|
||||||
* ],
|
* node_count: nnn,
|
||||||
* strings: [strings]
|
* edge_count: nnn
|
||||||
|
* },
|
||||||
|
* nodes: [nodes array],
|
||||||
|
* edges: [edges array],
|
||||||
|
* strings: [strings array]
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* Outgoing node links are stored after each node. Nodes reference strings
|
* Nodes reference strings, other nodes, and edges by their indexes
|
||||||
* and other nodes by their indexes in corresponding arrays.
|
* in corresponding arrays.
|
||||||
*/
|
*/
|
||||||
void Serialize(OutputStream* stream, SerializationFormat format) const;
|
void Serialize(OutputStream* stream, SerializationFormat format) const;
|
||||||
};
|
};
|
||||||
|
@ -1134,6 +1134,7 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
|
|||||||
gc_roots_entry_(NULL),
|
gc_roots_entry_(NULL),
|
||||||
natives_root_entry_(NULL),
|
natives_root_entry_(NULL),
|
||||||
raw_entries_(NULL),
|
raw_entries_(NULL),
|
||||||
|
number_of_edges_(0),
|
||||||
max_snapshot_js_object_id_(0) {
|
max_snapshot_js_object_id_(0) {
|
||||||
STATIC_CHECK(
|
STATIC_CHECK(
|
||||||
sizeof(HeapGraphEdge) ==
|
sizeof(HeapGraphEdge) ==
|
||||||
@ -1167,6 +1168,7 @@ void HeapSnapshot::AllocateEntries(int entries_count,
|
|||||||
int children_count,
|
int children_count,
|
||||||
int retainers_count) {
|
int retainers_count) {
|
||||||
ASSERT(raw_entries_ == NULL);
|
ASSERT(raw_entries_ == NULL);
|
||||||
|
number_of_edges_ = children_count;
|
||||||
raw_entries_size_ =
|
raw_entries_size_ =
|
||||||
HeapEntry::EntriesSize(entries_count, children_count, retainers_count);
|
HeapEntry::EntriesSize(entries_count, children_count, retainers_count);
|
||||||
raw_entries_ = NewArray<char>(raw_entries_size_);
|
raw_entries_ = NewArray<char>(raw_entries_size_);
|
||||||
@ -3576,14 +3578,37 @@ HeapSnapshot* HeapSnapshotJSONSerializer::CreateFakeSnapshot() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void HeapSnapshotJSONSerializer::CalculateNodeIndexes(
|
||||||
|
const List<HeapEntry*>& nodes) {
|
||||||
|
// type,name,id,self_size,retained_size,dominator,children_index.
|
||||||
|
const int node_fields_count = 7;
|
||||||
|
// Root must be the first.
|
||||||
|
ASSERT(nodes.first() == snapshot_->root());
|
||||||
|
// Rewrite node indexes, so they refer to actual array positions. Do this
|
||||||
|
// only once.
|
||||||
|
if (nodes[0]->entry_index() == -1) {
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < nodes.length(); ++i, index += node_fields_count) {
|
||||||
|
nodes[i]->set_entry_index(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void HeapSnapshotJSONSerializer::SerializeImpl() {
|
void HeapSnapshotJSONSerializer::SerializeImpl() {
|
||||||
|
List<HeapEntry*>& nodes = *(snapshot_->entries());
|
||||||
|
CalculateNodeIndexes(nodes);
|
||||||
writer_->AddCharacter('{');
|
writer_->AddCharacter('{');
|
||||||
writer_->AddString("\"snapshot\":{");
|
writer_->AddString("\"snapshot\":{");
|
||||||
SerializeSnapshot();
|
SerializeSnapshot();
|
||||||
if (writer_->aborted()) return;
|
if (writer_->aborted()) return;
|
||||||
writer_->AddString("},\n");
|
writer_->AddString("},\n");
|
||||||
writer_->AddString("\"nodes\":[");
|
writer_->AddString("\"nodes\":[");
|
||||||
SerializeNodes();
|
SerializeNodes(nodes);
|
||||||
|
if (writer_->aborted()) return;
|
||||||
|
writer_->AddString("],\n");
|
||||||
|
writer_->AddString("\"edges\":[");
|
||||||
|
SerializeEdges(nodes);
|
||||||
if (writer_->aborted()) return;
|
if (writer_->aborted()) return;
|
||||||
writer_->AddString("],\n");
|
writer_->AddString("],\n");
|
||||||
writer_->AddString("\"strings\":[");
|
writer_->AddString("\"strings\":[");
|
||||||
@ -3630,7 +3655,8 @@ static int itoa(int value, const Vector<char>& buffer, int buffer_pos) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) {
|
void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge,
|
||||||
|
bool first_edge) {
|
||||||
// The buffer needs space for 3 ints, 3 commas and \0
|
// The buffer needs space for 3 ints, 3 commas and \0
|
||||||
static const int kBufferSize =
|
static const int kBufferSize =
|
||||||
MaxDecimalDigitsIn<sizeof(int)>::kSigned * 3 + 3 + 1; // NOLINT
|
MaxDecimalDigitsIn<sizeof(int)>::kSigned * 3 + 3 + 1; // NOLINT
|
||||||
@ -3640,7 +3666,9 @@ void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) {
|
|||||||
|| edge->type() == HeapGraphEdge::kWeak
|
|| edge->type() == HeapGraphEdge::kWeak
|
||||||
? edge->index() : GetStringId(edge->name());
|
? edge->index() : GetStringId(edge->name());
|
||||||
int buffer_pos = 0;
|
int buffer_pos = 0;
|
||||||
|
if (!first_edge) {
|
||||||
buffer[buffer_pos++] = ',';
|
buffer[buffer_pos++] = ',';
|
||||||
|
}
|
||||||
buffer_pos = itoa(edge->type(), buffer, buffer_pos);
|
buffer_pos = itoa(edge->type(), buffer, buffer_pos);
|
||||||
buffer[buffer_pos++] = ',';
|
buffer[buffer_pos++] = ',';
|
||||||
buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos);
|
buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos);
|
||||||
@ -3651,17 +3679,33 @@ void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) {
|
void HeapSnapshotJSONSerializer::SerializeEdges(const List<HeapEntry*>& nodes) {
|
||||||
|
bool first_edge = true;
|
||||||
|
for (int i = 0; i < nodes.length(); ++i) {
|
||||||
|
HeapEntry* entry = nodes[i];
|
||||||
|
Vector<HeapGraphEdge> children = entry->children();
|
||||||
|
for (int j = 0; j < children.length(); ++j) {
|
||||||
|
SerializeEdge(&children[j], first_edge);
|
||||||
|
first_edge = false;
|
||||||
|
if (writer_->aborted()) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry,
|
||||||
|
int edges_index) {
|
||||||
// The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0
|
// The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0
|
||||||
static const int kBufferSize =
|
static const int kBufferSize =
|
||||||
6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT
|
6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT
|
||||||
+ MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT
|
+ MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT
|
||||||
+ 7 + 1 + 1;
|
+ 7 + 1 + 1;
|
||||||
EmbeddedVector<char, kBufferSize> buffer;
|
EmbeddedVector<char, kBufferSize> buffer;
|
||||||
Vector<HeapGraphEdge> children = entry->children();
|
|
||||||
int buffer_pos = 0;
|
int buffer_pos = 0;
|
||||||
buffer[buffer_pos++] = '\n';
|
buffer[buffer_pos++] = '\n';
|
||||||
|
if (entry->entry_index() != 0) {
|
||||||
buffer[buffer_pos++] = ',';
|
buffer[buffer_pos++] = ',';
|
||||||
|
}
|
||||||
buffer_pos = itoa(entry->type(), buffer, buffer_pos);
|
buffer_pos = itoa(entry->type(), buffer, buffer_pos);
|
||||||
buffer[buffer_pos++] = ',';
|
buffer[buffer_pos++] = ',';
|
||||||
buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos);
|
buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos);
|
||||||
@ -3674,93 +3718,19 @@ void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) {
|
|||||||
buffer[buffer_pos++] = ',';
|
buffer[buffer_pos++] = ',';
|
||||||
buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos);
|
buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos);
|
||||||
buffer[buffer_pos++] = ',';
|
buffer[buffer_pos++] = ',';
|
||||||
buffer_pos = itoa(children.length(), buffer, buffer_pos);
|
buffer_pos = itoa(edges_index, buffer, buffer_pos);
|
||||||
buffer[buffer_pos++] = '\0';
|
buffer[buffer_pos++] = '\0';
|
||||||
writer_->AddString(buffer.start());
|
writer_->AddString(buffer.start());
|
||||||
for (int i = 0; i < children.length(); ++i) {
|
|
||||||
SerializeEdge(&children[i]);
|
|
||||||
if (writer_->aborted()) return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HeapSnapshotJSONSerializer::SerializeNodes() {
|
void HeapSnapshotJSONSerializer::SerializeNodes(const List<HeapEntry*>& nodes) {
|
||||||
// The first (zero) item of nodes array is an object describing node
|
|
||||||
// serialization layout. We use a set of macros to improve
|
|
||||||
// readability.
|
|
||||||
#define JSON_A(s) "["s"]"
|
|
||||||
#define JSON_O(s) "{"s"}"
|
|
||||||
#define JSON_S(s) "\""s"\""
|
|
||||||
writer_->AddString(JSON_O(
|
|
||||||
JSON_S("fields") ":" JSON_A(
|
|
||||||
JSON_S("type")
|
|
||||||
"," JSON_S("name")
|
|
||||||
"," JSON_S("id")
|
|
||||||
"," JSON_S("self_size")
|
|
||||||
"," JSON_S("retained_size")
|
|
||||||
"," JSON_S("dominator")
|
|
||||||
"," JSON_S("children_count")
|
|
||||||
"," JSON_S("children"))
|
|
||||||
"," JSON_S("types") ":" JSON_A(
|
|
||||||
JSON_A(
|
|
||||||
JSON_S("hidden")
|
|
||||||
"," JSON_S("array")
|
|
||||||
"," JSON_S("string")
|
|
||||||
"," JSON_S("object")
|
|
||||||
"," JSON_S("code")
|
|
||||||
"," JSON_S("closure")
|
|
||||||
"," JSON_S("regexp")
|
|
||||||
"," JSON_S("number")
|
|
||||||
"," JSON_S("native")
|
|
||||||
"," JSON_S("synthetic"))
|
|
||||||
"," JSON_S("string")
|
|
||||||
"," JSON_S("number")
|
|
||||||
"," JSON_S("number")
|
|
||||||
"," JSON_S("number")
|
|
||||||
"," JSON_S("number")
|
|
||||||
"," JSON_S("number")
|
|
||||||
"," JSON_O(
|
|
||||||
JSON_S("fields") ":" JSON_A(
|
|
||||||
JSON_S("type")
|
|
||||||
"," JSON_S("name_or_index")
|
|
||||||
"," JSON_S("to_node"))
|
|
||||||
"," JSON_S("types") ":" JSON_A(
|
|
||||||
JSON_A(
|
|
||||||
JSON_S("context")
|
|
||||||
"," JSON_S("element")
|
|
||||||
"," JSON_S("property")
|
|
||||||
"," JSON_S("internal")
|
|
||||||
"," JSON_S("hidden")
|
|
||||||
"," JSON_S("shortcut")
|
|
||||||
"," JSON_S("weak"))
|
|
||||||
"," JSON_S("string_or_number")
|
|
||||||
"," JSON_S("node"))))));
|
|
||||||
#undef JSON_S
|
|
||||||
#undef JSON_O
|
|
||||||
#undef JSON_A
|
|
||||||
|
|
||||||
const int node_fields_count = 7;
|
|
||||||
// type,name,id,self_size,retained_size,dominator,children_count.
|
|
||||||
const int edge_fields_count = 3; // type,name|index,to_node.
|
const int edge_fields_count = 3; // type,name|index,to_node.
|
||||||
|
int edges_index = 0;
|
||||||
List<HeapEntry*>& nodes = *(snapshot_->entries());
|
|
||||||
// Root must be the first.
|
|
||||||
ASSERT(nodes.first() == snapshot_->root());
|
|
||||||
// Rewrite node indexes, so they refer to actual array positions. Do this
|
|
||||||
// only once.
|
|
||||||
if (nodes[0]->entry_index() == -1) {
|
|
||||||
// Nodes start from array index 1.
|
|
||||||
int index = 1;
|
|
||||||
for (int i = 0; i < nodes.length(); ++i) {
|
for (int i = 0; i < nodes.length(); ++i) {
|
||||||
HeapEntry* node = nodes[i];
|
HeapEntry* entry = nodes[i];
|
||||||
node->set_entry_index(index);
|
SerializeNode(entry, edges_index);
|
||||||
index += node_fields_count +
|
edges_index += entry->children().length() * edge_fields_count;
|
||||||
node->children().length() * edge_fields_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < nodes.length(); ++i) {
|
|
||||||
SerializeNode(nodes[i]);
|
|
||||||
if (writer_->aborted()) return;
|
if (writer_->aborted()) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3772,6 +3742,61 @@ void HeapSnapshotJSONSerializer::SerializeSnapshot() {
|
|||||||
writer_->AddString("\"");
|
writer_->AddString("\"");
|
||||||
writer_->AddString(",\"uid\":");
|
writer_->AddString(",\"uid\":");
|
||||||
writer_->AddNumber(snapshot_->uid());
|
writer_->AddNumber(snapshot_->uid());
|
||||||
|
writer_->AddString(",\"meta\":");
|
||||||
|
// The object describing node serialization layout.
|
||||||
|
// We use a set of macros to improve readability.
|
||||||
|
#define JSON_A(s) "["s"]"
|
||||||
|
#define JSON_O(s) "{"s"}"
|
||||||
|
#define JSON_S(s) "\""s"\""
|
||||||
|
writer_->AddString(JSON_O(
|
||||||
|
JSON_S("node_fields") ":" JSON_A(
|
||||||
|
JSON_S("type") ","
|
||||||
|
JSON_S("name") ","
|
||||||
|
JSON_S("id") ","
|
||||||
|
JSON_S("self_size") ","
|
||||||
|
JSON_S("retained_size") ","
|
||||||
|
JSON_S("dominator") ","
|
||||||
|
JSON_S("edges_index")) ","
|
||||||
|
JSON_S("node_types") ":" JSON_A(
|
||||||
|
JSON_A(
|
||||||
|
JSON_S("hidden") ","
|
||||||
|
JSON_S("array") ","
|
||||||
|
JSON_S("string") ","
|
||||||
|
JSON_S("object") ","
|
||||||
|
JSON_S("code") ","
|
||||||
|
JSON_S("closure") ","
|
||||||
|
JSON_S("regexp") ","
|
||||||
|
JSON_S("number") ","
|
||||||
|
JSON_S("native") ","
|
||||||
|
JSON_S("synthetic")) ","
|
||||||
|
JSON_S("string") ","
|
||||||
|
JSON_S("number") ","
|
||||||
|
JSON_S("number") ","
|
||||||
|
JSON_S("number") ","
|
||||||
|
JSON_S("number") ","
|
||||||
|
JSON_S("number")) ","
|
||||||
|
JSON_S("edge_fields") ":" JSON_A(
|
||||||
|
JSON_S("type") ","
|
||||||
|
JSON_S("name_or_index") ","
|
||||||
|
JSON_S("to_node")) ","
|
||||||
|
JSON_S("edge_types") ":" JSON_A(
|
||||||
|
JSON_A(
|
||||||
|
JSON_S("context") ","
|
||||||
|
JSON_S("element") ","
|
||||||
|
JSON_S("property") ","
|
||||||
|
JSON_S("internal") ","
|
||||||
|
JSON_S("hidden") ","
|
||||||
|
JSON_S("shortcut") ","
|
||||||
|
JSON_S("weak")) ","
|
||||||
|
JSON_S("string_or_number") ","
|
||||||
|
JSON_S("node"))));
|
||||||
|
#undef JSON_S
|
||||||
|
#undef JSON_O
|
||||||
|
#undef JSON_A
|
||||||
|
writer_->AddString(",\"node_count\":");
|
||||||
|
writer_->AddNumber(snapshot_->entries()->length());
|
||||||
|
writer_->AddString(",\"edge_count\":");
|
||||||
|
writer_->AddNumber(snapshot_->number_of_edges());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -648,6 +648,7 @@ class HeapSnapshot {
|
|||||||
HeapEntry* gc_subroot(int index) { return gc_subroot_entries_[index]; }
|
HeapEntry* gc_subroot(int index) { return gc_subroot_entries_[index]; }
|
||||||
List<HeapEntry*>* entries() { return &entries_; }
|
List<HeapEntry*>* entries() { return &entries_; }
|
||||||
size_t raw_entries_size() { return raw_entries_size_; }
|
size_t raw_entries_size() { return raw_entries_size_; }
|
||||||
|
int number_of_edges() { return number_of_edges_; }
|
||||||
void RememberLastJSObjectId();
|
void RememberLastJSObjectId();
|
||||||
SnapshotObjectId max_snapshot_js_object_id() const {
|
SnapshotObjectId max_snapshot_js_object_id() const {
|
||||||
return max_snapshot_js_object_id_;
|
return max_snapshot_js_object_id_;
|
||||||
@ -690,6 +691,7 @@ class HeapSnapshot {
|
|||||||
List<HeapEntry*> entries_;
|
List<HeapEntry*> entries_;
|
||||||
List<HeapEntry*> sorted_entries_;
|
List<HeapEntry*> sorted_entries_;
|
||||||
size_t raw_entries_size_;
|
size_t raw_entries_size_;
|
||||||
|
int number_of_edges_;
|
||||||
SnapshotObjectId max_snapshot_js_object_id_;
|
SnapshotObjectId max_snapshot_js_object_id_;
|
||||||
|
|
||||||
friend class HeapSnapshotTester;
|
friend class HeapSnapshotTester;
|
||||||
@ -1160,12 +1162,14 @@ class HeapSnapshotJSONSerializer {
|
|||||||
v8::internal::kZeroHashSeed);
|
v8::internal::kZeroHashSeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CalculateNodeIndexes(const List<HeapEntry*>& nodes);
|
||||||
HeapSnapshot* CreateFakeSnapshot();
|
HeapSnapshot* CreateFakeSnapshot();
|
||||||
int GetStringId(const char* s);
|
int GetStringId(const char* s);
|
||||||
void SerializeEdge(HeapGraphEdge* edge);
|
void SerializeEdge(HeapGraphEdge* edge, bool first_edge);
|
||||||
|
void SerializeEdges(const List<HeapEntry*>& nodes);
|
||||||
void SerializeImpl();
|
void SerializeImpl();
|
||||||
void SerializeNode(HeapEntry* entry);
|
void SerializeNode(HeapEntry* entry, int edges_index);
|
||||||
void SerializeNodes();
|
void SerializeNodes(const List<HeapEntry*>& nodes);
|
||||||
void SerializeSnapshot();
|
void SerializeSnapshot();
|
||||||
void SerializeString(const unsigned char* s);
|
void SerializeString(const unsigned char* s);
|
||||||
void SerializeStrings();
|
void SerializeStrings();
|
||||||
|
@ -618,42 +618,37 @@ TEST(HeapSnapshotJSONSerialization) {
|
|||||||
env->Global()->Get(v8_str("parsed"))->ToObject();
|
env->Global()->Get(v8_str("parsed"))->ToObject();
|
||||||
CHECK(parsed_snapshot->Has(v8_str("snapshot")));
|
CHECK(parsed_snapshot->Has(v8_str("snapshot")));
|
||||||
CHECK(parsed_snapshot->Has(v8_str("nodes")));
|
CHECK(parsed_snapshot->Has(v8_str("nodes")));
|
||||||
|
CHECK(parsed_snapshot->Has(v8_str("edges")));
|
||||||
CHECK(parsed_snapshot->Has(v8_str("strings")));
|
CHECK(parsed_snapshot->Has(v8_str("strings")));
|
||||||
|
|
||||||
// Get node and edge "member" offsets.
|
// Get node and edge "member" offsets.
|
||||||
v8::Local<v8::Value> meta_analysis_result = CompileRun(
|
v8::Local<v8::Value> meta_analysis_result = CompileRun(
|
||||||
"var parsed_meta = parsed.nodes[0];\n"
|
"var meta = parsed.snapshot.meta;\n"
|
||||||
"var children_count_offset ="
|
"var edges_index_offset = meta.node_fields.indexOf('edges_index');\n"
|
||||||
" parsed_meta.fields.indexOf('children_count');\n"
|
"var node_fields_count = meta.node_fields.length;\n"
|
||||||
"var children_offset ="
|
"var edge_fields_count = meta.edge_fields.length;\n"
|
||||||
" parsed_meta.fields.indexOf('children');\n"
|
"var edge_type_offset = meta.edge_fields.indexOf('type');\n"
|
||||||
"var children_meta ="
|
"var edge_name_offset = meta.edge_fields.indexOf('name_or_index');\n"
|
||||||
" parsed_meta.types[children_offset];\n"
|
"var edge_to_node_offset = meta.edge_fields.indexOf('to_node');\n"
|
||||||
"var child_fields_count = children_meta.fields.length;\n"
|
|
||||||
"var child_type_offset ="
|
|
||||||
" children_meta.fields.indexOf('type');\n"
|
|
||||||
"var child_name_offset ="
|
|
||||||
" children_meta.fields.indexOf('name_or_index');\n"
|
|
||||||
"var child_to_node_offset ="
|
|
||||||
" children_meta.fields.indexOf('to_node');\n"
|
|
||||||
"var property_type ="
|
"var property_type ="
|
||||||
" children_meta.types[child_type_offset].indexOf('property');\n"
|
" meta.edge_types[edge_type_offset].indexOf('property');\n"
|
||||||
"var shortcut_type ="
|
"var shortcut_type ="
|
||||||
" children_meta.types[child_type_offset].indexOf('shortcut');");
|
" meta.edge_types[edge_type_offset].indexOf('shortcut');\n"
|
||||||
|
"parsed.nodes.concat(0, 0, 0, 0, 0, 0, parsed.edges.length);");
|
||||||
CHECK(!meta_analysis_result.IsEmpty());
|
CHECK(!meta_analysis_result.IsEmpty());
|
||||||
|
|
||||||
// A helper function for processing encoded nodes.
|
// A helper function for processing encoded nodes.
|
||||||
CompileRun(
|
CompileRun(
|
||||||
"function GetChildPosByProperty(pos, prop_name, prop_type) {\n"
|
"function GetChildPosByProperty(pos, prop_name, prop_type) {\n"
|
||||||
" var nodes = parsed.nodes;\n"
|
" var nodes = parsed.nodes;\n"
|
||||||
|
" var edges = parsed.edges;\n"
|
||||||
" var strings = parsed.strings;\n"
|
" var strings = parsed.strings;\n"
|
||||||
" for (var i = 0,\n"
|
" for (var i = nodes[pos + edges_index_offset],\n"
|
||||||
" count = nodes[pos + children_count_offset] * child_fields_count;\n"
|
" count = nodes[pos + node_fields_count + edges_index_offset];\n"
|
||||||
" i < count; i += child_fields_count) {\n"
|
" i < count; i += edge_fields_count) {\n"
|
||||||
" var child_pos = pos + children_offset + i;\n"
|
" if (edges[i + edge_type_offset] === prop_type\n"
|
||||||
" if (nodes[child_pos + child_type_offset] === prop_type\n"
|
" && strings[edges[i + edge_name_offset]] === prop_name)\n"
|
||||||
" && strings[nodes[child_pos + child_name_offset]] === prop_name)\n"
|
" return edges[i + edge_to_node_offset];\n"
|
||||||
" return nodes[child_pos + child_to_node_offset];\n"
|
|
||||||
" }\n"
|
" }\n"
|
||||||
" return null;\n"
|
" return null;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
@ -662,8 +657,9 @@ TEST(HeapSnapshotJSONSerialization) {
|
|||||||
"GetChildPosByProperty(\n"
|
"GetChildPosByProperty(\n"
|
||||||
" GetChildPosByProperty(\n"
|
" GetChildPosByProperty(\n"
|
||||||
" GetChildPosByProperty("
|
" GetChildPosByProperty("
|
||||||
" parsed.nodes[1 + children_offset + child_to_node_offset],"
|
" parsed.edges[parsed.nodes[edges_index_offset]"
|
||||||
" \"b\",shortcut_type),\n"
|
" + edge_to_node_offset],"
|
||||||
|
" \"b\", shortcut_type),\n"
|
||||||
" \"x\", property_type),"
|
" \"x\", property_type),"
|
||||||
" \"s\", property_type)");
|
" \"s\", property_type)");
|
||||||
CHECK(!string_obj_pos_val.IsEmpty());
|
CHECK(!string_obj_pos_val.IsEmpty());
|
||||||
|
Loading…
Reference in New Issue
Block a user