Revision: 24896
Author: [email protected]
Date: Mon Oct 27 10:12:16 2014 UTC
Log: [turbofan] Reduce memory consumption of graph building
Allow reservation of additional input capacity when creating nodes to
prevent switching to deque representation when adding well-known additional
inputs.
Also ensure that only a single temporary buffer is used to create temporary
input arrays before allocating nodes.
[email protected]
Review URL: https://codereview.chromium.org/644083003
https://code.google.com/p/v8/source/detail?r=24896
Modified:
/branches/bleeding_edge/src/compiler/generic-node-inl.h
/branches/bleeding_edge/src/compiler/generic-node.h
/branches/bleeding_edge/src/compiler/graph-builder.cc
/branches/bleeding_edge/src/compiler/graph-builder.h
/branches/bleeding_edge/src/compiler/graph.cc
/branches/bleeding_edge/src/compiler/node.h
/branches/bleeding_edge/src/compiler/raw-machine-assembler.cc
/branches/bleeding_edge/src/compiler/raw-machine-assembler.h
/branches/bleeding_edge/test/cctest/compiler/graph-builder-tester.h
/branches/bleeding_edge/test/cctest/compiler/simplified-graph-builder.cc
/branches/bleeding_edge/test/cctest/compiler/simplified-graph-builder.h
=======================================
--- /branches/bleeding_edge/src/compiler/generic-node-inl.h Wed Oct 15
11:38:04 2014 UTC
+++ /branches/bleeding_edge/src/compiler/generic-node-inl.h Mon Oct 27
10:12:16 2014 UTC
@@ -16,13 +16,16 @@
namespace compiler {
template <class B, class S>
-GenericNode<B, S>::GenericNode(GenericGraphBase* graph, int input_count)
+GenericNode<B, S>::GenericNode(GenericGraphBase* graph, int input_count,
+ int reserve_input_count)
: BaseClass(graph->zone()),
input_count_(input_count),
+ reserve_input_count_(reserve_input_count),
has_appendable_inputs_(false),
use_count_(0),
first_use_(NULL),
last_use_(NULL) {
+ DCHECK(reserve_input_count <= kMaxReservedInputs);
inputs_.static_ = reinterpret_cast<Input*>(this + 1);
AssignUniqueID(graph);
}
@@ -154,12 +157,18 @@
template <class B, class S>
void GenericNode<B, S>::AppendInput(Zone* zone, GenericNode<B, S>*
to_append) {
- EnsureAppendableInputs(zone);
Use* new_use = new (zone) Use;
Input new_input;
new_input.to = to_append;
new_input.use = new_use;
- inputs_.appendable_->push_back(new_input);
+ if (reserve_input_count_ > 0) {
+ DCHECK(!has_appendable_inputs_);
+ reserve_input_count_--;
+ inputs_.static_[input_count_] = new_input;
+ } else {
+ EnsureAppendableInputs(zone);
+ inputs_.appendable_->push_back(new_input);
+ }
new_use->input_index = input_count_;
new_use->from = this;
to_append->AppendUse(new_use);
@@ -224,15 +233,17 @@
}
template <class B, class S>
-S* GenericNode<B, S>::New(GenericGraphBase* graph, int input_count,
- S** inputs) {
+S* GenericNode<B, S>::New(GenericGraphBase* graph, int input_count, S**
inputs,
+ bool has_extensible_inputs) {
size_t node_size = sizeof(GenericNode);
- size_t inputs_size = input_count * sizeof(Input);
+ size_t reserve_input_count =
+ has_extensible_inputs ? kDefaultReservedInputs : 0;
+ size_t inputs_size = (input_count + reserve_input_count) * sizeof(Input);
size_t uses_size = input_count * sizeof(Use);
int size = static_cast<int>(node_size + inputs_size + uses_size);
Zone* zone = graph->zone();
void* buffer = zone->New(size);
- S* result = new (buffer) S(graph, input_count);
+ S* result = new (buffer) S(graph, input_count, reserve_input_count);
Input* input =
reinterpret_cast<Input*>(reinterpret_cast<char*>(buffer) +
node_size);
Use* use =
=======================================
--- /branches/bleeding_edge/src/compiler/generic-node.h Wed Sep 24 09:28:56
2014 UTC
+++ /branches/bleeding_edge/src/compiler/generic-node.h Mon Oct 27 10:12:16
2014 UTC
@@ -92,7 +92,8 @@
bool OwnedBy(GenericNode* owner) const;
- static S* New(GenericGraphBase* graph, int input_count, S** inputs);
+ static S* New(GenericGraphBase* graph, int input_count, S** inputs,
+ bool has_extensible_inputs);
protected:
friend class GenericGraphBase;
@@ -128,15 +129,21 @@
void* operator new(size_t, void* location) { return location; }
- GenericNode(GenericGraphBase* graph, int input_count);
+ GenericNode(GenericGraphBase* graph, int input_count,
+ int reserved_input_count);
private:
void AssignUniqueID(GenericGraphBase* graph);
typedef ZoneDeque<Input> InputDeque;
+ static const int kReservedInputCountBits = 2;
+ static const int kMaxReservedInputs = (1 << kReservedInputCountBits) - 1;
+ static const int kDefaultReservedInputs = kMaxReservedInputs;
+
NodeId id_;
- int input_count_ : 31;
+ int input_count_ : 29;
+ unsigned int reserve_input_count_ : kReservedInputCountBits;
bool has_appendable_inputs_ : 1;
union {
// When a node is initially allocated, it uses a static buffer to hold
its
=======================================
--- /branches/bleeding_edge/src/compiler/graph-builder.cc Tue Oct 21
14:44:50 2014 UTC
+++ /branches/bleeding_edge/src/compiler/graph-builder.cc Mon Oct 27
10:12:16 2014 UTC
@@ -25,13 +25,26 @@
common_(common),
environment_(NULL),
local_zone_(local_zone),
+ input_buffer_size_(0),
+ input_buffer_(NULL),
current_context_(NULL),
- exit_control_(NULL) {}
+ exit_control_(NULL) {
+ EnsureInputBufferSize(kInputBufferSizeIncrement);
+}
+
+
+Node** StructuredGraphBuilder::EnsureInputBufferSize(int size) {
+ if (size > input_buffer_size_) {
+ size += kInputBufferSizeIncrement;
+ input_buffer_ = local_zone()->NewArray<Node*>(size);
+ }
+ return input_buffer_;
+}
Node* StructuredGraphBuilder::MakeNode(const Operator* op,
int value_input_count,
- Node** value_inputs) {
+ Node** value_inputs, bool
incomplete) {
DCHECK(op->InputCount() == value_input_count);
bool has_context = OperatorProperties::HasContextInput(op);
@@ -44,14 +57,14 @@
Node* result = NULL;
if (!has_context && !has_framestate && !has_control && !has_effect) {
- result = graph()->NewNode(op, value_input_count, value_inputs);
+ result = graph()->NewNode(op, value_input_count, value_inputs,
incomplete);
} else {
int input_count_with_deps = value_input_count;
if (has_context) ++input_count_with_deps;
if (has_framestate) ++input_count_with_deps;
if (has_control) ++input_count_with_deps;
if (has_effect) ++input_count_with_deps;
- Node** buffer = local_zone()->NewArray<Node*>(input_count_with_deps);
+ Node** buffer = EnsureInputBufferSize(input_count_with_deps);
memcpy(buffer, value_inputs, kPointerSize * value_input_count);
Node** current_input = buffer + value_input_count;
if (has_context) {
@@ -69,7 +82,7 @@
if (has_control) {
*current_input++ = environment_->GetControlDependency();
}
- result = graph()->NewNode(op, input_count_with_deps, buffer);
+ result = graph()->NewNode(op, input_count_with_deps, buffer,
incomplete);
if (has_effect) {
environment_->UpdateEffectDependency(result);
}
@@ -125,7 +138,9 @@
// placing a singleton merge as the new control dependency.
if (this->IsMarkedAsUnreachable()) {
Node* other_control = other->control_dependency_;
- control_dependency_ = graph()->NewNode(common()->Merge(1),
other_control);
+ Node* inputs[] = {other_control};
+ control_dependency_ =
+ graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs,
true);
effect_dependency_ = other->effect_dependency_;
values_ = other->values_;
return;
@@ -164,7 +179,7 @@
Node* StructuredGraphBuilder::NewPhi(int count, Node* input, Node*
control) {
const Operator* phi_op = common()->Phi(kMachAnyTagged, count);
- Node** buffer = local_zone()->NewArray<Node*>(count + 1);
+ Node** buffer = EnsureInputBufferSize(count + 1);
MemsetPointer(buffer, input, count);
buffer[count] = control;
return graph()->NewNode(phi_op, count + 1, buffer, true);
@@ -175,7 +190,7 @@
Node* StructuredGraphBuilder::NewEffectPhi(int count, Node* input,
Node* control) {
const Operator* phi_op = common()->EffectPhi(count);
- Node** buffer = local_zone()->NewArray<Node*>(count + 1);
+ Node** buffer = EnsureInputBufferSize(count + 1);
MemsetPointer(buffer, input, count);
buffer[count] = control;
return graph()->NewNode(phi_op, count + 1, buffer, true);
@@ -197,7 +212,8 @@
} else {
// Control node is a singleton, introduce a merge.
const Operator* op = common()->Merge(inputs);
- control = graph()->NewNode(op, control, other);
+ Node* inputs[] = {control, other};
+ control = graph()->NewNode(op, arraysize(inputs), inputs, true);
}
return control;
}
=======================================
--- /branches/bleeding_edge/src/compiler/graph-builder.h Tue Oct 21
14:44:50 2014 UTC
+++ /branches/bleeding_edge/src/compiler/graph-builder.h Mon Oct 27
10:12:16 2014 UTC
@@ -24,42 +24,44 @@
explicit GraphBuilder(Graph* graph) : graph_(graph) {}
virtual ~GraphBuilder() {}
- Node* NewNode(const Operator* op) {
- return MakeNode(op, 0, static_cast<Node**>(NULL));
+ Node* NewNode(const Operator* op, bool incomplete = false) {
+ return MakeNode(op, 0, static_cast<Node**>(NULL), incomplete);
}
- Node* NewNode(const Operator* op, Node* n1) { return MakeNode(op, 1,
&n1); }
+ Node* NewNode(const Operator* op, Node* n1) {
+ return MakeNode(op, 1, &n1, false);
+ }
Node* NewNode(const Operator* op, Node* n1, Node* n2) {
Node* buffer[] = {n1, n2};
- return MakeNode(op, arraysize(buffer), buffer);
+ return MakeNode(op, arraysize(buffer), buffer, false);
}
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) {
Node* buffer[] = {n1, n2, n3};
- return MakeNode(op, arraysize(buffer), buffer);
+ return MakeNode(op, arraysize(buffer), buffer, false);
}
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node*
n4) {
Node* buffer[] = {n1, n2, n3, n4};
- return MakeNode(op, arraysize(buffer), buffer);
+ return MakeNode(op, arraysize(buffer), buffer, false);
}
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
Node* n5) {
Node* buffer[] = {n1, n2, n3, n4, n5};
- return MakeNode(op, arraysize(buffer), buffer);
+ return MakeNode(op, arraysize(buffer), buffer, false);
}
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
Node* n5, Node* n6) {
Node* nodes[] = {n1, n2, n3, n4, n5, n6};
- return MakeNode(op, arraysize(nodes), nodes);
+ return MakeNode(op, arraysize(nodes), nodes, false);
}
- Node* NewNode(const Operator* op, int value_input_count,
- Node** value_inputs) {
- return MakeNode(op, value_input_count, value_inputs);
+ Node* NewNode(const Operator* op, int value_input_count, Node**
value_inputs,
+ bool incomplete = false) {
+ return MakeNode(op, value_input_count, value_inputs, incomplete);
}
Graph* graph() const { return graph_; }
@@ -67,7 +69,7 @@
protected:
// Base implementation used by all factory methods.
virtual Node* MakeNode(const Operator* op, int value_input_count,
- Node** value_inputs) = 0;
+ Node** value_inputs, bool incomplete) = 0;
private:
Graph* graph_;
@@ -95,8 +97,8 @@
// Helpers to create new control nodes.
Node* NewIfTrue() { return NewNode(common()->IfTrue()); }
Node* NewIfFalse() { return NewNode(common()->IfFalse()); }
- Node* NewMerge() { return NewNode(common()->Merge(1)); }
- Node* NewLoop() { return NewNode(common()->Loop(1)); }
+ Node* NewMerge() { return NewNode(common()->Merge(1), true); }
+ Node* NewLoop() { return NewNode(common()->Loop(1), true); }
Node* NewBranch(Node* condition) {
return NewNode(common()->Branch(), condition);
}
@@ -110,7 +112,7 @@
// ensures effect and control dependencies are wired up. The dependencies
// tracked by the environment might be mutated.
virtual Node* MakeNode(const Operator* op, int value_input_count,
- Node** value_inputs) FINAL;
+ Node** value_inputs, bool incomplete) FINAL;
Environment* environment() const { return environment_; }
void set_environment(Environment* env) { environment_ = env; }
@@ -148,6 +150,10 @@
// Zone local to the builder for data not leaking into the graph.
Zone* local_zone_;
+ // Temporary storage for building node input lists.
+ int input_buffer_size_;
+ Node** input_buffer_;
+
// Node representing the control dependency for dead code.
SetOncePointer<Node> dead_control_;
@@ -157,6 +163,12 @@
// Merge of all control nodes that exit the function body.
Node* exit_control_;
+ // Growth increment for the temporary buffer used to construct input
lists to
+ // new nodes.
+ static const int kInputBufferSizeIncrement = 64;
+
+ Node** EnsureInputBufferSize(int size);
+
DISALLOW_COPY_AND_ASSIGN(StructuredGraphBuilder);
};
=======================================
--- /branches/bleeding_edge/src/compiler/graph.cc Wed Oct 15 11:38:04 2014
UTC
+++ /branches/bleeding_edge/src/compiler/graph.cc Mon Oct 27 10:12:16 2014
UTC
@@ -11,6 +11,7 @@
#include "src/compiler/node-aux-data-inl.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/node-properties-inl.h"
+#include "src/compiler/opcodes.h"
#include "src/compiler/operator-properties.h"
#include "src/compiler/operator-properties-inl.h"
@@ -29,12 +30,14 @@
}
-Node* Graph::NewNode(
- const Operator* op, int input_count, Node** inputs, bool incomplete) {
+Node* Graph::NewNode(const Operator* op, int input_count, Node** inputs,
+ bool incomplete) {
DCHECK_LE(op->InputCount(), input_count);
- Node* result = Node::New(this, input_count, inputs);
+ Node* result = Node::New(this, input_count, inputs, incomplete);
result->Initialize(op);
- if (!incomplete) Decorate(result);
+ if (!incomplete) {
+ Decorate(result);
+ }
return result;
}
=======================================
--- /branches/bleeding_edge/src/compiler/node.h Wed Oct 15 11:38:04 2014 UTC
+++ /branches/bleeding_edge/src/compiler/node.h Mon Oct 27 10:12:16 2014 UTC
@@ -48,8 +48,8 @@
// out-of-line indexed by the Node's id.
class Node FINAL : public GenericNode<NodeData, Node> {
public:
- Node(GenericGraphBase* graph, int input_count)
- : GenericNode<NodeData, Node>(graph, input_count) {}
+ Node(GenericGraphBase* graph, int input_count, int reserve_input_count)
+ : GenericNode<NodeData, Node>(graph, input_count,
reserve_input_count) {}
void Initialize(const Operator* op) { set_op(op); }
=======================================
--- /branches/bleeding_edge/src/compiler/raw-machine-assembler.cc Tue Oct
21 12:38:46 2014 UTC
+++ /branches/bleeding_edge/src/compiler/raw-machine-assembler.cc Mon Oct
27 10:12:16 2014 UTC
@@ -151,10 +151,10 @@
Node* RawMachineAssembler::MakeNode(const Operator* op, int input_count,
- Node** inputs) {
+ Node** inputs, bool incomplete) {
DCHECK(ScheduleValid());
DCHECK(current_block_ != NULL);
- Node* node = graph()->NewNode(op, input_count, inputs);
+ Node* node = graph()->NewNode(op, input_count, inputs, incomplete);
BasicBlock* block = op->opcode() == IrOpcode::kParameter ?
schedule()->start()
:
CurrentBlock();
schedule()->AddNode(block, node);
=======================================
--- /branches/bleeding_edge/src/compiler/raw-machine-assembler.h Tue Oct 14
11:57:06 2014 UTC
+++ /branches/bleeding_edge/src/compiler/raw-machine-assembler.h Mon Oct 27
10:12:16 2014 UTC
@@ -416,8 +416,8 @@
Schedule* Export();
protected:
- virtual Node* MakeNode(const Operator* op, int input_count,
- Node** inputs) FINAL;
+ virtual Node* MakeNode(const Operator* op, int input_count, Node**
inputs,
+ bool incomplete) FINAL;
bool ScheduleValid() { return schedule_ != NULL; }
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/graph-builder-tester.h Thu
Sep 11 10:37:49 2014 UTC
+++ /branches/bleeding_edge/test/cctest/compiler/graph-builder-tester.h Mon
Oct 27 10:12:16 2014 UTC
@@ -27,8 +27,8 @@
protected:
virtual Node* MakeNode(const Operator* op, int value_input_count,
- Node** value_inputs) FINAL {
- return graph()->NewNode(op, value_input_count, value_inputs);
+ Node** value_inputs, bool incomplete) FINAL {
+ return graph()->NewNode(op, value_input_count, value_inputs,
incomplete);
}
};
=======================================
---
/branches/bleeding_edge/test/cctest/compiler/simplified-graph-builder.cc
Wed Sep 10 12:23:45 2014 UTC
+++
/branches/bleeding_edge/test/cctest/compiler/simplified-graph-builder.cc
Mon Oct 27 10:12:16 2014 UTC
@@ -45,7 +45,7 @@
Node* SimplifiedGraphBuilder::MakeNode(const Operator* op,
int value_input_count,
- Node** value_inputs) {
+ Node** value_inputs, bool
incomplete) {
DCHECK(op->InputCount() == value_input_count);
DCHECK(!OperatorProperties::HasContextInput(op));
@@ -58,7 +58,7 @@
Node* result = NULL;
if (!has_control && !has_effect) {
- result = graph()->NewNode(op, value_input_count, value_inputs);
+ result = graph()->NewNode(op, value_input_count, value_inputs,
incomplete);
} else {
int input_count_with_deps = value_input_count;
if (has_control) ++input_count_with_deps;
@@ -72,7 +72,7 @@
if (has_control) {
*current_input++ = graph()->start();
}
- result = graph()->NewNode(op, input_count_with_deps, buffer);
+ result = graph()->NewNode(op, input_count_with_deps, buffer,
incomplete);
if (has_effect) {
effect_ = result;
}
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/simplified-graph-builder.h
Tue Oct 7 13:30:28 2014 UTC
+++ /branches/bleeding_edge/test/cctest/compiler/simplified-graph-builder.h
Mon Oct 27 10:12:16 2014 UTC
@@ -139,7 +139,7 @@
protected:
virtual Node* MakeNode(const Operator* op, int value_input_count,
- Node** value_inputs) FINAL;
+ Node** value_inputs, bool incomplete) FINAL;
private:
Node* effect_;
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.