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);
}
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);
}
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 =
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;
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
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);
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) {
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);
}
// 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;
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);
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);
} 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;
}
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_; }
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_;
// 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);
}
// 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; }
// 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_;
// 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);
};
#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"
}
-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;
}
// 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); }
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);
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; }
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);
}
};
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));
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;
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;
}
protected:
virtual Node* MakeNode(const Operator* op, int value_input_count,
- Node** value_inputs) FINAL;
+ Node** value_inputs, bool incomplete) FINAL;
private:
Node* effect_;