51894ec36c
R=bmeurer@chromium.org Review URL: https://codereview.chromium.org/539903002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23681 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
300 lines
9.6 KiB
C++
300 lines
9.6 KiB
C++
// 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_CCTEST_COMPILER_STRUCTURED_MACHINE_ASSEMBLER_H_
|
|
#define V8_CCTEST_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, MachineSignature* machine_sig,
|
|
MachineType word = kMachPtr);
|
|
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_; }
|
|
size_t parameter_count() const { return machine_sig_->parameter_count(); }
|
|
MachineSignature* machine_sig() const { return machine_sig_; }
|
|
|
|
// Parameters.
|
|
Node* Parameter(size_t 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 ZoneVector<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);
|
|
|
|
Schedule* schedule_;
|
|
MachineOperatorBuilder machine_;
|
|
CommonOperatorBuilder common_;
|
|
MachineSignature* machine_sig_;
|
|
CallDescriptor* call_descriptor_;
|
|
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 ZoneVector<ExpressionState> ExpressionStates;
|
|
typedef ZoneVector<UnresolvedBranch*> PendingMergeStack;
|
|
struct IfClause;
|
|
typedef ZoneVector<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_CCTEST_COMPILER_STRUCTURED_MACHINE_ASSEMBLER_H_
|