diff options
Diffstat (limited to 'deps/v8/src/compiler/structured-machine-assembler.h')
-rw-r--r-- | deps/v8/src/compiler/structured-machine-assembler.h | 311 |
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 ¤t_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_ |