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