13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Redistribution and use in source and binary forms, with or without
3d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// modification, are permitted provided that the following conditions are
4d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// met:
5d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//
6d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//     * Redistributions of source code must retain the above copyright
7d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       notice, this list of conditions and the following disclaimer.
8d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//     * Redistributions in binary form must reproduce the above
9d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       copyright notice, this list of conditions and the following
10d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       disclaimer in the documentation and/or other materials provided
11d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       with the distribution.
12d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//     * Neither the name of Google Inc. nor the names of its
13d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       contributors may be used to endorse or promote products derived
14d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       from this software without specific prior written permission.
15d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//
16d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
28d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#ifndef V8_FULL_CODEGEN_H_
29d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#define V8_FULL_CODEGEN_H_
30d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
31d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "v8.h"
32d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
33257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "allocation.h"
34d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "ast.h"
35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "code-stubs.h"
36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "codegen.h"
37f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#include "compiler.h"
38d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
39d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkenamespace v8 {
40d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkenamespace internal {
41d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
42b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Forward declarations.
43b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass JumpPatchSite;
44b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// AST node visitor which can tell whether a given statement will be breakable
467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// when the code is compiled by the full compiler in the debugger. This means
477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// that there will be an IC (load/store/call) in the code generated for the
487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// debugger to piggybag on.
497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochclass BreakableStatementChecker: public AstVisitor {
507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch public:
517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  BreakableStatementChecker() : is_breakable_(false) {}
527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void Check(Statement* stmt);
547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void Check(Expression* stmt);
557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  bool is_breakable() { return is_breakable_; }
577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch private:
597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // AST node visit functions.
607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  AST_NODE_LIST(DECLARE_VISIT)
627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch#undef DECLARE_VISIT
637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  bool is_breakable_;
657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  DISALLOW_COPY_AND_ASSIGN(BreakableStatementChecker);
677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch};
687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
70d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// -----------------------------------------------------------------------------
71d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Full code generator.
72d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
73d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass FullCodeGenerator: public AstVisitor {
74d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public:
75b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  enum State {
76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    NO_REGISTERS,
77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TOS_REG
78b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  };
79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FullCodeGenerator(MacroAssembler* masm, CompilationInfo* info)
81d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      : masm_(masm),
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        info_(info),
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        scope_(info->scope()),
84d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        nesting_stack_(NULL),
85d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        loop_depth_(0),
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        global_count_(0),
87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        context_(NULL),
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bailout_entries_(info->HasDeoptimizationSupport()
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         ? info->function()->ast_node_count() : 0),
905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        stack_checks_(2),  // There's always at least one.
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        type_feedback_cells_(info->HasDeoptimizationSupport()
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             ? info->function()->ast_node_count() : 0),
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ic_total_count_(0),
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        has_self_optimization_header_(false) { }
95d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
96f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  static bool MakeCode(CompilationInfo* info);
97d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns the platform-specific size in bytes of the self-optimization
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // header.
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static int self_optimization_header_size();
101592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Encode state and pc-offset as a BitField<type, start, size>.
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Only use 30 bits because we encode the result as a smi.
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class StateField : public BitField<State, 0, 1> { };
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  class PcField    : public BitField<unsigned, 1, 30-1> { };
106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const char* State2String(State state) {
108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    switch (state) {
109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case NO_REGISTERS: return "NO_REGISTERS";
110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case TOS_REG: return "TOS_REG";
111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    UNREACHABLE();
113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return NULL;
114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
115d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
116d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private:
117d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  class Breakable;
118d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  class Iteration;
11969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  class TestContext;
121d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
122d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  class NestedStatement BASE_EMBEDDED {
123d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke   public:
124d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    explicit NestedStatement(FullCodeGenerator* codegen) : codegen_(codegen) {
125d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      // Link into codegen's nesting stack.
126d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      previous_ = codegen->nesting_stack_;
127d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      codegen->nesting_stack_ = this;
128d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
129d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    virtual ~NestedStatement() {
130d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      // Unlink from codegen's nesting stack.
131d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      ASSERT_EQ(this, codegen_->nesting_stack_);
132d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      codegen_->nesting_stack_ = previous_;
133d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
134d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
135d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    virtual Breakable* AsBreakable() { return NULL; }
136d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    virtual Iteration* AsIteration() { return NULL; }
137d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
138d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    virtual bool IsContinueTarget(Statement* target) { return false; }
139d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    virtual bool IsBreakTarget(Statement* target) { return false; }
140d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
14169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Notify the statement that we are exiting it via break, continue, or
14269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // return and give it a chance to generate cleanup code.  Return the
14369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // next outer statement in the nesting stack.  We accumulate in
14469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // *stack_depth the amount to drop the stack and in *context_length the
14569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // number of context chain links to unwind as we traverse the nesting
14669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // stack from an exit to its target.
14769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
14869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      return previous_;
149d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
1503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   protected:
152d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    MacroAssembler* masm() { return codegen_->masm(); }
1533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
154d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    FullCodeGenerator* codegen_;
155d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    NestedStatement* previous_;
1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
158d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    DISALLOW_COPY_AND_ASSIGN(NestedStatement);
159d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  };
160d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
16169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // A breakable statement such as a block.
162d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  class Breakable : public NestedStatement {
163d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke   public:
16469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Breakable(FullCodeGenerator* codegen, BreakableStatement* statement)
16569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        : NestedStatement(codegen), statement_(statement) {
16669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
167d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    virtual ~Breakable() {}
16869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
169d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    virtual Breakable* AsBreakable() { return this; }
17069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    virtual bool IsBreakTarget(Statement* target) {
17169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      return statement() == target;
172d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
17369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
17469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    BreakableStatement* statement() { return statement_; }
17569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Label* break_label() { return &break_label_; }
17669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
177d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke   private:
17869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    BreakableStatement* statement_;
17969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Label break_label_;
180d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  };
181d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
18269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // An iteration statement such as a while, for, or do loop.
183d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  class Iteration : public Breakable {
184d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke   public:
18569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Iteration(FullCodeGenerator* codegen, IterationStatement* statement)
18669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        : Breakable(codegen, statement) {
18769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
188d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    virtual ~Iteration() {}
18969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
190d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    virtual Iteration* AsIteration() { return this; }
19169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    virtual bool IsContinueTarget(Statement* target) {
19269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      return statement() == target;
193d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
19469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
19569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Label* continue_label() { return &continue_label_; }
19669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
197d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke   private:
19869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Label continue_label_;
199d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  };
200d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
201589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // A nested block statement.
202589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  class NestedBlock : public Breakable {
203589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch   public:
204589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    NestedBlock(FullCodeGenerator* codegen, Block* block)
205589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        : Breakable(codegen, block) {
206589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
207589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    virtual ~NestedBlock() {}
208589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
209589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (statement()->AsBlock()->block_scope() != NULL) {
211589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        ++(*context_length);
212589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
213589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return previous_;
214589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    };
215589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  };
216589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
21769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // The try block of a try/catch statement.
218d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  class TryCatch : public NestedStatement {
219d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke   public:
22069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    explicit TryCatch(FullCodeGenerator* codegen) : NestedStatement(codegen) {
22169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
222d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    virtual ~TryCatch() {}
22369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
22469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    virtual NestedStatement* Exit(int* stack_depth, int* context_length);
225d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  };
226d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
22769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // The try block of a try/finally statement.
228d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  class TryFinally : public NestedStatement {
229d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke   public:
23069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
23169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        : NestedStatement(codegen), finally_entry_(finally_entry) {
23269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
233d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    virtual ~TryFinally() {}
23469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
23569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    virtual NestedStatement* Exit(int* stack_depth, int* context_length);
23669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
237d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke   private:
238d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Label* finally_entry_;
239d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  };
240d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
24169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // The finally block of a try/finally statement.
242d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  class Finally : public NestedStatement {
243d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke   public:
24469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    static const int kElementCount = 2;
24569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
246d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) { }
247d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    virtual ~Finally() {}
24869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
24969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
25069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      *stack_depth += kElementCount;
25169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      return previous_;
252d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
253d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  };
254d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
25569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // The body of a for/in loop.
256d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  class ForIn : public Iteration {
257d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke   public:
25869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    static const int kElementCount = 5;
25969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
26069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    ForIn(FullCodeGenerator* codegen, ForInStatement* statement)
26169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        : Iteration(codegen, statement) {
26269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
263d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    virtual ~ForIn() {}
26469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
26569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
26669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      *stack_depth += kElementCount;
26769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      return previous_;
26869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
26969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  };
27069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
27169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
27269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // The body of a with or catch.
27369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  class WithOrCatch : public NestedStatement {
27469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch   public:
27569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    explicit WithOrCatch(FullCodeGenerator* codegen)
27669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        : NestedStatement(codegen) {
27769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
27869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    virtual ~WithOrCatch() {}
27969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
28069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
28169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      ++(*context_length);
28269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      return previous_;
283d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
284d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  };
285d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Type of a member function that generates inline code for a native function.
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef void (FullCodeGenerator::*InlineFunctionGenerator)(CallRuntime* expr);
2880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  static const InlineFunctionGenerator kInlineFunctionGenerators[];
2900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
291db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // A platform-specific utility to overwrite the accumulator register
292db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // with a GC-safe value.
293db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  void ClearAccumulator();
294db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
29580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Determine whether or not to inline the smi case for the given
29680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // operation.
29780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  bool ShouldInlineSmiCase(Token::Value op);
29880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
299d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Helper function to convert a pure value into a test context.  The value
300d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // is expected on the stack or the accumulator, depending on the platform.
301d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // See the platform-specific implementation for details.
3023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void DoTest(Expression* condition,
3033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch              Label* if_true,
3043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch              Label* if_false,
3053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch              Label* fall_through);
3063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void DoTest(const TestContext* context);
30780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
30880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Helper function to split control flow and avoid a branch to the
30980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // fall-through label if it is set up.
310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef V8_TARGET_ARCH_MIPS
31180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void Split(Condition cc,
312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch             Register lhs,
313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch             const Operand&  rhs,
31480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen             Label* if_true,
31580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen             Label* if_false,
31680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen             Label* fall_through);
317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#else  // All non-mips arch.
318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Split(Condition cc,
319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch             Label* if_true,
320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch             Label* if_false,
321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch             Label* fall_through);
322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif  // V8_TARGET_ARCH_MIPS
323d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
324589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Load the value of a known (PARAMETER, LOCAL, or CONTEXT) variable into
325589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // a register.  Emits a context chain walk if if necessary (so does
326589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // SetVar) so avoid calling both on the same variable.
327589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void GetVar(Register destination, Variable* var);
328589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
329589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Assign to a known (PARAMETER, LOCAL, or CONTEXT) variable.  If it's in
330589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // the context, the write barrier will be emitted and source, scratch0,
331589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // scratch1 will be clobbered.  Emits a context chain walk if if necessary
332589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // (so does GetVar) so avoid calling both on the same variable.
333589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void SetVar(Variable* var,
334589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch              Register source,
335589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch              Register scratch0,
336589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch              Register scratch1);
337589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
338589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // An operand used to read/write a stack-allocated (PARAMETER or LOCAL)
339589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // variable.  Writing does not need the write barrier.
340589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand StackOperand(Variable* var);
341589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
342589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // An operand used to read/write a known (PARAMETER, LOCAL, or CONTEXT)
343589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // variable.  May emit code to traverse the context chain, loading the
344589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // found context into the scratch register.  Writing to this operand will
345589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // need the write barrier if location is CONTEXT.
346589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand VarOperand(Variable* var, Register scratch);
347d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
348d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void VisitForEffect(Expression* expr) {
3490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EffectContext context(this);
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Visit(expr);
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrepareForBailout(expr, NO_REGISTERS);
3520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
3530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void VisitForAccumulatorValue(Expression* expr) {
3550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Visit(expr);
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrepareForBailout(expr, TOS_REG);
358d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
359d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void VisitForStackValue(Expression* expr) {
3610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    StackValueContext context(this);
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Visit(expr);
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrepareForBailout(expr, NO_REGISTERS);
364d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
365d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
36680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void VisitForControl(Expression* expr,
36780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                       Label* if_true,
36880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                       Label* if_false,
36980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                       Label* fall_through) {
3703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    TestContext context(this, expr, if_true, if_false, fall_through);
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Visit(expr);
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For test contexts, we prepare for bailout before branching, not at
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // the end of the entire expression.  This happens as part of visiting
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // the expression.
375d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
376d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void VisitInDuplicateContext(Expression* expr);
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
379d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void VisitDeclarations(ZoneList<Declaration*>* declarations);
380d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void DeclareGlobals(Handle<FixedArray> pairs);
381589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int DeclareGlobalsFlags();
382d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
38380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Try to perform a comparison as a fast inlined literal compare if
38480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the operands allow it.  Returns true if the compare operations
38580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // has been matched and all code generated; false otherwise.
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool TryLiteralCompare(CompareOperation* compare);
38780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Platform-specific code for comparing the type of a value with
3893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // a given literal string.
3903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void EmitLiteralCompareTypeof(Expression* expr,
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Expression* sub_expr,
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Handle<String> check);
3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Platform-specific code for equality comparison with a nil-like value.
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EmitLiteralCompareNil(CompareOperation* expr,
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             Expression* sub_expr,
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             NilValue nil);
3983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Bailout support.
4003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void PrepareForBailout(Expression* node, State state);
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void PrepareForBailoutForId(unsigned id, State state);
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Cache cell support.  This associates AST ids with global property cells
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // that will be cleared during GC and collected by the type-feedback oracle.
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RecordTypeFeedbackCell(unsigned id, Handle<JSGlobalPropertyCell> cell);
4065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Record a call's return site offset, used to rebuild the frame if the
408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // called function was inlined at the site.
409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void RecordJSReturnSite(Call* call);
410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Prepare for bailout before a test (or compare) and branch.  If
412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // should_normalize, then the following comparison will not handle the
413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // canonical JS true value so we will insert a (dead) test against true at
414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the actual bailout target from the optimized code. If not
415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // should_normalize, the true and false labels are ignored.
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void PrepareForBailoutBeforeSplit(Expression* expr,
417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    bool should_normalize,
418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    Label* if_true,
419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    Label* if_false);
420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Platform-specific code for a variable, constant, or function
422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // declaration.  Functions have an initial value.
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Increments global_count_ for unallocated variables.
424589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void EmitDeclaration(VariableProxy* proxy,
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       VariableMode mode,
4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       FunctionLiteral* function);
427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Platform-specific code for checking the stack limit at the back edge of
429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // a loop.
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This is meant to be called at loop back edges, |back_edge_target| is
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the jump target of the back edge and is used to approximate the amount
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // of code inside the loop.
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EmitStackCheck(IterationStatement* stmt, Label* back_edge_target);
434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Record the OSR AST id corresponding to a stack check in the code.
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RecordStackCheck(unsigned osr_ast_id);
436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Emit a table of stack check ids and pcs into the code stream.  Return
437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the offset of the start of the table.
438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned EmitStackCheckTable();
439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EmitProfilingCounterDecrement(int delta);
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EmitProfilingCounterReset();
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
443d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Platform-specific return sequence
4447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void EmitReturnSequence();
445d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
446d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Platform-specific code sequences for calls
447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitCallWithStub(Call* expr, CallFunctionFlags flags);
448d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void EmitCallWithIC(Call* expr, Handle<Object> name, RelocInfo::Mode mode);
449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitKeyedCallWithIC(Call* expr, Expression* key);
450d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
451f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Platform-specific code for inline runtime calls.
4520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  InlineFunctionGenerator FindInlineFunctionGenerator(Runtime::FunctionId id);
4530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  void EmitInlineRuntimeCall(CallRuntime* expr);
455791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
456791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block#define EMIT_INLINE_RUNTIME_CALL(name, x, y) \
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Emit##name(CallRuntime* expr);
4580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
459791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
460791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block#undef EMIT_INLINE_RUNTIME_CALL
461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
462d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Platform-specific code for loading variables.
463589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void EmitLoadGlobalCheckExtensions(Variable* var,
464589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                     TypeofState typeof_state,
465589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                     Label* slow);
466589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand ContextSlotOperandCheckExtensions(Variable* var, Label* slow);
467589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void EmitDynamicLookupFastCase(Variable* var,
468589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                 TypeofState typeof_state,
469589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                 Label* slow,
470589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                 Label* done);
4713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void EmitVariableLoad(VariableProxy* proxy);
472d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EmitAccessor(Expression* expression);
4745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
475e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Expects the arguments and the function already pushed.
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EmitResolvePossiblyDirectEval(int arg_count);
477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Platform-specific support for allocating a new closure based on
479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the given function info.
4808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  void EmitNewClosure(Handle<SharedFunctionInfo> info, bool pretenure);
481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
482d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Platform-specific support for compiling assignments.
483d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
484d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Load a value from a named property.
485d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // The receiver is left on the stack by the IC.
486d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void EmitNamedPropertyLoad(Property* expr);
487d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
488d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Load a value from a keyed property.
489d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // The receiver and the key is left on the stack by the IC.
490d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void EmitKeyedPropertyLoad(Property* expr);
491d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
492d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Apply the compound assignment operator. Expects the left operand on top
493d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // of the stack and the right one in the accumulator.
494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitBinaryOp(BinaryOperation* expr,
495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    Token::Value op,
49680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    OverwriteMode mode);
49780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
49880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Helper functions for generating inlined smi code for certain
49980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // binary operations.
500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitInlineSmiBinaryOp(BinaryOperation* expr,
50180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                             Token::Value op,
50280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                             OverwriteMode mode,
50380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                             Expression* left,
504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                             Expression* right);
505d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Assign to the given expression as if via '='. The right-hand-side value
507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // is expected in the accumulator.
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EmitAssignment(Expression* expr);
509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
510d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Complete a variable assignment.  The right-hand-side value is expected
511d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // in the accumulator.
512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  void EmitVariableAssignment(Variable* var,
5130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                              Token::Value op);
514d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
515d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Complete a named property assignment.  The receiver is expected on top
516d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // of the stack and the right-hand-side value in the accumulator.
517d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void EmitNamedPropertyAssignment(Assignment* expr);
518d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
519d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Complete a keyed property assignment.  The receiver and key are
520d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // expected on top of the stack and the right-hand-side value in the
521d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // accumulator.
522d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void EmitKeyedPropertyAssignment(Assignment* expr);
523d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CallIC(Handle<Code> code,
5253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              unsigned ast_id = kNoASTId);
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
528d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void SetFunctionPosition(FunctionLiteral* fun);
529d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void SetReturnPosition(FunctionLiteral* fun);
530d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void SetStatementPosition(Statement* stmt);
5317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void SetExpressionPosition(Expression* expr, int pos);
532d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void SetStatementPosition(int pos);
533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void SetSourcePosition(int pos);
534d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
535d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Non-local control flow support.
536d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void EnterFinallyBlock();
537d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void ExitFinallyBlock();
538d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
539d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Loop nesting counter.
540d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int loop_depth() { return loop_depth_; }
541d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void increment_loop_depth() { loop_depth_++; }
542d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void decrement_loop_depth() {
543d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT(loop_depth_ > 0);
544d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    loop_depth_--;
545d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
546d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
547d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  MacroAssembler* masm() { return masm_; }
5483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  class ExpressionContext;
5500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const ExpressionContext* context() { return context_; }
5510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void set_new_context(const ExpressionContext* context) { context_ = context; }
5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Handle<Script> script() { return info_->script(); }
5543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  bool is_eval() { return info_->is_eval(); }
555589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  bool is_native() { return info_->is_native(); }
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool is_classic_mode() {
5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return language_mode() == CLASSIC_MODE;
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LanguageMode language_mode() {
5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return function()->language_mode();
5611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
5623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  FunctionLiteral* function() { return info_->function(); }
5633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Scope* scope() { return scope_; }
5643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
565d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static Register result_register();
566d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static Register context_register();
567d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
568d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Set fields in the stack frame. Offsets are the frame pointer relative
569d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // offsets defined in, e.g., StandardFrameConstants.
570d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void StoreToFrameField(int frame_offset, Register value);
571d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
572d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Load a value from the current context. Indices are defined as an enum
573d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // in v8::internal::Context.
574d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void LoadContextField(Register dst, int context_index);
575d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
5763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Push the function argument for the runtime functions PushWithContext
5773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // and PushCatchContext.
5783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void PushFunctionArgumentForContextAllocation();
5793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
580d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // AST node visit functions.
581d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
582d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  AST_NODE_LIST(DECLARE_VISIT)
583d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#undef DECLARE_VISIT
584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitUnaryOperation(UnaryOperation* expr, const char* comment);
586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void VisitComma(BinaryOperation* expr);
5883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void VisitLogicalExpression(BinaryOperation* expr);
5893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void VisitArithmeticExpression(BinaryOperation* expr);
590d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
5910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void VisitForTypeofValue(Expression* expr);
59280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Generate();
5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void PopulateDeoptimizationData(Handle<Code> code);
5953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void PopulateTypeFeedbackInfo(Handle<Code> code);
5963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void PopulateTypeFeedbackCells(Handle<Code> code);
5973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> handler_table() { return handler_table_; }
5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  struct BailoutEntry {
601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    unsigned id;
602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    unsigned pc_and_state;
603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  };
6044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
6053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  struct TypeFeedbackCellEntry {
6063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    unsigned ast_id;
6073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell;
6083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
6093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
610d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  class ExpressionContext BASE_EMBEDDED {
6120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen   public:
6130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    explicit ExpressionContext(FullCodeGenerator* codegen)
6140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        : masm_(codegen->masm()), old_(codegen->context()), codegen_(codegen) {
6150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      codegen->set_new_context(this);
6160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
6170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual ~ExpressionContext() {
6190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      codegen_->set_new_context(old_);
6200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
6210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
62244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Isolate* isolate() const { return codegen_->isolate(); }
62344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Convert constant control flow (true or false) to the result expected for
6250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // this expression context.
6260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(bool flag) const = 0;
6270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
628589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Emit code to convert a pure value (in a register, known variable
629589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // location, as a literal, or on top of the stack) into the result
630589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // expected according to this expression context.
6310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Register reg) const = 0;
632589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    virtual void Plug(Variable* var) const = 0;
6330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Handle<Object> lit) const = 0;
6340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Heap::RootListIndex index) const = 0;
6350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void PlugTOS() const = 0;
6360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Emit code to convert pure control flow to a pair of unbound labels into
6380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // the result expected according to this expression context.  The
639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // implementation will bind both labels unless it's a TestContext, which
640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // won't bind them at this point.
6410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Label* materialize_true,
6420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                      Label* materialize_false) const = 0;
6430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Emit code to discard count elements from the top of stack, then convert
6450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // a pure value into the result expected according to this expression
6460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // context.
6470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void DropAndPlug(int count, Register reg) const = 0;
6480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Set up branch labels for a test expression.  The three Label** parameters
6500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // are output parameters.
6510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void PrepareTest(Label* materialize_true,
6520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label* materialize_false,
6530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** if_true,
6540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** if_false,
6550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** fall_through) const = 0;
6560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Returns true if we are evaluating only for side effects (i.e. if the
6583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // result will be discarded).
6590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual bool IsEffect() const { return false; }
6600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Returns true if we are evaluating for the value (in accu/on stack).
6623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    virtual bool IsAccumulatorValue() const { return false; }
6633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    virtual bool IsStackValue() const { return false; }
6643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Returns true if we are branching on the value rather than materializing
666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // it.  Only used for asserts.
6670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual bool IsTest() const { return false; }
6680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen   protected:
6700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    FullCodeGenerator* codegen() const { return codegen_; }
6710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    MacroAssembler* masm() const { return masm_; }
6720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    MacroAssembler* masm_;
6730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen   private:
6750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    const ExpressionContext* old_;
6760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    FullCodeGenerator* codegen_;
6770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  };
6780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  class AccumulatorValueContext : public ExpressionContext {
6800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen   public:
6810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    explicit AccumulatorValueContext(FullCodeGenerator* codegen)
6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : ExpressionContext(codegen) { }
6830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(bool flag) const;
6850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Register reg) const;
6860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Label* materialize_true, Label* materialize_false) const;
687589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    virtual void Plug(Variable* var) const;
6880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Handle<Object> lit) const;
6890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Heap::RootListIndex) const;
6900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void PlugTOS() const;
6910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void DropAndPlug(int count, Register reg) const;
6920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void PrepareTest(Label* materialize_true,
6930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label* materialize_false,
6940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** if_true,
6950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** if_false,
6960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** fall_through) const;
6973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    virtual bool IsAccumulatorValue() const { return true; }
6980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  };
6990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
7000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  class StackValueContext : public ExpressionContext {
7010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen   public:
7020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    explicit StackValueContext(FullCodeGenerator* codegen)
7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : ExpressionContext(codegen) { }
7040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
7050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(bool flag) const;
7060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Register reg) const;
7070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Label* materialize_true, Label* materialize_false) const;
708589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    virtual void Plug(Variable* var) const;
7090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Handle<Object> lit) const;
7100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Heap::RootListIndex) const;
7110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void PlugTOS() const;
7120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void DropAndPlug(int count, Register reg) const;
7130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void PrepareTest(Label* materialize_true,
7140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label* materialize_false,
7150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** if_true,
7160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** if_false,
7170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** fall_through) const;
7183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    virtual bool IsStackValue() const { return true; }
7190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  };
7200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
7210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  class TestContext : public ExpressionContext {
7220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen   public:
7233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    TestContext(FullCodeGenerator* codegen,
7243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                Expression* condition,
7253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                Label* true_label,
7263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                Label* false_label,
7273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                Label* fall_through)
7280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        : ExpressionContext(codegen),
7293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          condition_(condition),
7300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          true_label_(true_label),
7310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          false_label_(false_label),
7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          fall_through_(fall_through) { }
7330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
734f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    static const TestContext* cast(const ExpressionContext* context) {
735f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      ASSERT(context->IsTest());
736f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      return reinterpret_cast<const TestContext*>(context);
737f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    }
738f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
7393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Expression* condition() const { return condition_; }
740f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    Label* true_label() const { return true_label_; }
741f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    Label* false_label() const { return false_label_; }
742f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    Label* fall_through() const { return fall_through_; }
743f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
7440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(bool flag) const;
7450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Register reg) const;
7460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Label* materialize_true, Label* materialize_false) const;
747589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    virtual void Plug(Variable* var) const;
7480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Handle<Object> lit) const;
7490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Heap::RootListIndex) const;
7500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void PlugTOS() const;
7510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void DropAndPlug(int count, Register reg) const;
7520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void PrepareTest(Label* materialize_true,
7530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label* materialize_false,
7540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** if_true,
7550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** if_false,
7560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** fall_through) const;
7570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual bool IsTest() const { return true; }
7580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
7590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen   private:
7603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Expression* condition_;
7610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* true_label_;
7620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* false_label_;
7630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* fall_through_;
7640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  };
7650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
7660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  class EffectContext : public ExpressionContext {
7670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen   public:
7680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    explicit EffectContext(FullCodeGenerator* codegen)
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : ExpressionContext(codegen) { }
7700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
7710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(bool flag) const;
7720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Register reg) const;
7730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Label* materialize_true, Label* materialize_false) const;
774589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    virtual void Plug(Variable* var) const;
7750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Handle<Object> lit) const;
7760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void Plug(Heap::RootListIndex) const;
7770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void PlugTOS() const;
7780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void DropAndPlug(int count, Register reg) const;
7790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual void PrepareTest(Label* materialize_true,
7800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label* materialize_false,
7810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** if_true,
7820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** if_false,
7830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             Label** fall_through) const;
7840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    virtual bool IsEffect() const { return true; }
7850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  };
7860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  MacroAssembler* masm_;
788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompilationInfo* info_;
7893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Scope* scope_;
790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label return_label_;
791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  NestedStatement* nesting_stack_;
792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int loop_depth_;
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int global_count_;
7940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const ExpressionContext* context_;
795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<BailoutEntry> bailout_entries_;
796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<BailoutEntry> stack_checks_;
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<TypeFeedbackCellEntry> type_feedback_cells_;
7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int ic_total_count_;
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_self_optimization_header_;
8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> handler_table_;
8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSGlobalPropertyCell> profiling_counter_;
802d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
803d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  friend class NestedStatement;
804d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
805d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator);
806d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke};
807d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
808d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// A map from property names to getter/setter pairs allocated in the zone.
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass AccessorTable: public TemplateHashMap<Literal,
8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            ObjectLiteral::Accessors,
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            ZoneListAllocationPolicy> {
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit AccessorTable(Zone* zone) :
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      TemplateHashMap<Literal,
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      ObjectLiteral::Accessors,
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      ZoneListAllocationPolicy>(Literal::Match),
8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      zone_(zone) { }
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Iterator lookup(Literal* literal) {
8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Iterator it = find(literal, true);
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (it->second == NULL) it->second = new(zone_) ObjectLiteral::Accessors();
8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return it;
8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Zone* zone_;
8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
831d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} }  // namespace v8::internal
832d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
833d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#endif  // V8_FULL_CODEGEN_H_
834