105ed9ddc6ff3a1ab3983c50d378cddfa257869b6jkummerow@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
4b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org#ifndef V8_FULL_CODEGEN_H_
6b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org#define V8_FULL_CODEGEN_H_
7b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
8196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org
10196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/allocation.h"
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/assert-scope.h"
12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/ast.h"
13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/code-stubs.h"
14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/codegen.h"
15196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/compiler.h"
16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/data-flow.h"
17196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/globals.h"
18196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/objects.h"
19b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
20b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgnamespace v8 {
21b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgnamespace internal {
22b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
235f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org// Forward declarations.
245f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.orgclass JumpPatchSite;
255f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
262356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org// AST node visitor which can tell whether a given statement will be breakable
272356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org// when the code is compiled by the full compiler in the debugger. This means
282356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org// that there will be an IC (load/store/call) in the code generated for the
292356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org// debugger to piggybag on.
302356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.orgclass BreakableStatementChecker: public AstVisitor {
312356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org public:
326d26cbb00b8ff12ecf86400c59f4a18d3850f22dmachenbach@chromium.org  explicit BreakableStatementChecker(Zone* zone) : is_breakable_(false) {
336d26cbb00b8ff12ecf86400c59f4a18d3850f22dmachenbach@chromium.org    InitializeAstVisitor(zone);
34a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
352356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
362356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  void Check(Statement* stmt);
372356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  void Check(Expression* stmt);
382356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
392356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  bool is_breakable() { return is_breakable_; }
402356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
412356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org private:
422356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  // AST node visit functions.
432356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
442356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  AST_NODE_LIST(DECLARE_VISIT)
452356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org#undef DECLARE_VISIT
462356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
472356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  bool is_breakable_;
482356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
49a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
502356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  DISALLOW_COPY_AND_ASSIGN(BreakableStatementChecker);
512356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org};
522356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
532356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
54b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// -----------------------------------------------------------------------------
55b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// Full code generator.
56b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
57b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgclass FullCodeGenerator: public AstVisitor {
58b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org public:
59a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  enum State {
60a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    NO_REGISTERS,
61a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    TOS_REG
62a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  };
63a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
645a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  FullCodeGenerator(MacroAssembler* masm, CompilationInfo* info)
65b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      : masm_(masm),
6656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        info_(info),
6756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        scope_(info->scope()),
68b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        nesting_stack_(NULL),
69b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        loop_depth_(0),
70ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com        globals_(NULL),
71a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org        context_(NULL),
7256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        bailout_entries_(info->HasDeoptimizationSupport()
735a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org                         ? info->function()->ast_node_count() : 0,
745a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org                         info->zone()),
75e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        back_edges_(2, info->zone()),
766d26cbb00b8ff12ecf86400c59f4a18d3850f22dmachenbach@chromium.org        ic_total_count_(0) {
77e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!info->IsStub());
78000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org    Initialize();
79000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org  }
80000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org
81000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org  void Initialize();
82b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
83b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org  static bool MakeCode(CompilationInfo* info);
84b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
8556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  // Encode state and pc-offset as a BitField<type, start, size>.
8656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  // Only use 30 bits because we encode the result as a smi.
8756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  class StateField : public BitField<State, 0, 1> { };
8856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  class PcField    : public BitField<unsigned, 1, 30-1> { };
89a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
90a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  static const char* State2String(State state) {
91a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    switch (state) {
92a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      case NO_REGISTERS: return "NO_REGISTERS";
93a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      case TOS_REG: return "TOS_REG";
94a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    }
95a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    UNREACHABLE();
96a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    return NULL;
97a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
98b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
99129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org  static const int kMaxBackEdgeWeight = 127;
100129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org
101b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  // Platform-specific code size multiplier.
102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
103a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  static const int kCodeSizeMultiplier = 105;
1048496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org  static const int kBootCodeSizeMultiplier = 100;
105129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org#elif V8_TARGET_ARCH_X64
106a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  static const int kCodeSizeMultiplier = 170;
1078496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org  static const int kBootCodeSizeMultiplier = 140;
108129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org#elif V8_TARGET_ARCH_ARM
109a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  static const int kCodeSizeMultiplier = 149;
1108496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org  static const int kBootCodeSizeMultiplier = 110;
111fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#elif V8_TARGET_ARCH_ARM64
112fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org// TODO(all): Copied ARM value. Check this is sensible for ARM64.
113a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  static const int kCodeSizeMultiplier = 149;
1148496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org  static const int kBootCodeSizeMultiplier = 110;
115129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org#elif V8_TARGET_ARCH_MIPS
116a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  static const int kCodeSizeMultiplier = 149;
1178496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org  static const int kBootCodeSizeMultiplier = 120;
11812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#elif V8_TARGET_ARCH_MIPS64
11912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  static const int kCodeSizeMultiplier = 149;
12012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  static const int kBootCodeSizeMultiplier = 120;
121129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org#else
122129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org#error Unsupported target architecture.
123129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org#endif
124129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org
125b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org private:
126b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  class Breakable;
127b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  class Iteration;
12828a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org
1296d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  class TestContext;
130b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
131b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  class NestedStatement BASE_EMBEDDED {
132b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org   public:
133b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    explicit NestedStatement(FullCodeGenerator* codegen) : codegen_(codegen) {
134b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      // Link into codegen's nesting stack.
135b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      previous_ = codegen->nesting_stack_;
136b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      codegen->nesting_stack_ = this;
137b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
138b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    virtual ~NestedStatement() {
139b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      // Unlink from codegen's nesting stack.
140e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK_EQ(this, codegen_->nesting_stack_);
141b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      codegen_->nesting_stack_ = previous_;
142b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
143b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
144b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    virtual Breakable* AsBreakable() { return NULL; }
145b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    virtual Iteration* AsIteration() { return NULL; }
146b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
147b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    virtual bool IsContinueTarget(Statement* target) { return false; }
148b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    virtual bool IsBreakTarget(Statement* target) { return false; }
149b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1504acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    // Notify the statement that we are exiting it via break, continue, or
1514acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    // return and give it a chance to generate cleanup code.  Return the
1524acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    // next outer statement in the nesting stack.  We accumulate in
1534acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    // *stack_depth the amount to drop the stack and in *context_length the
1544acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    // number of context chain links to unwind as we traverse the nesting
1554acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    // stack from an exit to its target.
1564acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
1574acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org      return previous_;
158b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
159e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org
16005ed9ddc6ff3a1ab3983c50d378cddfa257869b6jkummerow@chromium.org   protected:
161b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    MacroAssembler* masm() { return codegen_->masm(); }
162e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org
163b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    FullCodeGenerator* codegen_;
164b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    NestedStatement* previous_;
16505ed9ddc6ff3a1ab3983c50d378cddfa257869b6jkummerow@chromium.org
16605ed9ddc6ff3a1ab3983c50d378cddfa257869b6jkummerow@chromium.org   private:
167b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    DISALLOW_COPY_AND_ASSIGN(NestedStatement);
168b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  };
169b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
17028a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org  // A breakable statement such as a block.
171b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  class Breakable : public NestedStatement {
172b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org   public:
17328a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    Breakable(FullCodeGenerator* codegen, BreakableStatement* statement)
17428a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org        : NestedStatement(codegen), statement_(statement) {
17528a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    }
176b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    virtual ~Breakable() {}
17728a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org
178b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    virtual Breakable* AsBreakable() { return this; }
17928a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    virtual bool IsBreakTarget(Statement* target) {
18028a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org      return statement() == target;
181b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
18228a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org
18328a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    BreakableStatement* statement() { return statement_; }
18428a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    Label* break_label() { return &break_label_; }
18528a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org
186b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org   private:
18728a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    BreakableStatement* statement_;
18828a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    Label break_label_;
189b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  };
190b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
19128a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org  // An iteration statement such as a while, for, or do loop.
192b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  class Iteration : public Breakable {
193b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org   public:
19428a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    Iteration(FullCodeGenerator* codegen, IterationStatement* statement)
19528a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org        : Breakable(codegen, statement) {
19628a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    }
197b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    virtual ~Iteration() {}
19828a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org
199b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    virtual Iteration* AsIteration() { return this; }
20028a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    virtual bool IsContinueTarget(Statement* target) {
20128a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org      return statement() == target;
202b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
20328a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org
20428a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    Label* continue_label() { return &continue_label_; }
20528a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org
206b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org   private:
20728a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    Label continue_label_;
208b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  };
209b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
210486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // A nested block statement.
211486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  class NestedBlock : public Breakable {
212486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org   public:
213486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    NestedBlock(FullCodeGenerator* codegen, Block* block)
214486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org        : Breakable(codegen, block) {
215486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    }
216486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    virtual ~NestedBlock() {}
217486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org
218486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
219ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      if (statement()->AsBlock()->scope() != NULL) {
220486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org        ++(*context_length);
221486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      }
222486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      return previous_;
2233c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    }
224486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  };
225486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org
22628a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org  // The try block of a try/catch statement.
227b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  class TryCatch : public NestedStatement {
228b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org   public:
22928a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    explicit TryCatch(FullCodeGenerator* codegen) : NestedStatement(codegen) {
23028a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    }
231b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    virtual ~TryCatch() {}
23228a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org
2334acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    virtual NestedStatement* Exit(int* stack_depth, int* context_length);
234b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  };
235b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
23628a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org  // The try block of a try/finally statement.
237b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  class TryFinally : public NestedStatement {
238b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org   public:
23928a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
24028a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org        : NestedStatement(codegen), finally_entry_(finally_entry) {
24128a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    }
242b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    virtual ~TryFinally() {}
24328a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org
2444acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    virtual NestedStatement* Exit(int* stack_depth, int* context_length);
24528a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org
246b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org   private:
247b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    Label* finally_entry_;
248b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  };
249b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
25028a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org  // The finally block of a try/finally statement.
251b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  class Finally : public NestedStatement {
252b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org   public:
2537028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    static const int kElementCount = 5;
25428a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org
255b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) { }
256b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    virtual ~Finally() {}
25728a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org
2584acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
25928a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org      *stack_depth += kElementCount;
2604acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org      return previous_;
261b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
262b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  };
263b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
26428a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org  // The body of a for/in loop.
265b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  class ForIn : public Iteration {
266b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org   public:
26728a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    static const int kElementCount = 5;
26828a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org
26928a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    ForIn(FullCodeGenerator* codegen, ForInStatement* statement)
27028a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org        : Iteration(codegen, statement) {
27128a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    }
272b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    virtual ~ForIn() {}
27328a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org
2744acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
27528a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org      *stack_depth += kElementCount;
2764acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org      return previous_;
277b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
278b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  };
279b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2804acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
28128a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org  // The body of a with or catch.
2824acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  class WithOrCatch : public NestedStatement {
2834acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org   public:
2844acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    explicit WithOrCatch(FullCodeGenerator* codegen)
2854acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org        : NestedStatement(codegen) {
2864acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    }
2874acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    virtual ~WithOrCatch() {}
2884acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
2894acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
2904acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org      ++(*context_length);
2914acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org      return previous_;
2924acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    }
2934acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  };
2944acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
295d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // Type of a member function that generates inline code for a native function.
296c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  typedef void (FullCodeGenerator::*InlineFunctionGenerator)(CallRuntime* expr);
297d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com
298d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  static const InlineFunctionGenerator kInlineFunctionGenerators[];
299d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com
3005f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // A platform-specific utility to overwrite the accumulator register
3015f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // with a GC-safe value.
3025f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  void ClearAccumulator();
3035f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
30465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Determine whether or not to inline the smi case for the given
30565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // operation.
30665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  bool ShouldInlineSmiCase(Token::Value op);
30765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
308b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Helper function to convert a pure value into a test context.  The value
309b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // is expected on the stack or the accumulator, depending on the platform.
310b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // See the platform-specific implementation for details.
3116d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  void DoTest(Expression* condition,
3126d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org              Label* if_true,
3136d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org              Label* if_false,
3146d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org              Label* fall_through);
3156d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  void DoTest(const TestContext* context);
31665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
31765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Helper function to split control flow and avoid a branch to the
31865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // fall-through label if it is set up.
31993a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_MIPS
32065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  void Split(Condition cc,
321c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org             Register lhs,
322c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org             const Operand&  rhs,
32365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org             Label* if_true,
32465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org             Label* if_false,
32565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org             Label* fall_through);
32612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#elif V8_TARGET_ARCH_MIPS64
32712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  void Split(Condition cc,
32812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org             Register lhs,
32912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org             const Operand&  rhs,
33012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org             Label* if_true,
33112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org             Label* if_false,
33212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org             Label* fall_through);
333c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org#else  // All non-mips arch.
334c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  void Split(Condition cc,
335c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org             Label* if_true,
336c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org             Label* if_false,
337c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org             Label* fall_through);
338c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org#endif  // V8_TARGET_ARCH_MIPS
339b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
340486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // Load the value of a known (PARAMETER, LOCAL, or CONTEXT) variable into
341486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // a register.  Emits a context chain walk if if necessary (so does
342486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // SetVar) so avoid calling both on the same variable.
343486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  void GetVar(Register destination, Variable* var);
344486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org
345486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // Assign to a known (PARAMETER, LOCAL, or CONTEXT) variable.  If it's in
346486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // the context, the write barrier will be emitted and source, scratch0,
347486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // scratch1 will be clobbered.  Emits a context chain walk if if necessary
348486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // (so does GetVar) so avoid calling both on the same variable.
349486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  void SetVar(Variable* var,
350486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org              Register source,
351486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org              Register scratch0,
352486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org              Register scratch1);
353486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org
354486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // An operand used to read/write a stack-allocated (PARAMETER or LOCAL)
355486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // variable.  Writing does not need the write barrier.
356486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  MemOperand StackOperand(Variable* var);
357486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org
358486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // An operand used to read/write a known (PARAMETER, LOCAL, or CONTEXT)
359486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // variable.  May emit code to traverse the context chain, loading the
360486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // found context into the scratch register.  Writing to this operand will
361486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // need the write barrier if location is CONTEXT.
362486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  MemOperand VarOperand(Variable* var, Register scratch);
363b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
364b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void VisitForEffect(Expression* expr) {
3654a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    EffectContext context(this);
366c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Visit(expr);
367c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    PrepareForBailout(expr, NO_REGISTERS);
3684a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  }
3694a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
3704a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  void VisitForAccumulatorValue(Expression* expr) {
3714a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    AccumulatorValueContext context(this);
372c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Visit(expr);
373c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    PrepareForBailout(expr, TOS_REG);
374b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
375b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
3764a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  void VisitForStackValue(Expression* expr) {
3774a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    StackValueContext context(this);
378c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Visit(expr);
379c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    PrepareForBailout(expr, NO_REGISTERS);
380b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
381b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
38265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  void VisitForControl(Expression* expr,
38365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                       Label* if_true,
38465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                       Label* if_false,
38565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                       Label* fall_through) {
3866d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    TestContext context(this, expr, if_true, if_false, fall_through);
387c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Visit(expr);
388c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    // For test contexts, we prepare for bailout before branching, not at
389c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    // the end of the entire expression.  This happens as part of visiting
390c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    // the expression.
391b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
392b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
393c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  void VisitInDuplicateContext(Expression* expr);
394c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
395b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void VisitDeclarations(ZoneList<Declaration*>* declarations);
3968e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  void DeclareModules(Handle<FixedArray> descriptions);
397b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void DeclareGlobals(Handle<FixedArray> pairs);
3981805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  int DeclareGlobalsFlags();
399b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4008e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  // Generate code to allocate all (including nested) modules and contexts.
4018e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  // Because of recursive linking and the presence of module alias declarations,
4028e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  // this has to be a separate pass _before_ populating or executing any module.
4038e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  void AllocateModules(ZoneList<Declaration*>* declarations);
4048e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
40541728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  // Generate code to create an iterator result object.  The "value" property is
40641728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  // set to a value popped from the stack, and "done" is set according to the
40741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  // argument.  The result object is left in the result register.
40841728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  void EmitCreateIteratorResult(bool done);
40957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
41065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Try to perform a comparison as a fast inlined literal compare if
41165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // the operands allow it.  Returns true if the compare operations
41265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // has been matched and all code generated; false otherwise.
413c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bool TryLiteralCompare(CompareOperation* compare);
41465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
41504921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org  // Platform-specific code for comparing the type of a value with
41604921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org  // a given literal string.
417c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  void EmitLiteralCompareTypeof(Expression* expr,
418c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                Expression* sub_expr,
419c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                Handle<String> check);
420c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
421c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Platform-specific code for equality comparison with a nil-like value.
422c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void EmitLiteralCompareNil(CompareOperation* expr,
423c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                             Expression* sub_expr,
424c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                             NilValue nil);
42504921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org
426a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Bailout support.
427d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org  void PrepareForBailout(Expression* node, State state);
428471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  void PrepareForBailoutForId(BailoutId id, State state);
429a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
430f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Feedback slot support. The feedback vector will be cleared during gc and
431f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // collected by the type-feedback oracle.
432f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Handle<FixedArray> FeedbackVector() {
433a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org    return info_->feedback_vector();
434f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
435a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  void EnsureSlotContainsAllocationSite(int slot);
436fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
437a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Record a call's return site offset, used to rebuild the frame if the
438a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // called function was inlined at the site.
439a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  void RecordJSReturnSite(Call* call);
440a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
441a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Prepare for bailout before a test (or compare) and branch.  If
442a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // should_normalize, then the following comparison will not handle the
443a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // canonical JS true value so we will insert a (dead) test against true at
444a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // the actual bailout target from the optimized code. If not
445a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // should_normalize, the true and false labels are ignored.
446c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  void PrepareForBailoutBeforeSplit(Expression* expr,
447a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                    bool should_normalize,
448a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                    Label* if_true,
449a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                    Label* if_false);
450a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
451ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // If enabled, emit debug code for checking that the current context is
452ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // neither a with nor a catch context.
453ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  void EmitDebugCheckDeclarationContext(Variable* variable);
4549dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
45556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  // This is meant to be called at loop back edges, |back_edge_target| is
45656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  // the jump target of the back edge and is used to approximate the amount
45756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  // of code inside the loop.
458cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org  void EmitBackEdgeBookkeeping(IterationStatement* stmt,
459cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org                               Label* back_edge_target);
460cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org  // Record the OSR AST id corresponding to a back edge in the code.
461cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org  void RecordBackEdge(BailoutId osr_ast_id);
462e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Emit a table of back edge ids, pcs and loop depths into the code stream.
463e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Return the offset of the start of the table.
464e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  unsigned EmitBackEdgeTable();
465a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4664efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  void EmitProfilingCounterDecrement(int delta);
4674efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  void EmitProfilingCounterReset();
4684efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org
46941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  // Emit code to pop values from the stack associated with nested statements
47041728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  // like try/catch, try/finally, etc, running the finallies and unwinding the
47141728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  // handlers as needed.
47241728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  void EmitUnwindBeforeReturn();
47341728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org
474b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Platform-specific return sequence
4752cc82ae439960d1adaf4374e093730dc23945d59ager@chromium.org  void EmitReturnSequence();
476b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
477b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Platform-specific code sequences for calls
478d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  void EmitCall(Call* expr, CallICState::CallType = CallICState::FUNCTION);
479a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  void EmitCallWithLoadIC(Call* expr);
480a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  void EmitSuperCallWithLoadIC(Call* expr);
481a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  void EmitKeyedCallWithLoadIC(Call* expr, Expression* key);
482b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4839dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Platform-specific code for inline runtime calls.
484d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  InlineFunctionGenerator FindInlineFunctionGenerator(Runtime::FunctionId id);
485d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com
4869dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  void EmitInlineRuntimeCall(CallRuntime* expr);
487145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com
488145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com#define EMIT_INLINE_RUNTIME_CALL(name, x, y) \
489c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  void Emit##name(CallRuntime* expr);
490d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
491145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com#undef EMIT_INLINE_RUNTIME_CALL
4929dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
493ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Platform-specific code for resuming generators.
494ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  void EmitGeneratorResume(Expression *generator,
495ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org                           Expression *value,
496ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org                           JSGeneratorObject::ResumeMode resume_mode);
497ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
498b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Platform-specific code for loading variables.
4999d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org  void EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
500486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org                                     TypeofState typeof_state,
501486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org                                     Label* slow);
502486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  MemOperand ContextSlotOperandCheckExtensions(Variable* var, Label* slow);
5039d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org  void EmitDynamicLookupFastCase(VariableProxy* proxy,
504486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org                                 TypeofState typeof_state,
505486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org                                 Label* slow,
506486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org                                 Label* done);
507030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.org  void EmitVariableLoad(VariableProxy* proxy);
508b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5092c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org  void EmitAccessor(Expression* expression);
5102c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org
5119ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  // Expects the arguments and the function already pushed.
512c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  void EmitResolvePossiblyDirectEval(int arg_count);
5139ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
5149dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Platform-specific support for allocating a new closure based on
5159dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // the given function info.
51621b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org  void EmitNewClosure(Handle<SharedFunctionInfo> info, bool pretenure);
5179dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
518b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Platform-specific support for compiling assignments.
519b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
520b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Load a value from a named property.
521b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // The receiver is left on the stack by the IC.
522b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void EmitNamedPropertyLoad(Property* expr);
523b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
524a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  void EmitNamedSuperPropertyLoad(Property* expr);
525a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
526b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Load a value from a keyed property.
527b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // The receiver and the key is left on the stack by the IC.
528b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void EmitKeyedPropertyLoad(Property* expr);
529b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
530b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Apply the compound assignment operator. Expects the left operand on top
531b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // of the stack and the right one in the accumulator.
5328e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  void EmitBinaryOp(BinaryOperation* expr,
5338e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org                    Token::Value op,
53465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                    OverwriteMode mode);
535b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
536d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // Helper functions for generating inlined smi code for certain
537d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // binary operations.
5388e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  void EmitInlineSmiBinaryOp(BinaryOperation* expr,
539d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org                             Token::Value op,
540d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org                             OverwriteMode mode,
541d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org                             Expression* left,
5429ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org                             Expression* right);
543d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
5449dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Assign to the given expression as if via '='. The right-hand-side value
5459dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // is expected in the accumulator.
546be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  void EmitAssignment(Expression* expr);
5479dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
548b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Complete a variable assignment.  The right-hand-side value is expected
549b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // in the accumulator.
5509dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  void EmitVariableAssignment(Variable* var,
5514a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                              Token::Value op);
552b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
553f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Helper functions to EmitVariableAssignment
554f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void EmitStoreToStackLocalOrContextSlot(Variable* var,
555f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                          MemOperand location);
556f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
557b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Complete a named property assignment.  The receiver is expected on top
558b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // of the stack and the right-hand-side value in the accumulator.
559b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void EmitNamedPropertyAssignment(Assignment* expr);
560b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
561b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Complete a keyed property assignment.  The receiver and key are
562b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // expected on top of the stack and the right-hand-side value in the
563b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // accumulator.
564b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void EmitKeyedPropertyAssignment(Assignment* expr);
565b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
566a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  void EmitLoadHomeObject(SuperReference* expr);
567a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
568f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  void CallIC(Handle<Code> code,
569471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org              TypeFeedbackId id = TypeFeedbackId::None());
570f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
5719cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  void CallLoadIC(ContextualMode mode,
5729cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org                  TypeFeedbackId id = TypeFeedbackId::None());
573f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void CallStoreIC(TypeFeedbackId id = TypeFeedbackId::None());
5749cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org
575b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void SetFunctionPosition(FunctionLiteral* fun);
576b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void SetReturnPosition(FunctionLiteral* fun);
577b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void SetStatementPosition(Statement* stmt);
578a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  void SetExpressionPosition(Expression* expr);
579a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  void SetSourcePosition(int pos);
580b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
581b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Non-local control flow support.
582b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void EnterFinallyBlock();
583b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void ExitFinallyBlock();
584b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
585b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Loop nesting counter.
586b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  int loop_depth() { return loop_depth_; }
587b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void increment_loop_depth() { loop_depth_++; }
588b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void decrement_loop_depth() {
589e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(loop_depth_ > 0);
590b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    loop_depth_--;
591b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
592b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
593b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  MacroAssembler* masm() { return masm_; }
5945c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5954a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  class ExpressionContext;
5964a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  const ExpressionContext* context() { return context_; }
5974a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  void set_new_context(const ExpressionContext* context) { context_ = context; }
5984a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
5995c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Handle<Script> script() { return info_->script(); }
6005c838251403b0be9a882540f1922577abba4c872ager@chromium.org  bool is_eval() { return info_->is_eval(); }
6011805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  bool is_native() { return info_->is_native(); }
602486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  StrictMode strict_mode() { return function()->strict_mode(); }
6035c838251403b0be9a882540f1922577abba4c872ager@chromium.org  FunctionLiteral* function() { return info_->function(); }
6044f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  Scope* scope() { return scope_; }
6055c838251403b0be9a882540f1922577abba4c872ager@chromium.org
606b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  static Register result_register();
607b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  static Register context_register();
608b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
609b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Set fields in the stack frame. Offsets are the frame pointer relative
610b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // offsets defined in, e.g., StandardFrameConstants.
611b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void StoreToFrameField(int frame_offset, Register value);
612b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
613b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Load a value from the current context. Indices are defined as an enum
614b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // in v8::internal::Context.
615b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void LoadContextField(Register dst, int context_index);
616b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
6173cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Push the function argument for the runtime functions PushWithContext
6183cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // and PushCatchContext.
6193cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  void PushFunctionArgumentForContextAllocation();
6203cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
621b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // AST node visit functions.
622b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
623b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  AST_NODE_LIST(DECLARE_VISIT)
624b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org#undef DECLARE_VISIT
6258e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org
626d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org  void VisitComma(BinaryOperation* expr);
627d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org  void VisitLogicalExpression(BinaryOperation* expr);
628d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org  void VisitArithmeticExpression(BinaryOperation* expr);
629b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
6304a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  void VisitForTypeofValue(Expression* expr);
63165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
632f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  void Generate();
633f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  void PopulateDeoptimizationData(Handle<Code> code);
634f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  void PopulateTypeFeedbackInfo(Handle<Code> code);
635f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
636f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  Handle<FixedArray> handler_table() { return handler_table_; }
637f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
638a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  struct BailoutEntry {
639471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org    BailoutId id;
640a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    unsigned pc_and_state;
641a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  };
642b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
643e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  struct BackEdgeEntry {
644e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    BailoutId id;
645e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    unsigned pc;
646ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    uint32_t loop_depth;
647e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  };
648e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
649a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  class ExpressionContext BASE_EMBEDDED {
6504a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org   public:
6514a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    explicit ExpressionContext(FullCodeGenerator* codegen)
6524a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        : masm_(codegen->masm()), old_(codegen->context()), codegen_(codegen) {
6534a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      codegen->set_new_context(this);
6544a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    }
6554a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6564a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual ~ExpressionContext() {
6574a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      codegen_->set_new_context(old_);
6584a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    }
6594a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
660ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    Isolate* isolate() const { return codegen_->isolate(); }
661ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
6624a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    // Convert constant control flow (true or false) to the result expected for
6634a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    // this expression context.
6644a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(bool flag) const = 0;
6654a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
666486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // Emit code to convert a pure value (in a register, known variable
667486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // location, as a literal, or on top of the stack) into the result
668486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // expected according to this expression context.
6694a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Register reg) const = 0;
670486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    virtual void Plug(Variable* var) const = 0;
6714a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Handle<Object> lit) const = 0;
6724a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Heap::RootListIndex index) const = 0;
6734a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void PlugTOS() const = 0;
6744a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6754a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    // Emit code to convert pure control flow to a pair of unbound labels into
6764a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    // the result expected according to this expression context.  The
677a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // implementation will bind both labels unless it's a TestContext, which
678a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // won't bind them at this point.
6794a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Label* materialize_true,
6804a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                      Label* materialize_false) const = 0;
6814a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6824a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    // Emit code to discard count elements from the top of stack, then convert
6834a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    // a pure value into the result expected according to this expression
6844a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    // context.
6854a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void DropAndPlug(int count, Register reg) const = 0;
6864a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6874a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    // Set up branch labels for a test expression.  The three Label** parameters
6884a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    // are output parameters.
6894a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void PrepareTest(Label* materialize_true,
6904a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label* materialize_false,
6914a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** if_true,
6924a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** if_false,
6934a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** fall_through) const = 0;
6944a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6952efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    // Returns true if we are evaluating only for side effects (i.e. if the
6962efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    // result will be discarded).
6974a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual bool IsEffect() const { return false; }
6984a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
699d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    // Returns true if we are evaluating for the value (in accu/on stack).
700d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    virtual bool IsAccumulatorValue() const { return false; }
701d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    virtual bool IsStackValue() const { return false; }
702d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org
7034a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    // Returns true if we are branching on the value rather than materializing
704a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // it.  Only used for asserts.
7054a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual bool IsTest() const { return false; }
7064a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
7074a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org   protected:
7084a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    FullCodeGenerator* codegen() const { return codegen_; }
7094a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    MacroAssembler* masm() const { return masm_; }
7104a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    MacroAssembler* masm_;
7114a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
7124a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org   private:
7134a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    const ExpressionContext* old_;
7144a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    FullCodeGenerator* codegen_;
7154a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  };
7164a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
7174a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  class AccumulatorValueContext : public ExpressionContext {
7184a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org   public:
7194a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    explicit AccumulatorValueContext(FullCodeGenerator* codegen)
720c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        : ExpressionContext(codegen) { }
7214a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
7224a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(bool flag) const;
7234a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Register reg) const;
7244a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Label* materialize_true, Label* materialize_false) const;
725486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    virtual void Plug(Variable* var) const;
7264a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Handle<Object> lit) const;
7274a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Heap::RootListIndex) const;
7284a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void PlugTOS() const;
7294a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void DropAndPlug(int count, Register reg) const;
7304a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void PrepareTest(Label* materialize_true,
7314a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label* materialize_false,
7324a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** if_true,
7334a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** if_false,
7344a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** fall_through) const;
735d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    virtual bool IsAccumulatorValue() const { return true; }
7364a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  };
7374a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
7384a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  class StackValueContext : public ExpressionContext {
7394a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org   public:
7404a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    explicit StackValueContext(FullCodeGenerator* codegen)
741c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        : ExpressionContext(codegen) { }
7424a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
7434a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(bool flag) const;
7444a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Register reg) const;
7454a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Label* materialize_true, Label* materialize_false) const;
746486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    virtual void Plug(Variable* var) const;
7474a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Handle<Object> lit) const;
7484a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Heap::RootListIndex) const;
7494a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void PlugTOS() const;
7504a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void DropAndPlug(int count, Register reg) const;
7514a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void PrepareTest(Label* materialize_true,
7524a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label* materialize_false,
7534a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** if_true,
7544a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** if_false,
7554a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** fall_through) const;
756d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    virtual bool IsStackValue() const { return true; }
7574a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  };
7584a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
7594a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  class TestContext : public ExpressionContext {
7604a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org   public:
7616d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    TestContext(FullCodeGenerator* codegen,
7626d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org                Expression* condition,
7636d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org                Label* true_label,
7646d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org                Label* false_label,
7656d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org                Label* fall_through)
7664a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        : ExpressionContext(codegen),
7676d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org          condition_(condition),
7684a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          true_label_(true_label),
7694a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          false_label_(false_label),
770c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          fall_through_(fall_through) { }
7714a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
772b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org    static const TestContext* cast(const ExpressionContext* context) {
773e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(context->IsTest());
774b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org      return reinterpret_cast<const TestContext*>(context);
775b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org    }
776b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org
7776d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    Expression* condition() const { return condition_; }
778b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org    Label* true_label() const { return true_label_; }
779b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org    Label* false_label() const { return false_label_; }
780b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org    Label* fall_through() const { return fall_through_; }
781b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org
7824a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(bool flag) const;
7834a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Register reg) const;
7844a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Label* materialize_true, Label* materialize_false) const;
785486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    virtual void Plug(Variable* var) const;
7864a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Handle<Object> lit) const;
7874a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Heap::RootListIndex) const;
7884a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void PlugTOS() const;
7894a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void DropAndPlug(int count, Register reg) const;
7904a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void PrepareTest(Label* materialize_true,
7914a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label* materialize_false,
7924a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** if_true,
7934a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** if_false,
7944a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** fall_through) const;
7954a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual bool IsTest() const { return true; }
7964a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
7974a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org   private:
7986d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    Expression* condition_;
7994a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    Label* true_label_;
8004a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    Label* false_label_;
8014a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    Label* fall_through_;
8024a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  };
8034a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
8044a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  class EffectContext : public ExpressionContext {
8054a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org   public:
8064a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    explicit EffectContext(FullCodeGenerator* codegen)
807c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        : ExpressionContext(codegen) { }
8084a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
8094a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(bool flag) const;
8104a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Register reg) const;
8114a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Label* materialize_true, Label* materialize_false) const;
812486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    virtual void Plug(Variable* var) const;
8134a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Handle<Object> lit) const;
8144a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void Plug(Heap::RootListIndex) const;
8154a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void PlugTOS() const;
8164a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void DropAndPlug(int count, Register reg) const;
8174a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual void PrepareTest(Label* materialize_true,
8184a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label* materialize_false,
8194a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** if_true,
8204a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** if_false,
8214a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             Label** fall_through) const;
8224a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    virtual bool IsEffect() const { return true; }
8234a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  };
8244a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
825a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  MacroAssembler* masm_;
826a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  CompilationInfo* info_;
8274f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  Scope* scope_;
828a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label return_label_;
829a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  NestedStatement* nesting_stack_;
830a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  int loop_depth_;
831ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  ZoneList<Handle<Object> >* globals_;
8328e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  Handle<FixedArray> modules_;
8338e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  int module_index_;
8344a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  const ExpressionContext* context_;
835a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  ZoneList<BailoutEntry> bailout_entries_;
836e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ZoneList<BackEdgeEntry> back_edges_;
837f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  int ic_total_count_;
83804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  Handle<FixedArray> handler_table_;
83941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  Handle<Cell> profiling_counter_;
840000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org  bool generate_debug_code_;
841b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
842b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  friend class NestedStatement;
843b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
844a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
845b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator);
846b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org};
847b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
848b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
8492c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org// A map from property names to getter/setter pairs allocated in the zone.
8502c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.orgclass AccessorTable: public TemplateHashMap<Literal,
8512c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org                                            ObjectLiteral::Accessors,
852400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org                                            ZoneAllocationPolicy> {
8532c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org public:
8542c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org  explicit AccessorTable(Zone* zone) :
855400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org      TemplateHashMap<Literal, ObjectLiteral::Accessors,
8567028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                      ZoneAllocationPolicy>(Literal::Match,
8577028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                                            ZoneAllocationPolicy(zone)),
8582c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org      zone_(zone) { }
8592c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org
8602c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org  Iterator lookup(Literal* literal) {
8617028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    Iterator it = find(literal, true, ZoneAllocationPolicy(zone_));
8622c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org    if (it->second == NULL) it->second = new(zone_) ObjectLiteral::Accessors();
8632c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org    return it;
8642c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org  }
8652c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org
8662c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org private:
8672c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org  Zone* zone_;
8682c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org};
8692c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org
8702c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org
871528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgclass BackEdgeTable {
872528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org public:
873528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  BackEdgeTable(Code* code, DisallowHeapAllocation* required) {
874e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(code->kind() == Code::FUNCTION);
875528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    instruction_start_ = code->instruction_start();
876528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    Address table_address = instruction_start_ + code->back_edge_table_offset();
877528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    length_ = Memory::uint32_at(table_address);
878528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    start_ = table_address + kTableLengthSize;
879528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  }
880528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
881528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  uint32_t length() { return length_; }
882528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
883528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  BailoutId ast_id(uint32_t index) {
884528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    return BailoutId(static_cast<int>(
885528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org        Memory::uint32_at(entry_at(index) + kAstIdOffset)));
886528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  }
887528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
888528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  uint32_t loop_depth(uint32_t index) {
889528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    return Memory::uint32_at(entry_at(index) + kLoopDepthOffset);
890528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  }
891528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
892528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  uint32_t pc_offset(uint32_t index) {
893528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    return Memory::uint32_at(entry_at(index) + kPcOffsetOffset);
894528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  }
895528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
896528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Address pc(uint32_t index) {
897528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    return instruction_start_ + pc_offset(index);
898528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  }
899528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
900528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  enum BackEdgeState {
901528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    INTERRUPT,
9028e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org    ON_STACK_REPLACEMENT,
9038e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org    OSR_AFTER_STACK_CHECK
904528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  };
905528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
90608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  // Increase allowed loop nesting level by one and patch those matching loops.
90708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  static void Patch(Isolate* isolate, Code* unoptimized_code);
908528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
9098e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  // Patch the back edge to the target state, provided the correct callee.
910528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  static void PatchAt(Code* unoptimized_code,
9118e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org                      Address pc,
9128e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org                      BackEdgeState target_state,
913528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                      Code* replacement_code);
914528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
9158e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  // Change all patched back edges back to normal interrupts.
916528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  static void Revert(Isolate* isolate,
917528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                     Code* unoptimized_code);
918528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
9198e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  // Change a back edge patched for on-stack replacement to perform a
9208e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  // stack check first.
9214954674151afa960af66efb4831df06bde727333yangguo@chromium.org  static void AddStackCheck(Handle<Code> code, uint32_t pc_offset);
922528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
9234954674151afa960af66efb4831df06bde727333yangguo@chromium.org  // Revert the patch by AddStackCheck.
9244954674151afa960af66efb4831df06bde727333yangguo@chromium.org  static void RemoveStackCheck(Handle<Code> code, uint32_t pc_offset);
9258e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
9268e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  // Return the current patch state of the back edge.
927528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  static BackEdgeState GetBackEdgeState(Isolate* isolate,
928528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                        Code* unoptimized_code,
929528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                        Address pc_after);
930528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
9318e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org#ifdef DEBUG
932528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Verify that all back edges of a certain loop depth are patched.
93308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  static bool Verify(Isolate* isolate, Code* unoptimized_code);
934528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org#endif  // DEBUG
935528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
936528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org private:
937528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Address entry_at(uint32_t index) {
938e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(index < length_);
939528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    return start_ + index * kEntrySize;
940528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  }
941528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
942528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  static const int kTableLengthSize = kIntSize;
943528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  static const int kAstIdOffset = 0 * kIntSize;
944528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  static const int kPcOffsetOffset = 1 * kIntSize;
945528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  static const int kLoopDepthOffset = 2 * kIntSize;
946528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  static const int kEntrySize = 3 * kIntSize;
947528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
948528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Address start_;
949528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Address instruction_start_;
950528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  uint32_t length_;
951528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org};
952528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
953528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
954b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org} }  // namespace v8::internal
955b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
956b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org#endif  // V8_FULL_CODEGEN_H_
957