summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/structured-machine-assembler.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/structured-machine-assembler.h')
-rw-r--r--deps/v8/src/compiler/structured-machine-assembler.h311
1 files changed, 311 insertions, 0 deletions
diff --git a/deps/v8/src/compiler/structured-machine-assembler.h b/deps/v8/src/compiler/structured-machine-assembler.h
new file mode 100644
index 000000000..a6cb8ca88
--- /dev/null
+++ b/deps/v8/src/compiler/structured-machine-assembler.h
@@ -0,0 +1,311 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_STRUCTURED_MACHINE_ASSEMBLER_H_
+#define V8_COMPILER_STRUCTURED_MACHINE_ASSEMBLER_H_
+
+#include "src/v8.h"
+
+#include "src/compiler/common-operator.h"
+#include "src/compiler/graph-builder.h"
+#include "src/compiler/machine-node-factory.h"
+#include "src/compiler/machine-operator.h"
+#include "src/compiler/node.h"
+#include "src/compiler/operator.h"
+
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class BasicBlock;
+class Schedule;
+class StructuredMachineAssembler;
+
+
+class Variable : public ZoneObject {
+ public:
+ Node* Get() const;
+ void Set(Node* value) const;
+
+ private:
+ Variable(StructuredMachineAssembler* smasm, int offset)
+ : smasm_(smasm), offset_(offset) {}
+
+ friend class StructuredMachineAssembler;
+ friend class StructuredMachineAssemblerFriend;
+ StructuredMachineAssembler* const smasm_;
+ const int offset_;
+};
+
+
+class StructuredMachineAssembler
+ : public GraphBuilder,
+ public MachineNodeFactory<StructuredMachineAssembler> {
+ public:
+ class Environment : public ZoneObject {
+ public:
+ Environment(Zone* zone, BasicBlock* block, bool is_dead_);
+
+ private:
+ BasicBlock* block_;
+ NodeVector variables_;
+ bool is_dead_;
+ friend class StructuredMachineAssembler;
+ DISALLOW_COPY_AND_ASSIGN(Environment);
+ };
+
+ class IfBuilder;
+ friend class IfBuilder;
+ class LoopBuilder;
+ friend class LoopBuilder;
+
+ StructuredMachineAssembler(
+ Graph* graph, MachineCallDescriptorBuilder* call_descriptor_builder,
+ MachineType word = MachineOperatorBuilder::pointer_rep());
+ virtual ~StructuredMachineAssembler() {}
+
+ Isolate* isolate() const { return zone()->isolate(); }
+ Zone* zone() const { return graph()->zone(); }
+ MachineOperatorBuilder* machine() { return &machine_; }
+ CommonOperatorBuilder* common() { return &common_; }
+ CallDescriptor* call_descriptor() const {
+ return call_descriptor_builder_->BuildCallDescriptor(zone());
+ }
+ int parameter_count() const {
+ return call_descriptor_builder_->parameter_count();
+ }
+ const MachineType* parameter_types() const {
+ return call_descriptor_builder_->parameter_types();
+ }
+
+ // Parameters.
+ Node* Parameter(int index);
+ // Variables.
+ Variable NewVariable(Node* initial_value);
+ // Control flow.
+ void Return(Node* value);
+
+ // MachineAssembler is invalid after export.
+ Schedule* Export();
+
+ protected:
+ virtual Node* MakeNode(Operator* op, int input_count, Node** inputs);
+
+ Schedule* schedule() {
+ DCHECK(ScheduleValid());
+ return schedule_;
+ }
+
+ private:
+ bool ScheduleValid() { return schedule_ != NULL; }
+
+ typedef std::vector<Environment*, zone_allocator<Environment*> >
+ EnvironmentVector;
+
+ NodeVector* CurrentVars() { return &current_environment_->variables_; }
+ Node*& VariableAt(Environment* environment, int offset);
+ Node* GetVariable(int offset);
+ void SetVariable(int offset, Node* value);
+
+ void AddBranch(Environment* environment, Node* condition,
+ Environment* true_val, Environment* false_val);
+ void AddGoto(Environment* from, Environment* to);
+ BasicBlock* TrampolineFor(BasicBlock* block);
+
+ void CopyCurrentAsDead();
+ Environment* Copy(Environment* environment) {
+ return Copy(environment, static_cast<int>(environment->variables_.size()));
+ }
+ Environment* Copy(Environment* environment, int truncate_at);
+ void Merge(EnvironmentVector* environments, int truncate_at);
+ Environment* CopyForLoopHeader(Environment* environment);
+ void MergeBackEdgesToLoopHeader(Environment* header,
+ EnvironmentVector* environments);
+
+ typedef std::vector<MachineType, zone_allocator<MachineType> >
+ RepresentationVector;
+
+ Schedule* schedule_;
+ MachineOperatorBuilder machine_;
+ CommonOperatorBuilder common_;
+ MachineCallDescriptorBuilder* call_descriptor_builder_;
+ Node** parameters_;
+ Environment* current_environment_;
+ int number_of_variables_;
+
+ friend class Variable;
+ // For testing only.
+ friend class StructuredMachineAssemblerFriend;
+ DISALLOW_COPY_AND_ASSIGN(StructuredMachineAssembler);
+};
+
+// IfBuilder constructs of nested if-else expressions which more or less follow
+// C semantics. Foe example:
+//
+// if (x) {do_x} else if (y) {do_y} else {do_z}
+//
+// would look like this:
+//
+// IfBuilder b;
+// b.If(x).Then();
+// do_x
+// b.Else();
+// b.If().Then();
+// do_y
+// b.Else();
+// do_z
+// b.End();
+//
+// Then() and Else() can be skipped, representing an empty block in C.
+// Combinations like If(x).Then().If(x).Then() are legitimate, but
+// Else().Else() is not. That is, once you've nested an If(), you can't get to a
+// higher level If() branch.
+// TODO(dcarney): describe expressions once the api is finalized.
+class StructuredMachineAssembler::IfBuilder {
+ public:
+ explicit IfBuilder(StructuredMachineAssembler* smasm);
+ ~IfBuilder() {
+ if (!IsDone()) End();
+ }
+
+ IfBuilder& If(); // TODO(dcarney): this should take an expression.
+ IfBuilder& If(Node* condition);
+ void Then();
+ void Else();
+ void End();
+
+ // The next 4 functions are exposed for expression support.
+ // They will be private once I have a nice expression api.
+ void And();
+ void Or();
+ IfBuilder& OpenParen() {
+ DCHECK(smasm_->current_environment_ != NULL);
+ CurrentClause()->PushNewExpressionState();
+ return *this;
+ }
+ IfBuilder& CloseParen() {
+ DCHECK(smasm_->current_environment_ == NULL);
+ CurrentClause()->PopExpressionState();
+ return *this;
+ }
+
+ private:
+ // UnresolvedBranch represents the chain of environments created while
+ // generating an expression. At this point, a branch Node
+ // cannot be created, as the target environments of the branch are not yet
+ // available, so everything required to create the branch Node is
+ // stored in this structure until the target environments are resolved.
+ struct UnresolvedBranch : public ZoneObject {
+ UnresolvedBranch(Environment* environment, Node* condition,
+ UnresolvedBranch* next)
+ : environment_(environment), condition_(condition), next_(next) {}
+ // environment_ will eventually be terminated by a branch on condition_.
+ Environment* environment_;
+ Node* condition_;
+ // next_ is the next link in the UnresolvedBranch chain, and will be
+ // either the true or false branch jumped to from environment_.
+ UnresolvedBranch* next_;
+ };
+
+ struct ExpressionState {
+ int pending_then_size_;
+ int pending_else_size_;
+ };
+
+ typedef std::vector<ExpressionState, zone_allocator<ExpressionState> >
+ ExpressionStates;
+ typedef std::vector<UnresolvedBranch*, zone_allocator<UnresolvedBranch*> >
+ PendingMergeStack;
+ struct IfClause;
+ typedef std::vector<IfClause*, zone_allocator<IfClause*> > IfClauses;
+
+ struct PendingMergeStackRange {
+ PendingMergeStack* merge_stack_;
+ int start_;
+ int size_;
+ };
+
+ enum CombineType { kCombineThen, kCombineElse };
+ enum ResolutionType { kExpressionTerm, kExpressionDone };
+
+ // IfClause represents one level of if-then-else nesting plus the associated
+ // expression.
+ // A call to If() triggers creation of a new nesting level after expression
+ // creation is complete - ie Then() or Else() has been called.
+ struct IfClause : public ZoneObject {
+ IfClause(Zone* zone, int initial_environment_size);
+ void CopyEnvironments(const PendingMergeStackRange& data,
+ EnvironmentVector* environments);
+ void ResolvePendingMerges(StructuredMachineAssembler* smasm,
+ CombineType combine_type,
+ ResolutionType resolution_type);
+ PendingMergeStackRange ComputeRelevantMerges(CombineType combine_type);
+ void FinalizeBranches(StructuredMachineAssembler* smasm,
+ const PendingMergeStackRange& offset_data,
+ CombineType combine_type,
+ Environment* then_environment,
+ Environment* else_environment);
+ void PushNewExpressionState();
+ void PopExpressionState();
+
+ // Each invocation of And or Or creates a new UnresolvedBranch.
+ // These form a singly-linked list, of which we only need to keep track of
+ // the tail. On creation of an UnresolvedBranch, pending_then_merges_ and
+ // pending_else_merges_ each push a copy, which are removed on merges to the
+ // respective environment.
+ UnresolvedBranch* unresolved_list_tail_;
+ int initial_environment_size_;
+ // expression_states_ keeps track of the state of pending_*_merges_,
+ // pushing and popping the lengths of these on
+ // OpenParend() and CloseParend() respectively.
+ ExpressionStates expression_states_;
+ PendingMergeStack pending_then_merges_;
+ PendingMergeStack pending_else_merges_;
+ // then_environment_ is created iff there is a call to Then(), otherwise
+ // branches which would merge to it merge to the exit environment instead.
+ // Likewise for else_environment_.
+ Environment* then_environment_;
+ Environment* else_environment_;
+ };
+
+ IfClause* CurrentClause() { return if_clauses_.back(); }
+ void AddCurrentToPending();
+ void PushNewIfClause();
+ bool IsDone() { return if_clauses_.empty(); }
+
+ StructuredMachineAssembler* smasm_;
+ IfClauses if_clauses_;
+ EnvironmentVector pending_exit_merges_;
+ DISALLOW_COPY_AND_ASSIGN(IfBuilder);
+};
+
+
+class StructuredMachineAssembler::LoopBuilder {
+ public:
+ explicit LoopBuilder(StructuredMachineAssembler* smasm);
+ ~LoopBuilder() {
+ if (!IsDone()) End();
+ }
+
+ void Break();
+ void Continue();
+ void End();
+
+ private:
+ friend class StructuredMachineAssembler;
+ bool IsDone() { return header_environment_ == NULL; }
+
+ StructuredMachineAssembler* smasm_;
+ Environment* header_environment_;
+ EnvironmentVector pending_header_merges_;
+ EnvironmentVector pending_exit_merges_;
+ DISALLOW_COPY_AND_ASSIGN(LoopBuilder);
+};
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
+
+#endif // V8_COMPILER_STRUCTURED_MACHINE_ASSEMBLER_H_