| Index: src/full-codegen.h
|
| diff --git a/src/full-codegen.h b/src/full-codegen.h
|
| index 257f20c5023ea6c642d8f44bb03bf9fe895070df..8d9fe2d3322f7cd57f5c91395debf5cb965e342f 100644
|
| --- a/src/full-codegen.h
|
| +++ b/src/full-codegen.h
|
| @@ -31,6 +31,8 @@
|
| #include "v8.h"
|
|
|
| #include "ast.h"
|
| +#include "code-stubs.h"
|
| +#include "codegen.h"
|
| #include "compiler.h"
|
|
|
| namespace v8 {
|
| @@ -66,17 +68,39 @@ class BreakableStatementChecker: public AstVisitor {
|
|
|
| class FullCodeGenerator: public AstVisitor {
|
| public:
|
| + enum State {
|
| + NO_REGISTERS,
|
| + TOS_REG
|
| + };
|
| +
|
| explicit FullCodeGenerator(MacroAssembler* masm)
|
| : masm_(masm),
|
| info_(NULL),
|
| nesting_stack_(NULL),
|
| loop_depth_(0),
|
| - context_(NULL) {
|
| + context_(NULL),
|
| + bailout_entries_(0),
|
| + stack_checks_(2), // There's always at least one.
|
| + forward_bailout_stack_(NULL),
|
| + forward_bailout_pending_(NULL) {
|
| }
|
|
|
| static bool MakeCode(CompilationInfo* info);
|
|
|
| void Generate(CompilationInfo* info);
|
| + void PopulateDeoptimizationData(Handle<Code> code);
|
| +
|
| + class StateField : public BitField<State, 0, 8> { };
|
| + class PcField : public BitField<unsigned, 8, 32-8> { };
|
| +
|
| + static const char* State2String(State state) {
|
| + switch (state) {
|
| + case NO_REGISTERS: return "NO_REGISTERS";
|
| + case TOS_REG: return "TOS_REG";
|
| + }
|
| + UNREACHABLE();
|
| + return NULL;
|
| + }
|
|
|
| private:
|
| class Breakable;
|
| @@ -229,6 +253,24 @@ class FullCodeGenerator: public AstVisitor {
|
| DISALLOW_COPY_AND_ASSIGN(ForIn);
|
| };
|
|
|
| + // The forward bailout stack keeps track of the expressions that can
|
| + // bail out to just before the control flow is split in a child
|
| + // node. The stack elements are linked together through the parent
|
| + // link when visiting expressions in test contexts after requesting
|
| + // bailout in child forwarding.
|
| + class ForwardBailoutStack BASE_EMBEDDED {
|
| + public:
|
| + ForwardBailoutStack(Expression* expr, ForwardBailoutStack* parent)
|
| + : expr_(expr), parent_(parent) { }
|
| +
|
| + Expression* expr() const { return expr_; }
|
| + ForwardBailoutStack* parent() const { return parent_; }
|
| +
|
| + private:
|
| + Expression* const expr_;
|
| + ForwardBailoutStack* const parent_;
|
| + };
|
| +
|
| enum ConstantOperand {
|
| kNoConstants,
|
| kLeftConstant,
|
| @@ -274,19 +316,23 @@ class FullCodeGenerator: public AstVisitor {
|
| // register.
|
| MemOperand EmitSlotSearch(Slot* slot, Register scratch);
|
|
|
| + // Forward the bailout responsibility for the given expression to
|
| + // the next child visited (which must be in a test context).
|
| + void ForwardBailoutToChild(Expression* expr);
|
| +
|
| void VisitForEffect(Expression* expr) {
|
| EffectContext context(this);
|
| - Visit(expr);
|
| + HandleInNonTestContext(expr, NO_REGISTERS);
|
| }
|
|
|
| void VisitForAccumulatorValue(Expression* expr) {
|
| AccumulatorValueContext context(this);
|
| - Visit(expr);
|
| + HandleInNonTestContext(expr, TOS_REG);
|
| }
|
|
|
| void VisitForStackValue(Expression* expr) {
|
| StackValueContext context(this);
|
| - Visit(expr);
|
| + HandleInNonTestContext(expr, NO_REGISTERS);
|
| }
|
|
|
| void VisitForControl(Expression* expr,
|
| @@ -294,9 +340,15 @@ class FullCodeGenerator: public AstVisitor {
|
| Label* if_false,
|
| Label* fall_through) {
|
| TestContext context(this, if_true, if_false, fall_through);
|
| - Visit(expr);
|
| + VisitInTestContext(expr);
|
| + // Forwarding bailouts to children is a one shot operation. It
|
| + // should have been processed at this point.
|
| + ASSERT(forward_bailout_pending_ == NULL);
|
| }
|
|
|
| + void HandleInNonTestContext(Expression* expr, State state);
|
| + void VisitInTestContext(Expression* expr);
|
| +
|
| void VisitDeclarations(ZoneList<Declaration*>* declarations);
|
| void DeclareGlobals(Handle<FixedArray> pairs);
|
|
|
| @@ -310,12 +362,39 @@ class FullCodeGenerator: public AstVisitor {
|
| Label* if_false,
|
| Label* fall_through);
|
|
|
| + // Bailout support.
|
| + void PrepareForBailout(AstNode* node, State state);
|
| + void PrepareForBailoutForId(int id, State state);
|
| +
|
| + // Record a call's return site offset, used to rebuild the frame if the
|
| + // called function was inlined at the site.
|
| + void RecordJSReturnSite(Call* call);
|
| +
|
| + // Prepare for bailout before a test (or compare) and branch. If
|
| + // should_normalize, then the following comparison will not handle the
|
| + // canonical JS true value so we will insert a (dead) test against true at
|
| + // the actual bailout target from the optimized code. If not
|
| + // should_normalize, the true and false labels are ignored.
|
| + void PrepareForBailoutBeforeSplit(State state,
|
| + bool should_normalize,
|
| + Label* if_true,
|
| + Label* if_false);
|
| +
|
| // Platform-specific code for a variable, constant, or function
|
| // declaration. Functions have an initial value.
|
| void EmitDeclaration(Variable* variable,
|
| Variable::Mode mode,
|
| FunctionLiteral* function);
|
|
|
| + // Platform-specific code for checking the stack limit at the back edge of
|
| + // a loop.
|
| + void EmitStackCheck(IterationStatement* stmt);
|
| + // Record the OSR AST id corresponding to a stack check in the code.
|
| + void RecordStackCheck(int osr_ast_id);
|
| + // Emit a table of stack check ids and pcs into the code stream. Return
|
| + // the offset of the start of the table.
|
| + unsigned EmitStackCheckTable();
|
| +
|
| // Platform-specific return sequence
|
| void EmitReturnSequence();
|
|
|
| @@ -471,14 +550,13 @@ class FullCodeGenerator: public AstVisitor {
|
|
|
| void VisitForTypeofValue(Expression* expr);
|
|
|
| - MacroAssembler* masm_;
|
| - CompilationInfo* info_;
|
| + struct BailoutEntry {
|
| + unsigned id;
|
| + unsigned pc_and_state;
|
| + };
|
|
|
| - Label return_label_;
|
| - NestedStatement* nesting_stack_;
|
| - int loop_depth_;
|
|
|
| - class ExpressionContext {
|
| + class ExpressionContext BASE_EMBEDDED {
|
| public:
|
| explicit ExpressionContext(FullCodeGenerator* codegen)
|
| : masm_(codegen->masm()), old_(codegen->context()), codegen_(codegen) {
|
| @@ -504,7 +582,8 @@ class FullCodeGenerator: public AstVisitor {
|
|
|
| // Emit code to convert pure control flow to a pair of unbound labels into
|
| // the result expected according to this expression context. The
|
| - // implementation may decide to bind either of the labels.
|
| + // implementation will bind both labels unless it's a TestContext, which
|
| + // won't bind them at this point.
|
| virtual void Plug(Label* materialize_true,
|
| Label* materialize_false) const = 0;
|
|
|
| @@ -526,12 +605,14 @@ class FullCodeGenerator: public AstVisitor {
|
| Label** if_false,
|
| Label** fall_through) const = 0;
|
|
|
| + virtual void HandleExpression(Expression* expr) const = 0;
|
| +
|
| // Returns true if we are evaluating only for side effects (ie if the result
|
| - // will be discarded.
|
| + // will be discarded).
|
| virtual bool IsEffect() const { return false; }
|
|
|
| // Returns true if we are branching on the value rather than materializing
|
| - // it.
|
| + // it. Only used for asserts.
|
| virtual bool IsTest() const { return false; }
|
|
|
| protected:
|
| @@ -565,6 +646,7 @@ class FullCodeGenerator: public AstVisitor {
|
| Label** if_true,
|
| Label** if_false,
|
| Label** fall_through) const;
|
| + virtual void HandleExpression(Expression* expr) const;
|
| };
|
|
|
| class StackValueContext : public ExpressionContext {
|
| @@ -588,6 +670,7 @@ class FullCodeGenerator: public AstVisitor {
|
| Label** if_true,
|
| Label** if_false,
|
| Label** fall_through) const;
|
| + virtual void HandleExpression(Expression* expr) const;
|
| };
|
|
|
| class TestContext : public ExpressionContext {
|
| @@ -626,6 +709,7 @@ class FullCodeGenerator: public AstVisitor {
|
| Label** if_true,
|
| Label** if_false,
|
| Label** fall_through) const;
|
| + virtual void HandleExpression(Expression* expr) const;
|
| virtual bool IsTest() const { return true; }
|
|
|
| private:
|
| @@ -655,10 +739,20 @@ class FullCodeGenerator: public AstVisitor {
|
| Label** if_true,
|
| Label** if_false,
|
| Label** fall_through) const;
|
| + virtual void HandleExpression(Expression* expr) const;
|
| virtual bool IsEffect() const { return true; }
|
| };
|
|
|
| + MacroAssembler* masm_;
|
| + CompilationInfo* info_;
|
| + Label return_label_;
|
| + NestedStatement* nesting_stack_;
|
| + int loop_depth_;
|
| const ExpressionContext* context_;
|
| + ZoneList<BailoutEntry> bailout_entries_;
|
| + ZoneList<BailoutEntry> stack_checks_;
|
| + ForwardBailoutStack* forward_bailout_stack_;
|
| + ForwardBailoutStack* forward_bailout_pending_;
|
|
|
| friend class NestedStatement;
|
|
|
|
|