hydrogen.cc revision 5d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0b
1c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Redistribution and use in source and binary forms, with or without
3b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// modification, are permitted provided that the following conditions are
4b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// met:
5b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//
6b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Redistributions of source code must retain the above copyright
7b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       notice, this list of conditions and the following disclaimer.
8b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Redistributions in binary form must reproduce the above
9b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       copyright notice, this list of conditions and the following
10b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       disclaimer in the documentation and/or other materials provided
11b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       with the distribution.
12b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Neither the name of Google Inc. nor the names of its
13b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       contributors may be used to endorse or promote products derived
14b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       from this software without specific prior written permission.
15b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//
16b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "v8.h"
29b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "hydrogen.h"
30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "codegen.h"
32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h"
33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "hashmap.h"
34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "lithium-allocator.h"
35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "parser.h"
363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "scopeinfo.h"
37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "scopes.h"
381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "stub-cache.h"
39b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#if V8_TARGET_ARCH_IA32
41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "ia32/lithium-codegen-ia32.h"
42b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#elif V8_TARGET_ARCH_X64
43b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "x64/lithium-codegen-x64.h"
44b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#elif V8_TARGET_ARCH_ARM
45b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "arm/lithium-codegen-arm.h"
4644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#elif V8_TARGET_ARCH_MIPS
4744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "mips/lithium-codegen-mips.h"
48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#else
49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#error Unsupported target architecture.
50b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
51b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
52b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 {
53b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal {
54b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
55b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock::HBasicBlock(HGraph* graph)
56b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : block_id_(graph->GetNextBlockID()),
57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      graph_(graph),
58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phis_(4),
59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      first_(NULL),
60b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      last_(NULL),
61b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      end_(NULL),
62b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      loop_information_(NULL),
63b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      predecessors_(2),
64b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      dominator_(NULL),
65b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      dominated_blocks_(4),
66b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      last_environment_(NULL),
67b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      argument_count_(-1),
68b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      first_instruction_index_(-1),
69b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      last_instruction_index_(-1),
70b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      deleted_phis_(4),
711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      parent_loop_header_(NULL),
723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      is_inline_return_target_(false),
735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      is_deoptimizing_(false),
745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      dominates_loop_successors_(false) { }
75b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AttachLoopInformation() {
78b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsLoopHeader());
798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  loop_information_ = new(zone()) HLoopInformation(this);
80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::DetachLoopInformation() {
84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(IsLoopHeader());
85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  loop_information_ = NULL;
86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddPhi(HPhi* phi) {
90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsStartBlock());
91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phis_.Add(phi);
92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phi->SetBlock(this);
93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::RemovePhi(HPhi* phi) {
97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(phi->block() == this);
98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(phis_.Contains(phi));
9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(phi->HasNoUses() || !phi->is_live());
1005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  phi->Kill();
101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phis_.RemoveElement(phi);
102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phi->SetBlock(NULL);
103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddInstruction(HInstruction* instr) {
107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsStartBlock() || !IsFinished());
108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!instr->IsLinked());
109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsFinished());
110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (first_ == NULL) {
1118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HBlockEntry* entry = new(zone()) HBlockEntry();
112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    entry->InitializeAsFirst(this);
113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    first_ = last_ = entry;
114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  instr->InsertAfter(last_);
116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  last_ = instr;
117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHDeoptimize* HBasicBlock::CreateDeoptimize(
121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HDeoptimize::UseEnvironment has_uses) {
12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(HasEnvironment());
123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (has_uses == HDeoptimize::kNoUses) return new(zone()) HDeoptimize(0);
12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HEnvironment* environment = last_environment();
1268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HDeoptimize* instr = new(zone()) HDeoptimize(environment->length());
12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < environment->length(); i++) {
12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* val = environment->values()->at(i);
12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    instr->AddEnvironmentValue(val);
13044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
13144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return instr;
13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1363fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHSimulate* HBasicBlock::CreateSimulate(int ast_id) {
137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(HasEnvironment());
138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* environment = last_environment();
1393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(ast_id == AstNode::kNoNumber ||
1403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         environment->closure()->shared()->VerifyBailoutId(ast_id));
141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int push_count = environment->push_count();
143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int pop_count = environment->pop_count();
144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HSimulate* instr = new(zone()) HSimulate(ast_id, pop_count);
146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = push_count - 1; i >= 0; --i) {
147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->AddPushedValue(environment->ExpressionStackAt(i));
148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < environment->assigned_variables()->length(); ++i) {
150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int index = environment->assigned_variables()->at(i);
151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->AddAssignedValue(index, environment->Lookup(index));
152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  environment->ClearHistory();
154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Finish(HControlInstruction* end) {
159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsFinished());
160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(end);
161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  end_ = end;
1623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
1633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    it.Current()->RegisterPredecessor(this);
164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
168592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid HBasicBlock::Goto(HBasicBlock* block, bool drop_extra) {
16944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (block->IsInlineReturnTarget()) {
1708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HLeaveInlined);
171c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    last_environment_ = last_environment()->DiscardInlined(drop_extra);
17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddSimulate(AstNode::kNoNumber);
1748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HGoto* instr = new(zone()) HGoto(block);
175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Finish(instr);
176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
179592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid HBasicBlock::AddLeaveInlined(HValue* return_value,
180592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                  HBasicBlock* target,
181592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                  bool drop_extra) {
18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(target->IsInlineReturnTarget());
18344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(return_value != NULL);
1848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HLeaveInlined);
185c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  last_environment_ = last_environment()->DiscardInlined(drop_extra);
18644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  last_environment()->Push(return_value);
18744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  AddSimulate(AstNode::kNoNumber);
1888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HGoto* instr = new(zone()) HGoto(target);
18944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Finish(instr);
19044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
19144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!HasEnvironment());
195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(first() == NULL);
196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UpdateEnvironment(env);
197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HBasicBlock::SetJoinId(int ast_id) {
201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = predecessors_.length();
202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(length > 0);
203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; i++) {
204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* predecessor = predecessors_[i];
205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(predecessor->end()->IsGoto());
206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // We only need to verify the ID once.
208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(i != 0 ||
209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           predecessor->last_environment()->closure()->shared()
2103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               ->VerifyBailoutId(ast_id));
2113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    simulate->set_ast_id(ast_id);
212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HBasicBlock::Dominates(HBasicBlock* other) const {
217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* current = other->dominator();
218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (current != NULL) {
219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current == this) return true;
220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current = current->dominator();
221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return false;
223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
226589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochint HBasicBlock::LoopNestingDepth() const {
227589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  const HBasicBlock* current = this;
228589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int result  = (current->IsLoopHeader()) ? 1 : 0;
229589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  while (current->parent_loop_header() != NULL) {
230589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    current = current->parent_loop_header();
231589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    result++;
232589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
233589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return result;
234589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
235589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(IsLoopHeader());
239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetJoinId(stmt->EntryId());
241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (predecessors()->length() == 1) {
242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // This is a degenerated loop.
243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    DetachLoopInformation();
244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Only the first entry into the loop is from outside the loop. All other
248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // entries must be back edges.
249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 1; i < predecessors()->length(); ++i) {
250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    loop_information()->RegisterBackEdge(predecessors()->at(i));
251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (HasPredecessor()) {
257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Only loop header blocks can have a predecessor added after
258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // instructions have been added to the block (they have phis for all
259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // values in the environment, these phis may be eliminated later).
260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(IsLoopHeader() || first_ == NULL);
261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HEnvironment* incoming_env = pred->last_environment();
262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (IsLoopHeader()) {
2639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ASSERT(phis()->length() == incoming_env->length());
264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int i = 0; i < phis_.length(); ++i) {
265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phis_[i]->AddInput(incoming_env->values()->at(i));
266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      last_environment()->AddIncomingEdge(this, pred->last_environment());
269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (!HasEnvironment() && !IsFinished()) {
271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!IsLoopHeader());
272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetInitialEnvironment(pred->last_environment()->Copy());
273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  predecessors_.Add(pred);
276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!dominated_blocks_.Contains(block));
281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Keep the list of dominated blocks sorted such that if there is two
282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // succeeding block in this list, the predecessor is before the successor.
283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = 0;
284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (index < dominated_blocks_.length() &&
285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         dominated_blocks_[index]->block_id() < block->block_id()) {
286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ++index;
287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  dominated_blocks_.InsertAt(index, block);
289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (dominator_ == NULL) {
294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    dominator_ = other;
295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    other->AddDominatedBlock(this);
296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (other->dominator() != NULL) {
297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* first = dominator_;
298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* second = other;
299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (first != second) {
301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (first->block_id() > second->block_id()) {
302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        first = first->dominator();
303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        second = second->dominator();
305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(first != NULL && second != NULL);
307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (dominator_ != first) {
310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(dominator_->dominated_blocks_.Contains(this));
311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      dominator_->dominated_blocks_.RemoveElement(this);
312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      dominator_ = first;
313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      first->AddDominatedBlock(this);
314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HBasicBlock::AssignLoopSuccessorDominators() {
3205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // Mark blocks that dominate all subsequent reachable blocks inside their
3215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // loop. Exploit the fact that blocks are sorted in reverse post order. When
3225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // the loop is visited in increasing block id order, if the number of
3235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // non-loop-exiting successor edges at the dominator_candidate block doesn't
3245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // exceed the number of previously encountered predecessor edges, there is no
3255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // path from the loop header to any block with higher id that doesn't go
3265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // through the dominator_candidate block. In this case, the
3275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // dominator_candidate block is guaranteed to dominate all blocks reachable
3285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // from it with higher ids.
3295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HBasicBlock* last = loop_information()->GetLastBackEdge();
3305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int outstanding_successors = 1;  // one edge from the pre-header
3315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // Header always dominates everything.
3325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  MarkAsLoopSuccessorDominator();
3335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  for (int j = block_id(); j <= last->block_id(); ++j) {
3345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HBasicBlock* dominator_candidate = graph_->blocks()->at(j);
3355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    for (HPredecessorIterator it(dominator_candidate); !it.Done();
3365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch         it.Advance()) {
3375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HBasicBlock* predecessor = it.Current();
3385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      // Don't count back edges.
3395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (predecessor->block_id() < dominator_candidate->block_id()) {
3405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        outstanding_successors--;
3415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
3425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
3435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
3445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // If more successors than predecessors have been seen in the loop up to
3455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // now, it's not possible to guarantee that the current block dominates
3465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // all of the blocks with higher IDs. In this case, assume conservatively
3475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // that those paths through loop that don't go through the current block
3485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // contain all of the loop's dependencies. Also be careful to record
3495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // dominator information about the current loop that's being processed,
3505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // and not nested loops, which will be processed when
3515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // AssignLoopSuccessorDominators gets called on their header.
3525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ASSERT(outstanding_successors >= 0);
3535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header();
3545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (outstanding_successors == 0 &&
3555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) {
3565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      dominator_candidate->MarkAsLoopSuccessorDominator();
3575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
3585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HControlInstruction* end = dominator_candidate->end();
3595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
3605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HBasicBlock* successor = it.Current();
3615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      // Only count successors that remain inside the loop and don't loop back
3625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      // to a loop header.
3635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (successor->block_id() > dominator_candidate->block_id() &&
3645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          successor->block_id() <= last->block_id()) {
3655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        // Backwards edges must land on loop headers.
3665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ASSERT(successor->block_id() > dominator_candidate->block_id() ||
3675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch               successor->IsLoopHeader());
3685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        outstanding_successors++;
3695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
3705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
3715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
3725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
3735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
3745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const {
376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < predecessors_.length(); ++i) {
377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (predecessors_[i] == predecessor) return i;
378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UNREACHABLE();
380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return -1;
381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Verify() {
386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check that every block is finished.
387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(IsFinished());
388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(block_id() >= 0);
38944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
39044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the incoming edges are in edge split form.
39144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (predecessors_.length() > 1) {
39244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 0; i < predecessors_.length(); ++i) {
39344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(predecessors_[i]->end()->SecondSuccessor() == NULL);
39444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
39544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  this->back_edges_.Add(block);
402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddBlock(block);
403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HLoopInformation::GetLastBackEdge() const {
407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int max_id = -1;
408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* result = NULL;
409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < back_edges_.length(); ++i) {
410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* cur = back_edges_[i];
411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (cur->block_id() > max_id) {
412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      max_id = cur->block_id();
413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      result = cur;
414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HLoopInformation::AddBlock(HBasicBlock* block) {
421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block == loop_header()) return;
422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->parent_loop_header() == loop_header()) return;
423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->parent_loop_header() != NULL) {
424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddBlock(block->parent_loop_header());
425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    block->set_parent_loop_header(loop_header());
427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    blocks_.Add(block);
428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < block->predecessors()->length(); ++i) {
429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddBlock(block->predecessors()->at(i));
430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Checks reachability of the blocks in this graph and stores a bit in
438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the BitVector "reachable()" for every block that can be reached
439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// from the start block of the graph. If "dont_visit" is non-null, the given
440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// block is treated as if it would not be part of the graph. "visited_count()"
441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// returns the number of reachable blocks.
442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass ReachabilityAnalyzer BASE_EMBEDDED {
443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ReachabilityAnalyzer(HBasicBlock* entry_block,
445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       int block_count,
446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       HBasicBlock* dont_visit)
447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : visited_count_(0),
448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        stack_(16),
4495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        reachable_(block_count, ZONE),
450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        dont_visit_(dont_visit) {
451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PushBlock(entry_block);
452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Analyze();
453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int visited_count() const { return visited_count_; }
456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const BitVector* reachable() const { return &reachable_; }
457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void PushBlock(HBasicBlock* block) {
460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block != NULL && block != dont_visit_ &&
461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        !reachable_.Contains(block->block_id())) {
462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      reachable_.Add(block->block_id());
463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      stack_.Add(block);
464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      visited_count_++;
465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze() {
469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (!stack_.is_empty()) {
470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HControlInstruction* end = stack_.RemoveLast()->end();
4713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
4723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        PushBlock(it.Current());
4733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int visited_count_;
478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HBasicBlock*> stack_;
479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BitVector reachable_;
480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* dont_visit_;
481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
484592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid HGraph::Verify(bool do_full_verify) const {
485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); i++) {
486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = blocks_.at(i);
487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    block->Verify();
489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that every block contains at least one node and that only the last
491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // node is a control instruction.
492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = block->first();
493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(current != NULL && current->IsBlockEntry());
494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT((current->next() == NULL) == current->IsControlInstruction());
496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(current->block() == block);
497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current->Verify();
498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that successors are correctly set.
502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* first = block->end()->FirstSuccessor();
503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* second = block->end()->SecondSuccessor();
504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(second == NULL || first != NULL);
505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that the predecessor array is correct.
507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (first != NULL) {
508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(first->predecessors()->Contains(block));
509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (second != NULL) {
510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(second->predecessors()->Contains(block));
511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that phis have correct arguments.
515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < block->phis()->length(); j++) {
516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = block->phis()->at(j);
517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->Verify();
518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that all join blocks have predecessors that end with an
521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // unconditional goto and agree on their environment node id.
522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->predecessors()->length() >= 2) {
523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int id = block->predecessors()->first()->last_environment()->ast_id();
524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int k = 0; k < block->predecessors()->length(); k++) {
525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HBasicBlock* predecessor = block->predecessors()->at(k);
526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(predecessor->end()->IsGoto());
527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(predecessor->last_environment()->ast_id() == id);
528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check special property of first block to have no predecessors.
533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(blocks_.at(0)->predecessors()->is_empty());
534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
535592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (do_full_verify) {
536592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Check that the graph is fully connected.
537592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
538592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ASSERT(analyzer.visited_count() == blocks_.length());
539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
540592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Check that entry block dominator is NULL.
541592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ASSERT(entry_block_->dominator() == NULL);
542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
543592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Check dominators.
544592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    for (int i = 0; i < blocks_.length(); ++i) {
545592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      HBasicBlock* block = blocks_.at(i);
546592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (block->dominator() == NULL) {
547592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // Only start block may have no dominator assigned to.
548592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        ASSERT(i == 0);
549592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      } else {
550592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // Assert that block is unreachable if dominator must not be visited.
551592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        ReachabilityAnalyzer dominator_analyzer(entry_block_,
552592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                blocks_.length(),
553592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                block->dominator());
554592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        ASSERT(!dominator_analyzer.reachable()->Contains(block->block_id()));
555592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               Object* value) {
565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!pointer->is_set()) {
5668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HConstant* constant = new(zone()) HConstant(Handle<Object>(value),
5678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                Representation::Tagged());
568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    constant->InsertAfter(GetConstantUndefined());
569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    pointer->set(constant);
570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return pointer->get();
572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstant1() {
576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return GetConstant(&constant_1_, Smi::FromInt(1));
577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantMinus1() {
581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return GetConstant(&constant_minus1_, Smi::FromInt(-1));
582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantTrue() {
58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return GetConstant(&constant_true_, isolate()->heap()->true_value());
587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantFalse() {
59144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return GetConstant(&constant_false_, isolate()->heap()->false_value());
592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5953fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHConstant* HGraph::GetConstantHole() {
5963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return GetConstant(&constant_hole_, isolate()->heap()->the_hole_value());
5973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
5983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHGraphBuilder::HGraphBuilder(CompilationInfo* info,
601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                             TypeFeedbackOracle* oracle)
602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    : function_state_(NULL),
6035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      initial_function_state_(this, info, oracle, NORMAL_RETURN),
604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ast_context_(NULL),
605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break_scope_(NULL),
606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      graph_(NULL),
607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      current_block_(NULL),
608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      inlined_count_(0),
609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      zone_(info->isolate()->zone()),
610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      inline_bailout_(false) {
611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This is not initialized in the initializer list because the
612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // constructor for the initial state relies on function_state_ == NULL
613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // to know it's the initial state.
614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  function_state_= &initial_function_state_;
615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateJoin(HBasicBlock* first,
618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* second,
619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       int join_id) {
620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (first == NULL) {
621e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return second;
622e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (second == NULL) {
623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return first;
624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* join_block = graph_->CreateBasicBlock();
626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    first->Goto(join_block);
627e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    second->Goto(join_block);
628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    join_block->SetJoinId(join_id);
629e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return join_block;
630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::JoinContinue(IterationStatement* statement,
635e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         HBasicBlock* exit_block,
636e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         HBasicBlock* continue_block) {
637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (continue_block != NULL) {
638e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (exit_block != NULL) exit_block->Goto(continue_block);
639e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    continue_block->SetJoinId(statement->ContinueId());
640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return continue_block;
641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
642e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return exit_block;
643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
646e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement,
647e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* loop_entry,
648e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* body_exit,
649e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* loop_successor,
650e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* break_block) {
6513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (body_exit != NULL) body_exit->Goto(loop_entry);
652e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  loop_entry->PostProcessLoopHeader(statement);
653e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (break_block != NULL) {
654e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (loop_successor != NULL) loop_successor->Goto(break_block);
655e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    break_block->SetJoinId(statement->ExitId());
656e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return break_block;
657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
658e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return loop_successor;
659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
662e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HBasicBlock::FinishExit(HControlInstruction* instruction) {
663e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Finish(instruction);
664e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ClearEnvironment();
665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHGraph::HGraph(CompilationInfo* info)
66944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : isolate_(info->isolate()),
670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      next_block_id_(0),
67144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      entry_block_(NULL),
672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      blocks_(8),
673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      values_(16),
674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi_list_(NULL) {
6758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  start_environment_ =
6768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HEnvironment(NULL, info->scope(), info->closure());
6778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  start_environment_->set_ast_id(AstNode::kFunctionEntryId);
67844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  entry_block_ = CreateBasicBlock();
67944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  entry_block_->SetInitialEnvironment(start_environment_);
680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHandle<Code> HGraph::Compile(CompilationInfo* info) {
684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int values = GetMaximumValueID();
6855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (values > LUnallocated::kMaxVirtualRegisters) {
686c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    if (FLAG_trace_bailout) {
6875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      PrintF("Not enough virtual registers for (values).\n");
688c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    }
689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return Handle<Code>::null();
690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LAllocator allocator(values, this);
692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LChunkBuilder builder(info, this, &allocator);
693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LChunk* chunk = builder.Build();
694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (chunk == NULL) return Handle<Code>::null();
695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (!allocator.Allocate(chunk)) {
6975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (FLAG_trace_bailout) {
6985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      PrintF("Not enough virtual registers (regalloc).\n");
6995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
7005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return Handle<Code>::null();
7015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(info->isolate(), NULL, 0);
704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LCodeGen generator(chunk, &assembler, info);
705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  chunk->MarkEmptyBlocks();
707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (generator.GenerateCode()) {
709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (FLAG_trace_codegen) {
710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintF("Crankshaft Compiler - ");
711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    CodeGenerator::MakeCodePrologue(info);
713589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Code::Flags flags = Code::ComputeFlags(Code::OPTIMIZED_FUNCTION);
714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Code> code =
715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        CodeGenerator::MakeCodeEpilogue(&assembler, flags, info);
716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    generator.FinishCode(code);
717e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    CodeGenerator::PrintCode(code, info);
718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return code;
719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Handle<Code>::null();
721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraph::CreateBasicBlock() {
7258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HBasicBlock* result = new(zone()) HBasicBlock(this);
726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  blocks_.Add(result);
727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Canonicalize() {
732e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!FLAG_use_canonicalizing) return;
7335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HPhase phase("H_Canonicalize", this);
734e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < blocks()->length(); ++i) {
735e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HInstruction* instr = blocks()->at(i)->first();
736e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    while (instr != NULL) {
737e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HValue* value = instr->Canonicalize();
738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (value != instr) instr->DeleteAndReplaceWith(value);
739e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      instr = instr->next();
740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::OrderBlocks() {
7465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HPhase phase("H_Block ordering");
7475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  BitVector visited(blocks_.length(), zone());
748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HBasicBlock*> reverse_result(8);
750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* start = blocks_[0];
751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Postorder(start, &visited, &reverse_result, NULL);
752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  blocks_.Rewind(0);
754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = 0;
755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = reverse_result.length() - 1; i >= 0; --i) {
756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* b = reverse_result[i];
757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    blocks_.Add(b);
758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    b->set_block_id(index++);
759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::PostorderLoopBlocks(HLoopInformation* loop,
764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 BitVector* visited,
765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 ZoneList<HBasicBlock*>* order,
766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 HBasicBlock* loop_header) {
767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < loop->blocks()->length(); ++i) {
768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* b = loop->blocks()->at(i);
7693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    for (HSuccessorIterator it(b->end()); !it.Done(); it.Advance()) {
7703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Postorder(it.Current(), visited, order, loop_header);
7713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (b->IsLoopHeader() && b != loop->loop_header()) {
773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PostorderLoopBlocks(b->loop_information(), visited, order, loop_header);
774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Postorder(HBasicBlock* block,
780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       BitVector* visited,
781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       ZoneList<HBasicBlock*>* order,
782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       HBasicBlock* loop_header) {
783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block == NULL || visited->Contains(block->block_id())) return;
784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->parent_loop_header() != loop_header) return;
785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  visited->Add(block->block_id());
786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->IsLoopHeader()) {
787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PostorderLoopBlocks(block->loop_information(), visited, order, loop_header);
7883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) {
7893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Postorder(it.Current(), visited, order, block);
7903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
792592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ASSERT(block->IsFinished());
7933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) {
7943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Postorder(it.Current(), visited, order, loop_header);
7953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(block->end()->FirstSuccessor() == NULL ||
798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         order->Contains(block->end()->FirstSuccessor()) ||
799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         block->end()->FirstSuccessor()->IsLoopHeader());
800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(block->end()->SecondSuccessor() == NULL ||
801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         order->Contains(block->end()->SecondSuccessor()) ||
802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         block->end()->SecondSuccessor()->IsLoopHeader());
803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  order->Add(block);
804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::AssignDominators() {
8085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HPhase phase("H_Assign dominators", this);
809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); ++i) {
8105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HBasicBlock* block = blocks_[i];
8115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (block->IsLoopHeader()) {
81269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // Only the first predecessor of a loop header is from outside the loop.
81369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // All others are back edges, and thus cannot dominate the loop header.
8145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      block->AssignCommonDominator(block->predecessors()->first());
8155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      block->AssignLoopSuccessorDominators();
816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
82269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
8233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
82469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Mark all blocks that are dominated by an unconditional soft deoptimize to
82569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// prevent code motion across those blocks.
82669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid HGraph::PropagateDeoptimizingMark() {
8275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HPhase phase("H_Propagate deoptimizing mark", this);
8283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  MarkAsDeoptimizingRecursively(entry_block());
829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) {
8323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
8333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HBasicBlock* dominated = block->dominated_blocks()->at(i);
8343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing();
8353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MarkAsDeoptimizingRecursively(dominated);
8363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
8373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
8383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::EliminateRedundantPhis() {
8405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HPhase phase("H_Redundant phi elimination", this);
841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Worklist of phis that can potentially be eliminated. Initialized with
843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // all phi nodes. When elimination of a phi node modifies another phi node
844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the modified phi node is added to the worklist.
845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HPhi*> worklist(blocks_.length());
846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); ++i) {
847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    worklist.AddAll(*blocks_[i]->phis());
848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (!worklist.is_empty()) {
851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = worklist.RemoveLast();
852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = phi->block();
853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Skip phi node if it was already replaced.
855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block == NULL) continue;
856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Get replacement value if phi is redundant.
858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HValue* replacement = phi->GetRedundantReplacement();
859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (replacement != NULL) {
861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Iterate through the uses and replace them all.
862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        HValue* value = it.value();
864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        value->SetOperandAt(it.index(), replacement);
865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (value->IsPhi()) worklist.Add(HPhi::cast(value));
866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->RemovePhi(phi);
86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
86944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
87044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
87144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
87244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
87344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HGraph::EliminateUnreachablePhis() {
8745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HPhase phase("H_Unreachable phi elimination", this);
87544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
87644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Initialize worklist.
87744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ZoneList<HPhi*> phi_list(blocks_.length());
87844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ZoneList<HPhi*> worklist(blocks_.length());
87944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < blocks_.length(); ++i) {
88044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int j = 0; j < blocks_[i]->phis()->length(); j++) {
88144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HPhi* phi = blocks_[i]->phis()->at(j);
88244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      phi_list.Add(phi);
8831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // We can't eliminate phis in the receiver position in the environment
8841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // because in case of throwing an error we need this value to
8851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // construct a stack trace.
88644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (phi->HasRealUses() || phi->IsReceiver())  {
88744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        phi->set_is_live(true);
88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        worklist.Add(phi);
88944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
89044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
89144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
89244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
89344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Iteratively mark live phis.
89444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  while (!worklist.is_empty()) {
89544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HPhi* phi = worklist.RemoveLast();
89644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 0; i < phi->OperandCount(); i++) {
89744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HValue* operand = phi->OperandAt(i);
89844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (operand->IsPhi() && !HPhi::cast(operand)->is_live()) {
89944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        HPhi::cast(operand)->set_is_live(true);
90044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        worklist.Add(HPhi::cast(operand));
90144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
90244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
90344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
90444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
90544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Remove unreachable phis.
90644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < phi_list.length(); i++) {
90744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HPhi* phi = phi_list[i];
90844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!phi->is_live()) {
90944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HBasicBlock* block = phi->block();
910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->RemovePhi(phi);
911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->RecordDeletedPhi(phi->merged_index());
912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
917592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochbool HGraph::CheckArgumentsPhiUses() {
918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int block_count = blocks_.length();
919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < block_count; ++i) {
920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      HPhi* phi = blocks_[i]->phis()->at(j);
922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // We don't support phi uses of arguments for now.
923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (phi->CheckFlag(HValue::kIsArguments)) return false;
924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return true;
927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
930592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochbool HGraph::CheckConstPhiUses() {
9313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int block_count = blocks_.length();
9323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < block_count; ++i) {
9333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
9343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HPhi* phi = blocks_[i]->phis()->at(j);
9353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Check for the hole value (from an uninitialized const).
9363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (int k = 0; k < phi->OperandCount(); k++) {
9373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (phi->OperandAt(k) == GetConstantHole()) return false;
9383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
9393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
9403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
9413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return true;
9423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
9433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
945592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid HGraph::CollectPhis() {
946592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  int block_count = blocks_.length();
947592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  phi_list_ = new ZoneList<HPhi*>(block_count);
948592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  for (int i = 0; i < block_count; ++i) {
949592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
950592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      HPhi* phi = blocks_[i]->phis()->at(j);
951592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      phi_list_->Add(phi);
952592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
953592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
954592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
955592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
956592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InferTypes(ZoneList<HValue*>* worklist) {
9585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  BitVector in_worklist(GetMaximumValueID(), zone());
959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < worklist->length(); ++i) {
960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!in_worklist.Contains(worklist->at(i)->id()));
961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    in_worklist.Add(worklist->at(i)->id());
962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (!worklist->is_empty()) {
965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* current = worklist->RemoveLast();
966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    in_worklist.Remove(current->id());
967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->UpdateInferredType()) {
968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      for (HUseIterator it(current->uses()); !it.Done(); it.Advance()) {
969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        HValue* use = it.value();
970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (!in_worklist.Contains(use->id())) {
971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          in_worklist.Add(use->id());
972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          worklist->Add(use);
973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HRangeAnalysis BASE_EMBEDDED {
981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
9825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit HRangeAnalysis(HGraph* graph) :
9835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      graph_(graph), zone_(graph->isolate()->zone()), changed_ranges_(16) { }
984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze();
986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void TraceRange(const char* msg, ...);
989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze(HBasicBlock* block);
9903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void InferControlFlowRange(HCompareIDAndBranch* test, HBasicBlock* dest);
9913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other);
992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferRange(HValue* value);
993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void RollBackTo(int index);
994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AddRange(HValue* value, Range* range);
995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
9975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Zone* zone_;
998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HValue*> changed_ranges_;
999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::TraceRange(const char* msg, ...) {
1003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_range) {
1004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_list arguments;
1005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_start(arguments, msg);
1006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    OS::VPrint(msg, arguments);
1007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_end(arguments);
1008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::Analyze() {
10135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HPhase phase("H_Range analysis", graph_);
10143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Analyze(graph_->entry_block());
1015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::Analyze(HBasicBlock* block) {
1019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("Analyzing block B%d\n", block->block_id());
1020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int last_changed_range = changed_ranges_.length() - 1;
1022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Infer range based on control flow.
1024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->predecessors()->length() == 1) {
1025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* pred = block->predecessors()->first();
10263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (pred->end()->IsCompareIDAndBranch()) {
10273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      InferControlFlowRange(HCompareIDAndBranch::cast(pred->end()), block);
1028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Process phi instructions.
1032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < block->phis()->length(); ++i) {
1033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = block->phis()->at(i);
10343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    InferRange(phi);
1035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Go through all instructions of the current block.
1038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = block->first();
1039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (instr != block->end()) {
1040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferRange(instr);
1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = instr->next();
1042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Continue analysis in all dominated blocks.
1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
1046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Analyze(block->dominated_blocks()->at(i));
1047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RollBackTo(last_changed_range);
1050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
10533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test,
10543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                           HBasicBlock* dest) {
10551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
10563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (test->GetInputRepresentation().IsInteger32()) {
10573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Token::Value op = test->token();
10583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (test->SecondSuccessor() == dest) {
10593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      op = Token::NegateCompareOp(op);
1060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
10613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Token::Value inverted_op = Token::InvertCompareOp(op);
10623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    UpdateControlFlowRange(op, test->left(), test->right());
10633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    UpdateControlFlowRange(inverted_op, test->right(), test->left());
1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// We know that value [op] other. Use this information to update the range on
1069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// value.
10703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HRangeAnalysis::UpdateControlFlowRange(Token::Value op,
10713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                            HValue* value,
10723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                            HValue* other) {
1073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Range temp_range;
1074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Range* range = other->range() != NULL ? other->range() : &temp_range;
1075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Range* new_range = NULL;
1076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("Control flow range infer %d %s %d\n",
1078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             value->id(),
1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             Token::Name(op),
1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             other->id());
1081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (op == Token::EQ || op == Token::EQ_STRICT) {
1083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // The same range has to apply for value.
10845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    new_range = range->Copy(zone_);
1085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::LT || op == Token::LTE) {
10865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    new_range = range->CopyClearLower(zone_);
1087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (op == Token::LT) {
1088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new_range->AddConstant(-1);
1089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::GT || op == Token::GTE) {
10915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    new_range = range->CopyClearUpper(zone_);
1092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (op == Token::GT) {
1093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new_range->AddConstant(1);
1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (new_range != NULL && !new_range->IsMostGeneric()) {
1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddRange(value, new_range);
1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferRange(HValue* value) {
1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!value->HasRange());
1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!value->representation().IsNone()) {
11065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    value->ComputeInitialRange(zone_);
1107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Range* range = value->range();
1108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n",
1109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               value->id(),
1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               value->Mnemonic(),
1111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               range->lower(),
1112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               range->upper());
1113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::RollBackTo(int index) {
1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = index + 1; i < changed_ranges_.length(); ++i) {
1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    changed_ranges_[i]->RemoveLastAddedRange();
1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  changed_ranges_.Rewind(index + 1);
1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::AddRange(HValue* value, Range* range) {
1126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Range* original_range = value->range();
11275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  value->AddNewRange(range, zone_);
1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  changed_ranges_.Add(value);
1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Range* new_range = value->range();
1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("Updated range of %d set to [%d,%d]\n",
1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             value->id(),
1132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             new_range->lower(),
1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             new_range->upper());
1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (original_range != NULL) {
1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceRange("Original range was [%d,%d]\n",
1136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               original_range->lower(),
1137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               original_range->upper());
1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("New information was [%d,%d]\n",
1140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             range->lower(),
1141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             range->upper());
1142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TraceGVN(const char* msg, ...) {
1146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_gvn) {
1147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_list arguments;
1148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_start(arguments, msg);
1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    OS::VPrint(msg, arguments);
1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_end(arguments);
1151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHValueMap::HValueMap(Zone* zone, const HValueMap* other)
1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : array_size_(other->array_size_),
1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      lists_size_(other->lists_size_),
1158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      count_(other->count_),
1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      present_flags_(other->present_flags_),
1160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      array_(zone->NewArray<HValueMapListElement>(other->array_size_)),
1161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      lists_(zone->NewArray<HValueMapListElement>(other->lists_size_)),
1162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      free_list_head_(other->free_list_head_) {
1163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memcpy(array_, other->array_, array_size_ * sizeof(HValueMapListElement));
1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memcpy(lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement));
1165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1168c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid HValueMap::Kill(GVNFlagSet flags) {
1169c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(flags);
1170c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  if (!present_flags_.ContainsAnyOf(depends_flags)) return;
1171c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  present_flags_.RemoveAll();
1172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < array_size_; ++i) {
1173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = array_[i].value;
1174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (value != NULL) {
1175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Clear list of collisions first, so we know if it becomes empty.
1176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int kept = kNil;  // List of kept elements.
1177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int next;
1178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int current = array_[i].next; current != kNil; current = next) {
1179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        next = lists_[current].next;
1180c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        HValue* value = lists_[current].value;
1181c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        if (value->gvn_flags().ContainsAnyOf(depends_flags)) {
1182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          // Drop it.
1183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          count_--;
1184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[current].next = free_list_head_;
1185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          free_list_head_ = current;
1186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else {
1187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          // Keep it.
1188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[current].next = kept;
1189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          kept = current;
1190c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          present_flags_.Add(value->gvn_flags());
1191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      array_[i].next = kept;
1194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Now possibly drop directly indexed element.
1196c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      value = array_[i].value;
1197c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      if (value->gvn_flags().ContainsAnyOf(depends_flags)) {  // Drop it.
1198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        count_--;
1199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int head = array_[i].next;
1200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (head == kNil) {
1201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          array_[i].value = NULL;
1202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else {
1203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          array_[i].value = lists_[head].value;
1204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          array_[i].next = lists_[head].next;
1205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[head].next = free_list_head_;
1206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          free_list_head_ = head;
1207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
1209c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        present_flags_.Add(value->gvn_flags());  // Keep it.
1210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHValue* HValueMap::Lookup(HValue* value) const {
1217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint32_t hash = static_cast<uint32_t>(value->Hashcode());
1218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint32_t pos = Bound(hash);
1219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (array_[pos].value != NULL) {
1220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (array_[pos].value->Equals(value)) return array_[pos].value;
1221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int next = array_[pos].next;
1222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (next != kNil) {
1223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (lists_[next].value->Equals(value)) return lists_[next].value;
1224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      next = lists_[next].next;
1225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return NULL;
1228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Resize(int new_size) {
1232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(new_size > count_);
1233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Hashing the values into the new array has no more collisions than in the
1234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // old hash map, so we can use the existing lists_ array, if we are careful.
1235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Make sure we have at least one free element.
1237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (free_list_head_ == kNil) {
1238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ResizeLists(lists_size_ << 1);
1239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* new_array =
124244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ZONE->NewArray<HValueMapListElement>(new_size);
1243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(new_array, 0, sizeof(HValueMapListElement) * new_size);
1244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* old_array = array_;
1246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int old_size = array_size_;
1247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int old_count = count_;
1249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  count_ = 0;
1250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Do not modify present_flags_.  It is currently correct.
1251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  array_size_ = new_size;
1252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  array_ = new_array;
1253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (old_array != NULL) {
1255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Iterate over all the elements in lists, rehashing them.
1256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < old_size; ++i) {
1257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (old_array[i].value != NULL) {
1258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int current = old_array[i].next;
1259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        while (current != kNil) {
1260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          Insert(lists_[current].value);
1261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          int next = lists_[current].next;
1262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[current].next = free_list_head_;
1263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          free_list_head_ = current;
1264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          current = next;
1265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Rehash the directly stored value.
1267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Insert(old_array[i].value);
1268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  USE(old_count);
1272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(count_ == old_count);
1273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::ResizeLists(int new_size) {
1277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(new_size > lists_size_);
1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* new_lists =
128044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ZONE->NewArray<HValueMapListElement>(new_size);
1281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(new_lists, 0, sizeof(HValueMapListElement) * new_size);
1282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* old_lists = lists_;
1284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int old_size = lists_size_;
1285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  lists_size_ = new_size;
1287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  lists_ = new_lists;
1288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (old_lists != NULL) {
1290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    memcpy(lists_, old_lists, old_size * sizeof(HValueMapListElement));
1291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = old_size; i < lists_size_; ++i) {
1293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    lists_[i].next = free_list_head_;
1294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    free_list_head_ = i;
1295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Insert(HValue* value) {
1300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(value != NULL);
1301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Resizing when half of the hashtable is filled up.
1302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (count_ >= array_size_ >> 1) Resize(array_size_ << 1);
1303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(count_ < array_size_);
1304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  count_++;
1305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint32_t pos = Bound(static_cast<uint32_t>(value->Hashcode()));
1306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (array_[pos].value == NULL) {
1307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    array_[pos].value = value;
1308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    array_[pos].next = kNil;
1309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
1310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (free_list_head_ == kNil) {
1311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ResizeLists(lists_size_ << 1);
1312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int new_element_pos = free_list_head_;
1314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(new_element_pos != kNil);
1315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    free_list_head_ = lists_[free_list_head_].next;
1316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    lists_[new_element_pos].value = value;
1317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    lists_[new_element_pos].next = array_[pos].next;
1318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value != NULL);
1319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    array_[pos].next = new_element_pos;
1320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HStackCheckEliminator BASE_EMBEDDED {
1325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
1326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { }
1327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Process();
1329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
1331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
1332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStackCheckEliminator::Process() {
1336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // For each loop block walk the dominator tree from the backwards branch to
1337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the loop header. If a call instruction is encountered the backwards branch
1338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // is dominated by a call and the stack check in the backwards branch can be
1339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // removed.
1340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < graph_->blocks()->length(); i++) {
1341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
1343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge();
1344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* dominator = back_edge;
13453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      while (true) {
1346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HInstruction* instr = dominator->first();
13473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        while (instr != NULL) {
1348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (instr->IsCall()) {
13493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            block->loop_information()->stack_check()->Eliminate();
13503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            break;
1351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
1352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          instr = instr->next();
1353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
13553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        // Done when the loop header is processed.
13563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (dominator == block) break;
1357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
13583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        // Move up the dominator tree.
13593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        dominator = dominator->dominator();
13603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
1361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Simple sparse set with O(1) add, contains, and clear.
1367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass SparseSet {
1368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
1369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SparseSet(Zone* zone, int capacity)
1370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : capacity_(capacity),
1371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        length_(0),
1372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        dense_(zone->NewArray<int>(capacity)),
13733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        sparse_(zone->NewArray<int>(capacity)) {
13743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#ifndef NVALGRIND
13753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Initialize the sparse array to make valgrind happy.
13763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    memset(sparse_, 0, sizeof(sparse_[0]) * capacity);
13773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
13783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool Contains(int n) const {
1381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(0 <= n && n < capacity_);
1382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int d = sparse_[n];
1383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return 0 <= d && d < length_ && dense_[d] == n;
1384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool Add(int n) {
1387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (Contains(n)) return false;
1388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    dense_[length_] = n;
1389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    sparse_[n] = length_;
1390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ++length_;
1391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return true;
1392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Clear() { length_ = 0; }
1395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
1397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int capacity_;
1398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int length_;
1399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int* dense_;
1400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int* sparse_;
1401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(SparseSet);
1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
1404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HGlobalValueNumberer BASE_EMBEDDED {
1407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
1408e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info)
1409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : graph_(graph),
1410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        info_(info),
1411592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        removed_side_effects_(false),
1412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        block_side_effects_(graph->blocks()->length()),
1413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        loop_side_effects_(graph->blocks()->length()),
1414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        visited_on_paths_(graph->zone(), graph->blocks()->length()) {
141544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(info->isolate()->heap()->allow_allocation(false));
1416c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    block_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length());
1417c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    loop_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length());
1418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ~HGlobalValueNumberer() {
142044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(!info_->isolate()->heap()->allow_allocation(true));
1421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1423592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Returns true if values with side effects are removed.
1424592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  bool Analyze();
1425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
1427c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock(
1428c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      HBasicBlock* dominator,
1429c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      HBasicBlock* dominated);
1430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
1431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void ComputeBlockSideEffects();
1432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void LoopInvariantCodeMotion();
1433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void ProcessLoopBlock(HBasicBlock* block,
1434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        HBasicBlock* before_loop,
14355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                        GVNFlagSet loop_kills,
14365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                        GVNFlagSet* accumulated_first_time_depends,
14375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                        GVNFlagSet* accumulated_first_time_changes);
1438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool AllowCodeMotion();
1439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
1440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HGraph* graph() { return graph_; }
1442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompilationInfo* info() { return info_; }
14438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Zone* zone() { return graph_->zone(); }
1444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
1446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompilationInfo* info_;
1447592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  bool removed_side_effects_;
1448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // A map of block IDs to their side effects.
1450c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  ZoneList<GVNFlagSet> block_side_effects_;
1451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // A map of loop header block IDs to their loop's side effects.
1453c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  ZoneList<GVNFlagSet> loop_side_effects_;
1454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Used when collecting side effects on paths from dominator to
1456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // dominated.
1457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SparseSet visited_on_paths_;
1458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1461592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochbool HGlobalValueNumberer::Analyze() {
14625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  removed_side_effects_ = false;
1463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ComputeBlockSideEffects();
1464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_loop_invariant_code_motion) {
1465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LoopInvariantCodeMotion();
1466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
14678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HValueMap* map = new(zone()) HValueMap();
14683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AnalyzeBlock(graph_->entry_block(), map);
1469592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return removed_side_effects_;
1470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::ComputeBlockSideEffects() {
14745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // The Analyze phase of GVN can be called multiple times. Clear loop side
14755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // effects before computing them to erase the contents from previous Analyze
14765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // passes.
14775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  for (int i = 0; i < loop_side_effects_.length(); ++i) {
14785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    loop_side_effects_[i].RemoveAll();
14795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
1480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Compute side effects for the block.
1482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* instr = block->first();
1484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int id = block->block_id();
1485c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    GVNFlagSet side_effects;
1486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (instr != NULL) {
1487c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      side_effects.Add(instr->ChangesFlags());
14885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (instr->IsSoftDeoptimize()) {
14895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        block_side_effects_[id].RemoveAll();
14905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        side_effects.RemoveAll();
14915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        break;
14925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
1493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = instr->next();
1494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1495c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    block_side_effects_[id].Add(side_effects);
1496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Loop headers are part of their loop.
1498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
1499c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      loop_side_effects_[id].Add(side_effects);
1500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Propagate loop side effects upwards.
1503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->HasParentLoopHeader()) {
1504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int header_id = block->parent_loop_header()->block_id();
1505c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      loop_side_effects_[header_id].Add(block->IsLoopHeader()
1506c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                        ? loop_side_effects_[id]
1507c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                        : side_effects);
1508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::LoopInvariantCodeMotion() {
1514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
1517c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      GVNFlagSet side_effects = loop_side_effects_[block->block_id()];
1518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n",
1519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               block->block_id(),
1520c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch               side_effects.ToIntegral());
1521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
15225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      GVNFlagSet accumulated_first_time_depends;
15235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      GVNFlagSet accumulated_first_time_changes;
1524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* last = block->loop_information()->GetLastBackEdge();
1525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = block->block_id(); j <= last->block_id(); ++j) {
15265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects,
15275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                         &accumulated_first_time_depends,
15285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                         &accumulated_first_time_changes);
1529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
15355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGlobalValueNumberer::ProcessLoopBlock(
15365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HBasicBlock* block,
15375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HBasicBlock* loop_header,
15385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    GVNFlagSet loop_kills,
15395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    GVNFlagSet* first_time_depends,
15405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    GVNFlagSet* first_time_changes) {
1541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* pre_header = loop_header->predecessors()->at(0);
1542c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
1543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n",
1544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           block->block_id(),
1545c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch           depends_flags.ToIntegral());
1546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = block->first();
1547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (instr != NULL) {
1548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* next = instr->next();
15495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    bool hoisted = false;
15505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (instr->CheckFlag(HValue::kUseGVN)) {
15515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      TraceGVN("Checking instruction %d (%s) instruction GVN flags 0x%X, "
15525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch               "loop kills 0x%X\n",
1553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               instr->id(),
15545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch               instr->Mnemonic(),
15555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch               instr->gvn_flags().ToIntegral(),
15565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch               depends_flags.ToIntegral());
15575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags);
15585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (instr->IsTransitionElementsKind()) {
15595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        // It's possible to hoist transitions out of a loop as long as the
15605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        // hoisting wouldn't move the transition past a DependsOn of one of it's
15615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        // changes or any instructions that might change an objects map or
15625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        // elements contents.
15635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        GVNFlagSet changes = instr->ChangesFlags();
15645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        GVNFlagSet hoist_depends_blockers =
15655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            HValue::ConvertChangesToDependsFlags(changes);
15665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        // In addition to not hoisting transitions above other instructions that
15675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        // change dependencies that the transition changes, it must not be
15685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        // hoisted above map changes and stores to an elements backing store
15695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        // that the transition might change.
15705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        GVNFlagSet hoist_change_blockers = changes;
15715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        hoist_change_blockers.Add(kChangesMaps);
15725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        HTransitionElementsKind* trans = HTransitionElementsKind::cast(instr);
15735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (trans->original_map()->has_fast_double_elements()) {
15745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          hoist_change_blockers.Add(kChangesDoubleArrayElements);
15755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        }
15765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (trans->transitioned_map()->has_fast_double_elements()) {
15775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          hoist_change_blockers.Add(kChangesArrayElements);
1578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
15795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        TraceGVN("Checking dependencies on HTransitionElementsKind %d (%s) "
15805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                 "hoist depends blockers 0x%X, hoist change blockers 0x%X, "
15815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                 "accumulated depends 0x%X, accumulated changes 0x%X\n",
15825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                 instr->id(),
15835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                 instr->Mnemonic(),
15845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                 hoist_depends_blockers.ToIntegral(),
15855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                 hoist_change_blockers.ToIntegral(),
15865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                 first_time_depends->ToIntegral(),
15875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                 first_time_changes->ToIntegral());
15885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        // It's possible to hoist transition from the current loop loop only if
15895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        // they dominate all of the successor blocks in the same loop and there
15905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        // are not any instructions that have Changes/DependsOn that intervene
15915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        // between it and the beginning of the loop header.
15925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        bool in_nested_loop = block != loop_header &&
15935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            ((block->parent_loop_header() != loop_header) ||
15945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch             block->IsLoopHeader());
15955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        can_hoist = !in_nested_loop &&
15965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            block->IsLoopSuccessorDominator() &&
15975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            !first_time_depends->ContainsAnyOf(hoist_depends_blockers) &&
15985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            !first_time_changes->ContainsAnyOf(hoist_change_blockers);
1599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
16015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (can_hoist) {
16025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        bool inputs_loop_invariant = true;
16035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        for (int i = 0; i < instr->OperandCount(); ++i) {
16045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) {
16055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            inputs_loop_invariant = false;
16065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          }
16075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        }
16085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
16095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (inputs_loop_invariant && ShouldMove(instr, loop_header)) {
16105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          TraceGVN("Hoisting loop invariant instruction %d\n", instr->id());
16115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          // Move the instruction out of the loop.
16125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          instr->Unlink();
16135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          instr->InsertBefore(pre_header->end());
16145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          if (instr->HasSideEffects()) removed_side_effects_ = true;
16155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          hoisted = true;
16165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        }
1617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
16195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (!hoisted) {
16205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      // If an instruction is not hoisted, we have to account for its side
16215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      // effects when hoisting later HTransitionElementsKind instructions.
16225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      first_time_depends->Add(instr->DependsOnFlags());
16235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      first_time_changes->Add(instr->ChangesFlags());
16245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
1625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = next;
1626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
16291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1630e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool HGlobalValueNumberer::AllowCodeMotion() {
1631e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
1632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
1636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                      HBasicBlock* loop_header) {
16373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // If we've disabled code motion or we're in a block that unconditionally
16383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // deoptimizes, don't move any instructions.
16393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return AllowCodeMotion() && !instr->block()->IsDeoptimizing();
1640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1643c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben MurdochGVNFlagSet HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
1644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* dominator, HBasicBlock* dominated) {
1645c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  GVNFlagSet side_effects;
1646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < dominated->predecessors()->length(); ++i) {
1647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* block = dominated->predecessors()->at(i);
1648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (dominator->block_id() < block->block_id() &&
1649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        block->block_id() < dominated->block_id() &&
1650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        visited_on_paths_.Add(block->block_id())) {
1651c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      side_effects.Add(block_side_effects_[block->block_id()]);
1652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (block->IsLoopHeader()) {
1653c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        side_effects.Add(loop_side_effects_[block->block_id()]);
1654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
1655c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock(
1656c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          dominator, block));
1657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return side_effects;
1660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
1664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TraceGVN("Analyzing block B%d%s\n",
1665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           block->block_id(),
1666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           block->IsLoopHeader() ? " (loop header)" : "");
1667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If this is a loop header kill everything killed by the loop.
1669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->IsLoopHeader()) {
1670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    map->Kill(loop_side_effects_[block->block_id()]);
1671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Go through all instructions of the current block.
1674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = block->first();
1675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (instr != NULL) {
1676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* next = instr->next();
1677c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    GVNFlagSet flags = instr->ChangesFlags();
1678c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    if (!flags.IsEmpty()) {
1679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Clear all instructions in the map that are affected by side effects.
1680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      map->Kill(flags);
1681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TraceGVN("Instruction %d kills\n", instr->id());
1682592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
1683592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (instr->CheckFlag(HValue::kUseGVN)) {
1684592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT(!instr->HasObservableSideEffects());
1685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* other = map->Lookup(instr);
1686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (other != NULL) {
1687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(instr->Equals(other) && other->Equals(instr));
1688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        TraceGVN("Replacing value %d (%s) with value %d (%s)\n",
1689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 instr->id(),
1690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 instr->Mnemonic(),
1691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 other->id(),
1692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 other->Mnemonic());
1693592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        if (instr->HasSideEffects()) removed_side_effects_ = true;
1694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        instr->DeleteAndReplaceWith(other);
1695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
1696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        map->Add(instr);
1697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = next;
1700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Recursively continue analysis for all immediately dominated blocks.
1703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = block->dominated_blocks()->length();
1704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; ++i) {
1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* dominated = block->dominated_blocks()->at(i);
1706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // No need to copy the map for the last child in the dominator tree.
17078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone());
1708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Kill everything killed on any path between this block and the
1710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // dominated block.
1711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // We don't have to traverse these paths if the value map is
1712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // already empty.
1713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // If the range of block ids (block_id, dominated_id) is empty
1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // there are no such paths.
1715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!successor_map->IsEmpty() &&
1716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        block->block_id() + 1 < dominated->block_id()) {
1717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      visited_on_paths_.Clear();
1718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      successor_map->Kill(CollectSideEffectsOnPathsToDominatedBlock(block,
1719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                                    dominated));
1720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AnalyzeBlock(dominated, successor_map);
1722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HInferRepresentation BASE_EMBEDDED {
1727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
1728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit HInferRepresentation(HGraph* graph)
17295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : graph_(graph),
17305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        worklist_(8),
17315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        in_worklist_(graph->GetMaximumValueID(), graph->zone()) { }
1732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze();
1734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
1736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation TryChange(HValue* current);
1737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AddToWorklist(HValue* current);
1738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferBasedOnInputs(HValue* current);
1739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AddDependantsToWorklist(HValue* current);
1740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferBasedOnUses(HValue* current);
1741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
17428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Zone* zone() { return graph_->zone(); }
17438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
1745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HValue*> worklist_;
1746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BitVector in_worklist_;
1747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::AddToWorklist(HValue* current) {
1751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (current->representation().IsSpecialization()) return;
1752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return;
1753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (in_worklist_.Contains(current->id())) return;
1754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  worklist_.Add(current);
1755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  in_worklist_.Add(current->id());
1756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This method tries to specialize the representation type of the value
1760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// given as a parameter. The value is asked to infer its representation type
1761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// based on its inputs. If the inferred type is more specialized, then this
1762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// becomes the new representation type of the node.
1763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::InferBasedOnInputs(HValue* current) {
1764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation r = current->representation();
1765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (r.IsSpecialization()) return;
1766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation));
1767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation inferred = current->InferredRepresentation();
1768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (inferred.IsSpecialization()) {
17695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (FLAG_trace_representation) {
17705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      PrintF("Changing #%d representation %s -> %s based on inputs\n",
17715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch             current->id(),
17725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch             r.Mnemonic(),
17735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch             inferred.Mnemonic());
17745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
1775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current->ChangeRepresentation(inferred);
1776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddDependantsToWorklist(current);
1777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HInferRepresentation::AddDependantsToWorklist(HValue* value) {
1782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
1783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AddToWorklist(it.value());
1784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < value->OperandCount(); ++i) {
1786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AddToWorklist(value->OperandAt(i));
1787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This method calculates whether specializing the representation of the value
1792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// given as the parameter has a benefit in terms of less necessary type
1793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// conversions. If there is a benefit, then the representation of the value is
1794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// specialized.
1795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HInferRepresentation::InferBasedOnUses(HValue* value) {
1796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Representation r = value->representation();
1797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (r.IsSpecialization() || value->HasNoUses()) return;
1798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(value->CheckFlag(HValue::kFlexibleRepresentation));
1799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Representation new_rep = TryChange(value);
1800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!new_rep.IsNone()) {
1801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!value->representation().Equals(new_rep)) {
18025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (FLAG_trace_representation) {
18035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        PrintF("Changing #%d representation %s -> %s based on uses\n",
18045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch               value->id(),
18055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch               r.Mnemonic(),
18065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch               new_rep.Mnemonic());
18075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
1808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      value->ChangeRepresentation(new_rep);
1809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      AddDependantsToWorklist(value);
1810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochRepresentation HInferRepresentation::TryChange(HValue* value) {
1816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Array of use counts for each representation.
1817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int use_count[Representation::kNumRepresentations] = { 0 };
1818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
1820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HValue* use = it.value();
1821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Representation rep = use->RequiredInputRepresentation(it.index());
1822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (rep.IsNone()) continue;
1823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (use->IsPhi()) HPhi::cast(use)->AddIndirectUsesTo(&use_count[0]);
18245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    use_count[rep.kind()] += use->LoopWeight();
1825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int tagged_count = use_count[Representation::kTagged];
1827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int double_count = use_count[Representation::kDouble];
1828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int int32_count = use_count[Representation::kInteger32];
1829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int non_tagged_count = double_count + int32_count;
1830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If a non-loop phi has tagged uses, don't convert it to untagged.
1832589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (value->IsPhi() && !value->block()->IsLoopHeader() && tagged_count > 0) {
1833589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return Representation::None();
1834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1836589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Prefer unboxing over boxing, the latter is more expensive.
1837592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (tagged_count > non_tagged_count) return Representation::None();
1838589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1839589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Prefer Integer32 over Double, if possible.
1840589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (int32_count > 0 && value->IsConvertibleToInteger()) {
1841589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return Representation::Integer32();
1842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1843589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1844589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (double_count > 0) return Representation::Double();
1845589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Representation::None();
1847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::Analyze() {
18515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HPhase phase("H_Infer representations", graph_);
1852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // (1) Initialize bit vectors and count real uses. Each phi gets a
1854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // bit-vector of length <number of phis>.
1855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<HPhi*>* phi_list = graph_->phi_list();
1856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int phi_count = phi_list->length();
1857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneList<BitVector*> connected_phis(phi_count);
1858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < phi_count; ++i) {
1859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    phi_list->at(i)->InitRealUses(i);
18605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    BitVector* connected_set = new(zone()) BitVector(phi_count, graph_->zone());
1861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    connected_set->Add(i);
1862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    connected_phis.Add(connected_set);
1863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // (2) Do a fixed point iteration to find the set of connected phis.  A
1866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // phi is connected to another phi if its value is used either directly or
1867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // indirectly through a transitive closure of the def-use relation.
1868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool change = true;
1869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (change) {
1870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    change = false;
1871589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // We normally have far more "forward edges" than "backward edges",
1872589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // so we terminate faster when we walk backwards.
1873589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    for (int i = phi_count - 1; i >= 0; --i) {
1874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = phi_list->at(i);
1875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
1876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        HValue* use = it.value();
1877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (use->IsPhi()) {
1878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          int id = HPhi::cast(use)->phi_id();
18793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          if (connected_phis[i]->UnionIsChanged(*connected_phis[id]))
18803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            change = true;
1881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1886589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // (3) Use the phi reachability information from step 2 to
1887589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  //     (a) sum up the non-phi use counts of all connected phis.
1888589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  //     (b) push information about values which can't be converted to integer
1889589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  //         without deoptimization through the phi use-def chains, avoiding
1890589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  //         unnecessary deoptimizations later.
1891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < phi_count; ++i) {
1892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = phi_list->at(i);
1893589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    bool cti = phi->AllOperandsConvertibleToInteger();
1894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (BitVector::Iterator it(connected_phis.at(i));
1895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         !it.Done();
1896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         it.Advance()) {
1897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int index = it.Current();
1898589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      HPhi* it_use = phi_list->at(it.Current());
1899589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (index != i) phi->AddNonPhiUsesFrom(it_use);  // Don't count twice!
1900589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (!cti) it_use->set_is_convertible_to_integer(false);
1901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1904589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Initialize work list
1905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < graph_->blocks()->length(); ++i) {
1906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const ZoneList<HPhi*>* phis = block->phis();
1908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < phis->length(); ++j) {
1909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddToWorklist(phis->at(j));
1910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = block->first();
1913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
1914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddToWorklist(current);
1915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
1916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1919589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Do a fixed point iteration, trying to improve representations
1920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (!worklist_.is_empty()) {
1921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* current = worklist_.RemoveLast();
1922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    in_worklist_.Remove(current->id());
1923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferBasedOnInputs(current);
1924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferBasedOnUses(current);
1925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InitializeInferredTypes() {
19305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HPhase phase("H_Inferring types", this);
1931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  InitializeInferredTypes(0, this->blocks_.length() - 1);
1932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InitializeInferredTypes(int from_inclusive, int to_inclusive) {
1936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = from_inclusive; i <= to_inclusive; ++i) {
1937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = blocks_[i];
1938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const ZoneList<HPhi*>* phis = block->phis();
1940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < phis->length(); j++) {
1941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phis->at(j)->UpdateInferredType();
1942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = block->first();
1945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
1946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current->UpdateInferredType();
1947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
1948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
1951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* last_back_edge =
1952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          block->loop_information()->GetLastBackEdge();
1953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InitializeInferredTypes(i + 1, last_back_edge->block_id());
1954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Skip all blocks already processed by the recursive call.
1955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      i = last_back_edge->block_id();
1956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Update phis of the loop header now after the whole loop body is
1957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // guaranteed to be processed.
1958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ZoneList<HValue*> worklist(block->phis()->length());
1959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < block->phis()->length(); ++j) {
1960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        worklist.Add(block->phis()->at(j));
1961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InferTypes(&worklist);
1963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) {
1969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* current = value;
1970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (current != NULL) {
1971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (visited->Contains(current->id())) return;
1972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // For phis, we must propagate the check to all of its inputs.
1974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->IsPhi()) {
1975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      visited->Add(current->id());
1976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = HPhi::cast(current);
1977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int i = 0; i < phi->OperandCount(); ++i) {
1978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PropagateMinusZeroChecks(phi->OperandAt(i), visited);
1979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
1981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // For multiplication and division, we must propagate to the left and
1984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // the right side.
1985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->IsMul()) {
1986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HMul* mul = HMul::cast(current);
1987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      mul->EnsureAndPropagateNotMinusZero(visited);
1988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(mul->left(), visited);
1989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(mul->right(), visited);
1990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (current->IsDiv()) {
1991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HDiv* div = HDiv::cast(current);
1992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      div->EnsureAndPropagateNotMinusZero(visited);
1993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(div->left(), visited);
1994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(div->right(), visited);
1995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current = current->EnsureAndPropagateNotMinusZero(visited);
1998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChangeForUse(HValue* value,
2003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              HValue* use_value,
2004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              int use_index,
2005e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              Representation to) {
2006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Insert the representation change right before its use. For phi-uses we
2007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // insert at the end of the corresponding predecessor.
20081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  HInstruction* next = NULL;
2009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (use_value->IsPhi()) {
2010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    next = use_value->block()->predecessors()->at(use_index)->end();
20111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
2012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    next = HInstruction::cast(use_value);
2013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // For constants we try to make the representation change at compile
2016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // time. When a representation change is not possible without loss of
2017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // information we treat constants like normal instructions and insert the
2018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // change instructions for them.
2019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* new_value = NULL;
2020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32);
2021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool deoptimize_on_undefined =
2022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      use_value->CheckFlag(HValue::kDeoptimizeOnUndefined);
2023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (value->IsConstant()) {
2024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HConstant* constant = HConstant::cast(value);
2025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Try to create a new copy of the constant with the new representation.
2026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_value = is_truncating
2027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ? constant->CopyToTruncatedInt32()
2028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        : constant->CopyToRepresentation(to);
2029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (new_value == NULL) {
2032592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    new_value = new(zone()) HChange(value, to,
20337d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch                                    is_truncating, deoptimize_on_undefined);
2034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  new_value->InsertBefore(next);
2037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  use_value->SetOperandAt(use_index, new_value);
2038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraph::InsertRepresentationChangesForValue(HValue* value) {
2042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Representation r = value->representation();
2043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (r.IsNone()) return;
2044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (value->HasNoUses()) return;
2045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
2047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HValue* use_value = it.value();
2048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int use_index = it.index();
2049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Representation req = use_value->RequiredInputRepresentation(use_index);
2050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (req.IsNone() || req.Equals(r)) continue;
2051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    InsertRepresentationChangeForUse(value, use_value, use_index, req);
2052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (value->HasNoUses()) {
2054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(value->IsConstant());
2055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value->DeleteAndReplaceWith(NULL);
2056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // The only purpose of a HForceRepresentation is to represent the value
2059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // after the (possible) HChange instruction.  We make it disappear.
2060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (value->IsForceRepresentation()) {
2061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value());
2062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChanges() {
20675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HPhase phase("H_Representation changes", this);
2068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Compute truncation flag for phis: Initially assume that all
2070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // int32-phis allow truncation and iteratively remove the ones that
2071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // are used in an operation that does not allow a truncating
2072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // conversion.
2073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(fschneider): Replace this with a worklist-based iteration.
2074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < phi_list()->length(); i++) {
2075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = phi_list()->at(i);
2076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (phi->representation().IsInteger32()) {
2077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->SetFlag(HValue::kTruncatingToInt32);
2078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool change = true;
2081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (change) {
2082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    change = false;
2083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < phi_list()->length(); i++) {
2084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = phi_list()->at(i);
2085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue;
20865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (!phi->CheckUsesForFlag(HValue::kTruncatingToInt32)) {
20875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        phi->ClearFlag(HValue::kTruncatingToInt32);
20885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        change = true;
2089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
2090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); ++i) {
2094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Process phi instructions first.
2095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    const ZoneList<HPhi*>* phis = blocks_[i]->phis();
2096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (int j = 0; j < phis->length(); j++) {
2097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      InsertRepresentationChangesForValue(phis->at(j));
2098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Process normal instructions.
2101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = blocks_[i]->first();
2102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
2103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      InsertRepresentationChangesForValue(current);
2104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
2105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
21107d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdochvoid HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) {
21117d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  if (phi->CheckFlag(HValue::kDeoptimizeOnUndefined)) return;
21127d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  phi->SetFlag(HValue::kDeoptimizeOnUndefined);
21137d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  for (int i = 0; i < phi->OperandCount(); ++i) {
21147d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    HValue* input = phi->OperandAt(i);
21157d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    if (input->IsPhi()) {
21167d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch      RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input));
21177d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    }
21187d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  }
21197d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch}
21207d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch
21217d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch
21227d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdochvoid HGraph::MarkDeoptimizeOnUndefined() {
21235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HPhase phase("H_MarkDeoptimizeOnUndefined", this);
21247d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // Compute DeoptimizeOnUndefined flag for phis.
21257d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // Any phi that can reach a use with DeoptimizeOnUndefined set must
21263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have DeoptimizeOnUndefined set.  Currently only HCompareIDAndBranch, with
21277d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // double input representation, has this flag set.
21287d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // The flag is used by HChange tagged->double, which must deoptimize
21297d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // if one of its uses has this flag set.
21307d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  for (int i = 0; i < phi_list()->length(); i++) {
21317d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    HPhi* phi = phi_list()->at(i);
21327d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    if (phi->representation().IsDouble()) {
2133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
2134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (it.value()->CheckFlag(HValue::kDeoptimizeOnUndefined)) {
21357d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch          RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
21367d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch          break;
21377d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch        }
21387d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch      }
21397d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    }
21407d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  }
21417d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch}
21427d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch
21437d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch
21441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid HGraph::ComputeMinusZeroChecks() {
21455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  BitVector visited(GetMaximumValueID(), zone());
21461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = 0; i < blocks_.length(); ++i) {
21471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    for (HInstruction* current = blocks_[i]->first();
21481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block         current != NULL;
21491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block         current = current->next()) {
21501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (current->IsChange()) {
21511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        HChange* change = HChange::cast(current);
21521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // Propagate flags for negative zero checks upwards from conversions
21531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // int32-to-tagged and int32-to-double.
21541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Representation from = change->value()->representation();
21551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ASSERT(from.Equals(change->from()));
21561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if (from.IsInteger32()) {
21571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          ASSERT(change->to().IsTagged() || change->to().IsDouble());
21581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          ASSERT(visited.IsEmpty());
21591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          PropagateMinusZeroChecks(change->value(), &visited);
21601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          visited.Clear();
21611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        }
21621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
21631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
21641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
21651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
21661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
21671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Implementation of utility class to encapsulate the translation state for
2169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// a (possibly inlined) function.
2170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochFunctionState::FunctionState(HGraphBuilder* owner,
2171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                             CompilationInfo* info,
2172592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                             TypeFeedbackOracle* oracle,
21735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             ReturnHandlingFlag return_handling)
2174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    : owner_(owner),
2175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      compilation_info_(info),
2176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      oracle_(oracle),
2177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      call_context_(NULL),
21785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      return_handling_(return_handling),
2179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      function_return_(NULL),
2180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      test_context_(NULL),
2181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      outer_(owner->function_state()) {
2182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (outer_ != NULL) {
2183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // State for an inline function.
2184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (owner->ast_context()->IsTest()) {
2185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
2186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
2187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if_true->MarkAsInlineReturnTarget();
2188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if_false->MarkAsInlineReturnTarget();
21893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Expression* cond = TestContext::cast(owner->ast_context())->condition();
2190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // The AstContext constructor pushed on the context stack.  This newed
2191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // instance is the reason that AstContext can't be BASE_EMBEDDED.
21923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      test_context_ = new TestContext(owner, cond, if_true, if_false);
2193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
2194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      function_return_ = owner->graph()->CreateBasicBlock();
2195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      function_return()->MarkAsInlineReturnTarget();
2196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Set this after possibly allocating a new TestContext above.
2198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    call_context_ = owner->ast_context();
2199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Push on the state stack.
2202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  owner->set_function_state(this);
2203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochFunctionState::~FunctionState() {
2207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  delete test_context_;
2208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  owner_->set_function_state(outer_);
2209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Implementation of utility classes to represent an expression's context in
2213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the AST.
2214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
22158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : owner_(owner),
22168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      kind_(kind),
22178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      outer_(owner->ast_context()),
22188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      for_typeof_(false) {
2219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner->set_ast_context(this);  // Push.
2220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
22215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT(owner->environment()->frame_type() == JS_FUNCTION);
22229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  original_length_ = owner->environment()->length();
2223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
2224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAstContext::~AstContext() {
2228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner_->set_ast_context(outer_);  // Pop.
2229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochEffectContext::~EffectContext() {
2233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(owner()->HasStackOverflow() ||
2234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         owner()->current_block() == NULL ||
2235c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch         (owner()->environment()->length() == original_length_ &&
22365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          owner()->environment()->frame_type() == JS_FUNCTION));
2237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochValueContext::~ValueContext() {
2241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(owner()->HasStackOverflow() ||
2242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         owner()->current_block() == NULL ||
2243c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch         (owner()->environment()->length() == original_length_ + 1 &&
22445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          owner()->environment()->frame_type() == JS_FUNCTION));
2245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid EffectContext::ReturnValue(HValue* value) {
2249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The value is simply ignored.
2250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid ValueContext::ReturnValue(HValue* value) {
2254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The value is tracked in the bailout environment, and communicated
2255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // through the environment as the result of the expression.
2256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) {
2257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    owner()->Bailout("bad value context for arguments value");
2258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->Push(value);
2260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::ReturnValue(HValue* value) {
2264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BuildBranch(value);
2265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) {
22693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(!instr->IsControlInstruction());
2270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->AddInstruction(instr);
2271592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id);
2272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid EffectContext::ReturnControl(HControlInstruction* instr, int ast_id) {
2276592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  ASSERT(!instr->HasObservableSideEffects());
22773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
22783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
22793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  instr->SetSuccessorAt(0, empty_true);
22803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  instr->SetSuccessorAt(1, empty_false);
22813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->current_block()->Finish(instr);
22823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
22833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->set_current_block(join);
22843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
22853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
22863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) {
22883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(!instr->IsControlInstruction());
2289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
22903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return owner()->Bailout("bad value context for arguments object value");
2291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->AddInstruction(instr);
2293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->Push(instr);
2294592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id);
2295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid ValueContext::ReturnControl(HControlInstruction* instr, int ast_id) {
2299592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  ASSERT(!instr->HasObservableSideEffects());
23003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
23013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return owner()->Bailout("bad value context for arguments object value");
23023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
23033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
23043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
23053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  instr->SetSuccessorAt(0, materialize_true);
23063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  instr->SetSuccessorAt(1, materialize_false);
23073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->current_block()->Finish(instr);
23083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->set_current_block(materialize_true);
23093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->Push(owner()->graph()->GetConstantTrue());
23103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->set_current_block(materialize_false);
23113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->Push(owner()->graph()->GetConstantFalse());
23123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* join =
23133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    owner()->CreateJoin(materialize_true, materialize_false, ast_id);
23143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->set_current_block(join);
23153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
23163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
23173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::ReturnInstruction(HInstruction* instr, int ast_id) {
23193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(!instr->IsControlInstruction());
2320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraphBuilder* builder = owner();
2321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  builder->AddInstruction(instr);
2322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We expect a simulate after every expression with side effects, though
2323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // this one isn't actually needed (and wouldn't work if it were targeted).
2324592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (instr->HasObservableSideEffects()) {
2325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    builder->Push(instr);
2326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    builder->AddSimulate(ast_id);
2327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    builder->Pop();
2328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BuildBranch(instr);
2330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
23333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid TestContext::ReturnControl(HControlInstruction* instr, int ast_id) {
2334592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  ASSERT(!instr->HasObservableSideEffects());
23353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
23363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
23373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  instr->SetSuccessorAt(0, empty_true);
23383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  instr->SetSuccessorAt(1, empty_false);
23393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->current_block()->Finish(instr);
2340592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  empty_true->Goto(if_true(), owner()->function_state()->drop_extra());
2341592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  empty_false->Goto(if_false(), owner()->function_state()->drop_extra());
23423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->set_current_block(NULL);
23433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
23443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
23453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::BuildBranch(HValue* value) {
2347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We expect the graph to be in edge-split form: there is no edge that
2348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // connects a branch node to a join node.  We conservatively ensure that
2349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // property by always adding an empty block on the outgoing edges of this
2350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // branch.
2351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraphBuilder* builder = owner();
23523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
2353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    builder->Bailout("arguments object value in a test context");
2354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
235769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  unsigned test_id = condition()->test_id();
235869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ToBooleanStub::Types expected(builder->oracle()->ToBooleanTypes(test_id));
235969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected);
2360e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  builder->current_block()->Finish(test);
2361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2362592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  empty_true->Goto(if_true(), owner()->function_state()->drop_extra());
2363592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  empty_false->Goto(if_false(), owner()->function_state()->drop_extra());
2364e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  builder->set_current_block(NULL);
2365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// HGraphBuilder infrastructure for bailing out and checking bailouts.
2369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define CHECK_BAILOUT(call)                     \
2370053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  do {                                          \
2371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    call;                                       \
2372053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    if (HasStackOverflow()) return;             \
2373053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  } while (false)
2374053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
2375053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
2376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define CHECK_ALIVE(call)                                       \
2377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  do {                                                          \
2378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    call;                                                       \
2379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (HasStackOverflow() || current_block() == NULL) return;  \
2380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } while (false)
2381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::Bailout(const char* reason) {
2384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_bailout) {
2385589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SmartArrayPointer<char> name(
2386589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        info()->shared_info()->DebugName()->ToCString());
2387e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *name, reason);
2388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetStackOverflow();
2390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForEffect(Expression* expr) {
2394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EffectContext for_effect(this);
2395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Visit(expr);
2396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitForValue(Expression* expr, ArgumentsAllowedFlag flag) {
2400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ValueContext for_value(this, flag);
2401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Visit(expr);
2402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
24058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid HGraphBuilder::VisitForTypeOf(Expression* expr) {
2406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
24078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  for_value.set_for_typeof(true);
24088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Visit(expr);
24098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
24108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
24118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
24128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForControl(Expression* expr,
2414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    HBasicBlock* true_block,
2415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    HBasicBlock* false_block) {
24163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  TestContext for_test(this, expr, true_block, false_block);
2417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Visit(expr);
2418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
24213fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHValue* HGraphBuilder::VisitArgument(Expression* expr) {
24223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  VisitForValue(expr);
24233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (HasStackOverflow() || current_block() == NULL) return NULL;
24243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* value = Pop();
24253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Push(AddInstruction(new(zone()) HPushArgument(value)));
24263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return value;
2427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) {
2431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < arguments->length(); i++) {
2432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitArgument(arguments->at(i)));
2433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) {
2438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < exprs->length(); ++i) {
2439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(exprs->at(i)));
2440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2443e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHGraph* HGraphBuilder::CreateGraph() {
24458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  graph_ = new(zone()) HGraph(info());
244644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info());
2447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
24495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HPhase phase("H_Block building");
245044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    current_block_ = graph()->entry_block();
2451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Scope* scope = info()->scope();
2453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (scope->HasIllegalRedeclaration()) {
2454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Bailout("function with illegal redeclaration");
2455e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      return NULL;
2456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
24575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (scope->calls_eval()) {
24585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      Bailout("function calls eval");
24595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      return NULL;
24605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
2461c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    SetUpScope(scope);
2462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Add an edge to the body entry.  This is warty: the graph's start
2464e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // environment will be used by the Lithium translation as the initial
2465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // environment on graph entry, but it has now been mutated by the
2466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Hydrogen translation of the instructions in the start block.  This
2467e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // environment uses values which have not been defined yet.  These
2468e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Hydrogen instructions will then be replayed by the Lithium
2469e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // translation, so they cannot have an environment effect.  The edge to
2470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // the body's entry block (along with some special logic for the start
2471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // block in HInstruction::InsertAfter) seals the start block from
2472e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // getting unwanted instructions inserted.
2473e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    //
2474e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // TODO(kmillikin): Fix this.  Stop mutating the initial environment.
2475e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Make the Hydrogen instructions in the initial block into Hydrogen
2476e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // values (but not instructions), present in the initial environment and
2477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // not replayed by the Lithium translation.
2478e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HEnvironment* initial_env = environment()->CopyWithoutHistory();
2479e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* body_entry = CreateBasicBlock(initial_env);
2480e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    current_block()->Goto(body_entry);
24818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    body_entry->SetJoinId(AstNode::kFunctionEntryId);
2482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(body_entry);
2483589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2484589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Handle implicit declaration of the function name in named function
2485589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // expressions before other declarations.
2486589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (scope->is_function_scope() && scope->function() != NULL) {
24875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HandleDeclaration(scope->function(), CONST, NULL, NULL);
2488589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
2489589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    VisitDeclarations(scope->declarations());
2490589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    AddSimulate(AstNode::kDeclarationsId);
2491589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2492589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    HValue* context = environment()->LookupContext();
2493589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    AddInstruction(
2494589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry));
2495589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    VisitStatements(info()->function()->body());
2497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (HasStackOverflow()) return NULL;
2498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2499e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (current_block() != NULL) {
25008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined());
2501e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      current_block()->FinishExit(instr);
2502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(NULL);
2503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  graph()->OrderBlocks();
2507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  graph()->AssignDominators();
2508592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2509592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#ifdef DEBUG
2510592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Do a full verify after building the graph and computing dominators.
2511592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  graph()->Verify(true);
2512592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#endif
2513592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
251469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  graph()->PropagateDeoptimizingMark();
2515592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!graph()->CheckConstPhiUses()) {
2516592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Bailout("Unsupported phi use of const variable");
2517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return NULL;
2518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2519592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  graph()->EliminateRedundantPhis();
2520592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!graph()->CheckArgumentsPhiUses()) {
2521592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Bailout("Unsupported phi use of arguments");
2522589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return NULL;
2523589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
2524592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis();
2525592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  graph()->CollectPhis();
2526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
25275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (graph()->has_osr_loop_entry()) {
25285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    const ZoneList<HPhi*>* phis = graph()->osr_loop_entry()->phis();
25295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    for (int j = 0; j < phis->length(); j++) {
25305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HPhi* phi = phis->at(j);
25315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      graph()->osr_values()->at(phi->merged_index())->set_incoming_value(phi);
25325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
25335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
25345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
2535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HInferRepresentation rep(graph());
2536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  rep.Analyze();
2537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
25387d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  graph()->MarkDeoptimizeOnUndefined();
2539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  graph()->InsertRepresentationChanges();
2540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
254169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  graph()->InitializeInferredTypes();
254269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  graph()->Canonicalize();
2543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Perform common subexpression elimination and loop-invariant code motion.
2545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_use_gvn) {
25465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HPhase phase("H_Global value numbering", graph());
2547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HGlobalValueNumberer gvn(graph(), info());
2548592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    bool removed_side_effects = gvn.Analyze();
2549592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Trigger a second analysis pass to further eliminate duplicate values that
2550592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // could only be discovered by removing side-effect-generating instructions
2551592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // during the first pass.
2552592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (FLAG_smi_only_arrays && removed_side_effects) {
25535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      removed_side_effects = gvn.Analyze();
25545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ASSERT(!removed_side_effects);
2555592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
2556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
255869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (FLAG_use_range) {
255969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    HRangeAnalysis rangeAnalysis(graph());
256069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    rangeAnalysis.Analyze();
256169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
256269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  graph()->ComputeMinusZeroChecks();
256369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
256469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Eliminate redundant stack checks on backwards branches.
256569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HStackCheckEliminator sce(graph());
256669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  sce.Process();
256769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
25687d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // Replace the results of check instructions with the original value, if the
25697d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // result is used. This is safe now, since we don't do code motion after this
25707d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // point. It enables better register allocation since the value produced by
25717d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // check instructions is really a copy of the original value.
25727d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  graph()->ReplaceCheckedValues();
25737d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch
2574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return graph();
2575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
25787d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdochvoid HGraph::ReplaceCheckedValues() {
25795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HPhase phase("H_Replace checked values", this);
25807d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  for (int i = 0; i < blocks()->length(); ++i) {
25817d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    HInstruction* instr = blocks()->at(i)->first();
25827d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    while (instr != NULL) {
25837d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch      if (instr->IsBoundsCheck()) {
25847d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch        // Replace all uses of the checked value with the original input.
2585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        ASSERT(instr->UseCount() > 0);
2586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        instr->ReplaceAllUsesWith(HBoundsCheck::cast(instr)->index());
25877d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch      }
25887d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch      instr = instr->next();
25897d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    }
25907d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  }
25917d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch}
25927d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch
25937d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch
2594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
2595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
2596e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->AddInstruction(instr);
2597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
2598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
26013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraphBuilder::AddSimulate(int ast_id) {
2602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
26033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  current_block()->AddSimulate(ast_id);
2604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddPhi(HPhi* instr) {
2608e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
2609e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->AddPhi(instr);
2610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::PushAndAdd(HInstruction* instr) {
2614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Push(instr);
2615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(instr);
2616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
26195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochtemplate <class Instruction>
26205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen MurdochHInstruction* HGraphBuilder::PreProcessCall(Instruction* call) {
26211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int count = call->argument_count();
26221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ZoneList<HValue*> arguments(count);
26231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = 0; i < count; ++i) {
26241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    arguments.Add(Pop());
2625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
26271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  while (!arguments.is_empty()) {
26288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast()));
2629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2630e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return call;
2631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2634c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid HGraphBuilder::SetUpScope(Scope* scope) {
26358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HConstant* undefined_constant = new(zone()) HConstant(
263644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->factory()->undefined_value(), Representation::Tagged());
2637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(undefined_constant);
2638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_->set_undefined_constant(undefined_constant);
2639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
26405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HArgumentsObject* object = new(zone()) HArgumentsObject;
26415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  AddInstruction(object);
26425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  graph()->SetArgumentsObject(object);
26435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
2644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Set the initial values of parameters including "this".  "This" has
2645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // parameter index 0.
2646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count());
2647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < environment()->parameter_count(); ++i) {
26498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* parameter = AddInstruction(new(zone()) HParameter(i));
2650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    environment()->Bind(i, parameter);
2651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // First special is HContext.
2654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HInstruction* context = AddInstruction(new(zone()) HContext);
2655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  environment()->BindContext(context);
2656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Initialize specials and locals to undefined.
2658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = environment()->parameter_count() + 1;
2659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       i < environment()->length();
2660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       ++i) {
2661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    environment()->Bind(i, undefined_constant);
2662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Handle the arguments and arguments shadow variables specially (they do
2665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // not have declarations).
2666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (scope->arguments() != NULL) {
26673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!scope->arguments()->IsStackAllocated()) {
2668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return Bailout("context-allocated arguments");
2669e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
26705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
26715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    environment()->Bind(scope->arguments(),
26725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                        graph()->GetArgumentsObject());
26733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
2674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
2678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < statements->length(); i++) {
2679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(Visit(statements->at(i)));
2680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
2685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* b = graph()->CreateBasicBlock();
2686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  b->SetInitialEnvironment(env);
2687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return b;
2688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2691e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
2692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* header = graph()->CreateBasicBlock();
2693e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
2694e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  header->SetInitialEnvironment(entry_env);
2695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  header->AttachLoopInformation();
2696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return header;
2697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBlock(Block* stmt) {
2701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
270469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (stmt->block_scope() != NULL) {
270569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return Bailout("ScopedBlock");
270669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
2707e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueInfo break_info(stmt);
2708e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  { BreakAndContinueScope push(&break_info, this);
2709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(VisitStatements(stmt->statements()));
2710e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2711e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* break_block = break_info.break_block();
2712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (break_block != NULL) {
2713e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (current_block() != NULL) current_block()->Goto(break_block);
2714e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    break_block->SetJoinId(stmt->ExitId());
2715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(break_block);
2716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
2721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForEffect(stmt->expression());
2725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
2729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitIfStatement(IfStatement* stmt) {
2736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (stmt->condition()->ToBooleanIsTrue()) {
2740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddSimulate(stmt->ThenId());
2741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Visit(stmt->then_statement());
2742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (stmt->condition()->ToBooleanIsFalse()) {
2743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddSimulate(stmt->ElseId());
2744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Visit(stmt->else_statement());
2745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2746e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* cond_true = graph()->CreateBasicBlock();
2747e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* cond_false = graph()->CreateBasicBlock();
2748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false));
2749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (cond_true->HasPredecessor()) {
2751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cond_true->SetJoinId(stmt->ThenId());
2752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      set_current_block(cond_true);
2753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(Visit(stmt->then_statement()));
2754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cond_true = current_block();
2755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
2756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cond_true = NULL;
2757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
2758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (cond_false->HasPredecessor()) {
2760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cond_false->SetJoinId(stmt->ElseId());
2761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      set_current_block(cond_false);
2762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(Visit(stmt->else_statement()));
2763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cond_false = current_block();
2764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
2765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cond_false = NULL;
2766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
2767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
27683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId());
2769e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(join);
2770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::BreakAndContinueScope::Get(
2775e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    BreakableStatement* stmt,
27765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    BreakType type,
27775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    int* drop_extra) {
27785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  *drop_extra = 0;
2779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueScope* current = this;
2780e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while (current != NULL && current->info()->target() != stmt) {
27815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    *drop_extra += current->info()->drop_extra();
2782e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    current = current->next();
2783e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2784e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current != NULL);  // Always found (unless stack is malformed).
27855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
27865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (type == BREAK) {
27875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    *drop_extra += current->info()->drop_extra();
27885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
27895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
2790e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* block = NULL;
2791e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  switch (type) {
2792e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case BREAK:
2793e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      block = current->info()->break_block();
2794e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (block == NULL) {
2795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        block = current->owner()->graph()->CreateBasicBlock();
2796e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        current->info()->set_break_block(block);
2797e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case CONTINUE:
2801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      block = current->info()->continue_block();
2802e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (block == NULL) {
2803e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        block = current->owner()->graph()->CreateBasicBlock();
2804e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        current->info()->set_continue_block(block);
2805e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2806e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2807e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2808e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2809e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return block;
2810e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2811e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2812e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
2814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
28175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int drop_extra = 0;
28185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HBasicBlock* continue_block = break_scope()->Get(stmt->target(),
28195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                                   CONTINUE,
28205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                                   &drop_extra);
28215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Drop(drop_extra);
2822e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Goto(continue_block);
2823e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(NULL);
2824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
2828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
28315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int drop_extra = 0;
28325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HBasicBlock* break_block = break_scope()->Get(stmt->target(),
28335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                                BREAK,
28345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                                &drop_extra);
28355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Drop(drop_extra);
2836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Goto(break_block);
2837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(NULL);
2838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
2842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AstContext* context = call_context();
2846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (context == NULL) {
2847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Not an inlined return, so an actual one.
2848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(stmt->expression()));
2849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* result = environment()->Pop();
28508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    current_block()->FinishExit(new(zone()) HReturn(result));
28515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  } else if (function_state()->is_construct()) {
28525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // Return from an inlined construct call.  In a test context the return
28535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // value will always evaluate to true, in a value context the return value
28545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // needs to be a JSObject.
28555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (context->IsTest()) {
28565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      TestContext* test = TestContext::cast(context);
28575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      CHECK_ALIVE(VisitForEffect(stmt->expression()));
28585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      current_block()->Goto(test->if_true(), function_state()->drop_extra());
28595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    } else if (context->IsEffect()) {
28605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      CHECK_ALIVE(VisitForEffect(stmt->expression()));
28615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      current_block()->Goto(function_return(), function_state()->drop_extra());
28625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    } else {
28635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ASSERT(context->IsValue());
28645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      CHECK_ALIVE(VisitForValue(stmt->expression()));
28655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HValue* return_value = Pop();
28665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HValue* receiver = environment()->Lookup(0);
28675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HHasInstanceTypeAndBranch* typecheck =
28685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          new(zone()) HHasInstanceTypeAndBranch(return_value,
28695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                                FIRST_SPEC_OBJECT_TYPE,
28705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                                LAST_SPEC_OBJECT_TYPE);
28715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
28725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
28735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      typecheck->SetSuccessorAt(0, if_spec_object);
28745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      typecheck->SetSuccessorAt(1, not_spec_object);
28755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      current_block()->Finish(typecheck);
28765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if_spec_object->AddLeaveInlined(return_value,
28775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      function_return(),
28785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      function_state()->drop_extra());
28795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      not_spec_object->AddLeaveInlined(receiver,
28805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       function_return(),
28815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       function_state()->drop_extra());
28825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
2883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Return from an inlined function, visit the subexpression in the
2885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // expression context of the call.
2886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (context->IsTest()) {
2887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TestContext* test = TestContext::cast(context);
2888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VisitForControl(stmt->expression(),
2889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      test->if_true(),
2890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      test->if_false());
289144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else if (context->IsEffect()) {
2892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForEffect(stmt->expression()));
2893592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      current_block()->Goto(function_return(), function_state()->drop_extra());
2894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
289544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(context->IsValue());
2896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(stmt->expression()));
28975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HValue* return_value = Pop();
2898592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      current_block()->AddLeaveInlined(return_value,
2899592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                       function_return(),
2900592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                       function_state()->drop_extra());
2901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
29035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  set_current_block(NULL);
2904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
290769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid HGraphBuilder::VisitWithStatement(WithStatement* stmt) {
2908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
291169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return Bailout("WithStatement");
2912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
2916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
291944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // We only optimize switch statements with smi-literal smi comparisons,
292044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // with a bounded number of clauses.
292144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kCaseClauseLimit = 128;
292244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ZoneList<CaseClause*>* clauses = stmt->cases();
292344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int clause_count = clauses->length();
292444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (clause_count > kCaseClauseLimit) {
2925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Bailout("SwitchStatement: too many clauses");
292644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
292744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2928592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HValue* context = environment()->LookupContext();
2929592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(stmt->tag()));
2931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddSimulate(stmt->EntryId());
293244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HValue* tag_value = Pop();
293344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* first_test_block = current_block();
2934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2935592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  SwitchType switch_type = UNKNOWN_SWITCH;
2936592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2937592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // 1. Extract clause type
293844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < clause_count; ++i) {
2939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CaseClause* clause = clauses->at(i);
2940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (clause->is_default()) continue;
2941592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2942592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (switch_type == UNKNOWN_SWITCH) {
2943592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (clause->label()->IsSmiLiteral()) {
2944592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        switch_type = SMI_SWITCH;
2945592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      } else if (clause->label()->IsStringLiteral()) {
2946592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        switch_type = STRING_SWITCH;
2947592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      } else {
2948592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        return Bailout("SwitchStatement: non-literal switch label");
2949592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
2950592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    } else if ((switch_type == STRING_SWITCH &&
2951592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                !clause->label()->IsStringLiteral()) ||
2952592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch               (switch_type == SMI_SWITCH &&
2953592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                !clause->label()->IsSmiLiteral())) {
2954592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      return Bailout("SwitchStatemnt: mixed label types are not supported");
2955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2956592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
2957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2958592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HUnaryControlInstruction* string_check = NULL;
2959592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HBasicBlock* not_string_block = NULL;
2960592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2961592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Test switch's tag value if all clauses are string literals
2962592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (switch_type == STRING_SWITCH) {
2963592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    string_check = new(zone()) HIsStringAndBranch(tag_value);
2964592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    first_test_block = graph()->CreateBasicBlock();
2965592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    not_string_block = graph()->CreateBasicBlock();
2966592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2967592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    string_check->SetSuccessorAt(0, first_test_block);
2968592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    string_check->SetSuccessorAt(1, not_string_block);
2969592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    current_block()->Finish(string_check);
2970592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2971592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    set_current_block(first_test_block);
2972592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
2973592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2974592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // 2. Build all the tests, with dangling true branches
2975592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  int default_id = AstNode::kNoNumber;
2976592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  for (int i = 0; i < clause_count; ++i) {
2977592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    CaseClause* clause = clauses->at(i);
2978592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (clause->is_default()) {
2979592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      default_id = clause->EntryId();
2980592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      continue;
2981592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
2982592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (switch_type == SMI_SWITCH) {
2983592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      clause->RecordTypeFeedback(oracle());
2984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2986592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Generate a compare and branch.
2987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(clause->label()));
298844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* label_value = Pop();
2989592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
299044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HBasicBlock* next_test_block = graph()->CreateBasicBlock();
2991592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    HBasicBlock* body_block = graph()->CreateBasicBlock();
2992592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2993592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    HControlInstruction* compare;
2994592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2995592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (switch_type == SMI_SWITCH) {
2996592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (!clause->IsSmiCompare()) {
2997592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // Finish with deoptimize and add uses of enviroment values to
2998592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // account for invisible uses.
2999592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
3000592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        set_current_block(NULL);
3001592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        break;
3002592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
3003592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3004592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      HCompareIDAndBranch* compare_ =
3005592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          new(zone()) HCompareIDAndBranch(tag_value,
3006592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                          label_value,
3007592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                          Token::EQ_STRICT);
3008592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      compare_->SetInputRepresentation(Representation::Integer32());
3009592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      compare = compare_;
3010592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    } else {
3011592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      compare = new(zone()) HStringCompareAndBranch(context, tag_value,
3012592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                     label_value,
3013592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                     Token::EQ_STRICT);
3014592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
3015592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
30163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    compare->SetSuccessorAt(0, body_block);
30173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    compare->SetSuccessorAt(1, next_test_block);
30183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    current_block()->Finish(compare);
3019592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
302044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    set_current_block(next_test_block);
302144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
302244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
302344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Save the current block to use for the default or to join with the
302444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // exit.  This block is NULL if we deoptimized.
302544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* last_block = current_block();
302644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3027592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (not_string_block != NULL) {
3028592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    int join_id = (default_id != AstNode::kNoNumber)
3029592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        ? default_id
3030592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        : stmt->ExitId();
3031592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    last_block = CreateJoin(last_block, not_string_block, join_id);
3032592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
3033592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3034592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // 3. Loop over the clauses and the linked list of tests in lockstep,
303544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // translating the clause bodies.
303644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* curr_test_block = first_test_block;
303744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* fall_through_block = NULL;
3038592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
303944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BreakAndContinueInfo break_info(stmt);
304044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  { BreakAndContinueScope push(&break_info, this);
304144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 0; i < clause_count; ++i) {
304244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      CaseClause* clause = clauses->at(i);
304344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
304444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Identify the block where normal (non-fall-through) control flow
304544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // goes to.
304644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HBasicBlock* normal_block = NULL;
3047053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block      if (clause->is_default()) {
3048053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block        if (last_block != NULL) {
3049053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block          normal_block = last_block;
3050053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block          last_block = NULL;  // Cleared to indicate we've handled it.
3051053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block        }
305244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else if (!curr_test_block->end()->IsDeoptimize()) {
305344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        normal_block = curr_test_block->end()->FirstSuccessor();
305444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        curr_test_block = curr_test_block->end()->SecondSuccessor();
305544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
3056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
305744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Identify a block to emit the body into.
305844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (normal_block == NULL) {
305944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (fall_through_block == NULL) {
306044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          // (a) Unreachable.
306144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (clause->is_default()) {
306244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            continue;  // Might still be reachable clause bodies.
306344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
306444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
306544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
306644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
306744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          // (b) Reachable only as fall through.
306844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          set_current_block(fall_through_block);
3069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
307044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else if (fall_through_block == NULL) {
307144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // (c) Reachable only normally.
307244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        set_current_block(normal_block);
3073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
307444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // (d) Reachable both ways.
307544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        HBasicBlock* join = CreateJoin(fall_through_block,
307644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       normal_block,
307744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       clause->EntryId());
307844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        set_current_block(join);
3079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
3080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(VisitStatements(clause->statements()));
308244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      fall_through_block = current_block();
3083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
308644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Create an up-to-3-way join.  Use the break block if it exists since
308744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // it's already a join block.
308844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* break_block = break_info.break_block();
308944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (break_block == NULL) {
309044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    set_current_block(CreateJoin(fall_through_block,
309144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 last_block,
309244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 stmt->ExitId()));
3093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
309444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (fall_through_block != NULL) fall_through_block->Goto(break_block);
309544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (last_block != NULL) last_block->Goto(break_block);
309644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    break_block->SetJoinId(stmt->ExitId());
309744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    set_current_block(break_block);
3098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
310144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
3103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return statement->OsrEntryId() == info()->osr_ast_id();
3104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
31075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochbool HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
31085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (!HasOsrEntryAt(statement)) return false;
3109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
3111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* osr_entry = graph()->CreateBasicBlock();
3112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* true_value = graph()->GetConstantTrue();
31133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry);
3114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Finish(test);
3115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
3117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  non_osr_entry->Goto(loop_predecessor);
3118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(osr_entry);
3120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int osr_entry_id = statement->OsrEntryId();
31215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int first_expression_index = environment()->first_expression_index();
31225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int length = environment()->length();
31235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ZoneList<HUnknownOSRValue*>* osr_values =
31245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      new(zone()) ZoneList<HUnknownOSRValue*>(length);
31255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
31265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  for (int i = 0; i < first_expression_index; ++i) {
3127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue;
3128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AddInstruction(osr_value);
3129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    environment()->Bind(i, osr_value);
31305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    osr_values->Add(osr_value);
31315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
31325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
31335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (first_expression_index != length) {
31345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    environment()->Drop(length - first_expression_index);
31355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    for (int i = first_expression_index; i < length; ++i) {
31365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue;
31375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      AddInstruction(osr_value);
31385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      environment()->Push(osr_value);
31395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      osr_values->Add(osr_value);
31405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
3141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
31435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  graph()->set_osr_values(osr_values);
31445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
3145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  AddSimulate(osr_entry_id);
31468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HOsrEntry(osr_entry_id));
3147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HContext* context = new(zone()) HContext;
3148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AddInstruction(context);
3149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  environment()->BindContext(context);
3150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Goto(loop_predecessor);
3151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  loop_predecessor->SetJoinId(statement->EntryId());
3152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_predecessor);
31535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  return true;
3154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
31573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraphBuilder::VisitLoopBody(IterationStatement* stmt,
31583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  HBasicBlock* loop_entry,
31593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  BreakAndContinueInfo* break_info) {
31603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BreakAndContinueScope push(break_info, this);
31613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AddSimulate(stmt->StackCheckId());
31623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
31633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HStackCheck* stack_check =
31643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch);
31653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AddInstruction(stack_check);
31663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(loop_entry->IsLoopHeader());
31673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  loop_entry->loop_information()->set_stack_check(stack_check);
31683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_BAILOUT(Visit(stmt->body()));
31693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
31703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
31713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
3173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
31775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  bool osr_entry = PreProcessOsrEntry(stmt);
3178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
31793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  current_block()->Goto(loop_entry);
3180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_entry);
31815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
3182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueInfo break_info(stmt);
31843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
3185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* body_exit =
3186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      JoinContinue(stmt, current_block(), break_info.continue_block());
3187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_successor = NULL;
3188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
3189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(body_exit);
3190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // The block for a true condition, the actual predecessor block of the
3191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // back edge.
3192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    body_exit = graph()->CreateBasicBlock();
3193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    loop_successor = graph()->CreateBasicBlock();
3194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
3195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (body_exit->HasPredecessor()) {
3196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      body_exit->SetJoinId(stmt->BackEdgeId());
3197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      body_exit = NULL;
3199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (loop_successor->HasPredecessor()) {
3201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      loop_successor->SetJoinId(stmt->ExitId());
3202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      loop_successor = NULL;
3204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_exit = CreateLoop(stmt,
3207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_entry,
3208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      body_exit,
3209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_successor,
3210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      break_info.break_block());
3211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_exit);
3212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
3216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
32205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  bool osr_entry = PreProcessOsrEntry(stmt);
3221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
32223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  current_block()->Goto(loop_entry);
3223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_entry);
32245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
32255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
3226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // If the condition is constant true, do not generate a branch.
3228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_successor = NULL;
3229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!stmt->cond()->ToBooleanIsTrue()) {
3230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* body_entry = graph()->CreateBasicBlock();
3231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    loop_successor = graph()->CreateBasicBlock();
3232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
3233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (body_entry->HasPredecessor()) {
3234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      body_entry->SetJoinId(stmt->BodyId());
3235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      set_current_block(body_entry);
3236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (loop_successor->HasPredecessor()) {
3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      loop_successor->SetJoinId(stmt->ExitId());
3239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      loop_successor = NULL;
3241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
3243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueInfo break_info(stmt);
3245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (current_block() != NULL) {
32463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
3247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* body_exit =
3249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      JoinContinue(stmt, current_block(), break_info.continue_block());
3250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_exit = CreateLoop(stmt,
3251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_entry,
3252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      body_exit,
3253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_successor,
3254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      break_info.break_block());
3255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_exit);
3256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForStatement(ForStatement* stmt) {
3260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (stmt->init() != NULL) {
3264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(Visit(stmt->init()));
3265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
32675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  bool osr_entry = PreProcessOsrEntry(stmt);
3268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
32693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  current_block()->Goto(loop_entry);
3270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_entry);
32715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
3272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_successor = NULL;
3274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (stmt->cond() != NULL) {
3275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* body_entry = graph()->CreateBasicBlock();
3276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    loop_successor = graph()->CreateBasicBlock();
3277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
3278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (body_entry->HasPredecessor()) {
3279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      body_entry->SetJoinId(stmt->BodyId());
3280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      set_current_block(body_entry);
3281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (loop_successor->HasPredecessor()) {
3283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      loop_successor->SetJoinId(stmt->ExitId());
3284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      loop_successor = NULL;
3286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueInfo break_info(stmt);
3290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (current_block() != NULL) {
32913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
3292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* body_exit =
3294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      JoinContinue(stmt, current_block(), break_info.continue_block());
3295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (stmt->next() != NULL && body_exit != NULL) {
3297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(body_exit);
3298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(Visit(stmt->next()));
3299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    body_exit = current_block();
3300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_exit = CreateLoop(stmt,
3303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_entry,
3304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      body_exit,
3305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_successor,
3306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      break_info.break_block());
3307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_exit);
3308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
3312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
33155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (!FLAG_optimize_for_in) {
33175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return Bailout("ForInStatement optimization is disabled");
33185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
33195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (!oracle()->IsForInFastCase(stmt)) {
33215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return Bailout("ForInStatement is not fast case");
33225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
33235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (!stmt->each()->IsVariableProxy() ||
33255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
33265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return Bailout("ForInStatement with non-local each variable");
33275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
33285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Variable* each_var = stmt->each()->AsVariableProxy()->var();
33305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  CHECK_ALIVE(VisitForValue(stmt->enumerable()));
33325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HValue* enumerable = Top();  // Leave enumerable at the top.
33335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HInstruction* map = AddInstruction(new(zone()) HForInPrepareMap(
33355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      environment()->LookupContext(), enumerable));
33365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  AddSimulate(stmt->PrepareId());
33375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HInstruction* array = AddInstruction(
33395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      new(zone()) HForInCacheArray(
33405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          enumerable,
33415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          map,
33425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          DescriptorArray::kEnumCacheBridgeCacheIndex));
33435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HInstruction* array_length = AddInstruction(
33455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      new(zone()) HFixedArrayBaseLength(array));
33465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HInstruction* start_index = AddInstruction(new(zone()) HConstant(
33485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      Handle<Object>(Smi::FromInt(0)), Representation::Integer32()));
33495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Push(map);
33515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Push(array);
33525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Push(array_length);
33535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Push(start_index);
33545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HInstruction* index_cache = AddInstruction(
33565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      new(zone()) HForInCacheArray(
33575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          enumerable,
33585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          map,
33595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          DescriptorArray::kEnumCacheBridgeIndicesCacheIndex));
33605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HForInCacheArray::cast(array)->set_index_cache(
33615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HForInCacheArray::cast(index_cache));
33625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  bool osr_entry = PreProcessOsrEntry(stmt);
33645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
33655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  current_block()->Goto(loop_entry);
33665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  set_current_block(loop_entry);
33675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
33685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HValue* index = environment()->ExpressionStackAt(0);
33705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HValue* limit = environment()->ExpressionStackAt(1);
33715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // Check that we still have more keys.
33735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HCompareIDAndBranch* compare_index =
33745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      new(zone()) HCompareIDAndBranch(index, limit, Token::LT);
33755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  compare_index->SetInputRepresentation(Representation::Integer32());
33765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HBasicBlock* loop_body = graph()->CreateBasicBlock();
33785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HBasicBlock* loop_successor = graph()->CreateBasicBlock();
33795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  compare_index->SetSuccessorAt(0, loop_body);
33815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  compare_index->SetSuccessorAt(1, loop_successor);
33825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  current_block()->Finish(compare_index);
33835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  set_current_block(loop_successor);
33855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Drop(5);
33865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  set_current_block(loop_body);
33885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HValue* key = AddInstruction(
33905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      new(zone()) HLoadKeyedFastElement(
33915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          environment()->ExpressionStackAt(2),  // Enum cache.
33925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          environment()->ExpressionStackAt(0),  // Iteration index.
33935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          HLoadKeyedFastElement::OMIT_HOLE_CHECK));
33945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
33955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // Check if the expected map still matches that of the enumerable.
33965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // If not just deoptimize.
33975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  AddInstruction(new(zone()) HCheckMapValue(
33985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      environment()->ExpressionStackAt(4),
33995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      environment()->ExpressionStackAt(3)));
34005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
34015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Bind(each_var, key);
34025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
34035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  BreakAndContinueInfo break_info(stmt, 5);
34045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
34055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
34065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HBasicBlock* body_exit =
34075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      JoinContinue(stmt, current_block(), break_info.continue_block());
34085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
34095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (body_exit != NULL) {
34105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    set_current_block(body_exit);
34115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
34125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HValue* current_index = Pop();
34135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HInstruction* new_index = new(zone()) HAdd(environment()->LookupContext(),
34145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                               current_index,
34155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                               graph()->GetConstant1());
34165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    new_index->AssumeRepresentation(Representation::Integer32());
34175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    PushAndAdd(new_index);
34185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    body_exit = current_block();
34195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
34205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
34215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HBasicBlock* loop_exit = CreateLoop(stmt,
34225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      loop_entry,
34235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      body_exit,
34245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      loop_successor,
34255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      break_info.break_block());
34265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
34275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  set_current_block(loop_exit);
3428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
3432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("TryCatchStatement");
3436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
3440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("TryFinallyStatement");
3444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("DebuggerStatement");
34528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
34538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
34548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
34558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic Handle<SharedFunctionInfo> SearchSharedFunctionInfo(
34568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Code* unoptimized_code, FunctionLiteral* expr) {
34578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int start_position = expr->start_position();
34588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  RelocIterator it(unoptimized_code);
34598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  for (;!it.done(); it.next()) {
34608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    RelocInfo* rinfo = it.rinfo();
34618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue;
34628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Object* obj = rinfo->target_object();
34638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (obj->IsSharedFunctionInfo()) {
34648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
34658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (shared->start_position() == start_position) {
34668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        return Handle<SharedFunctionInfo>(shared);
34678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
34688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
34698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
34708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
34718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Handle<SharedFunctionInfo>();
3472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
3476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<SharedFunctionInfo> shared_info =
34808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      SearchSharedFunctionInfo(info()->shared_info()->code(),
34818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                               expr);
34828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (shared_info.is_null()) {
34838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    shared_info = Compiler::BuildFunctionInfo(expr, info()->script());
34848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
3485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We also have a stack overflow if the recursive compilation did.
3486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (HasStackOverflow()) return;
34873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
3488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HFunctionLiteral* instr =
34893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure());
34903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
3491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitSharedFunctionInfoLiteral(
3495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SharedFunctionInfoLiteral* expr) {
3496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("SharedFunctionInfoLiteral");
3500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitConditional(Conditional* expr) {
3504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* cond_true = graph()->CreateBasicBlock();
3508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* cond_false = graph()->CreateBasicBlock();
3509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
3510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
351144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Visit the true and false subexpressions in the same AST context as the
351244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // whole expression.
3513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (cond_true->HasPredecessor()) {
3514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cond_true->SetJoinId(expr->ThenId());
3515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(cond_true);
3516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(Visit(expr->then_expression()));
3517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cond_true = current_block();
3518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cond_true = NULL;
3520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (cond_false->HasPredecessor()) {
3523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cond_false->SetJoinId(expr->ElseId());
3524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(cond_false);
3525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(Visit(expr->else_expression()));
3526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cond_false = current_block();
3527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cond_false = NULL;
3529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
353144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!ast_context()->IsTest()) {
3532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
353344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    set_current_block(join);
3534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (join != NULL && !ast_context()->IsEffect()) {
35353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnValue(Pop());
3536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
353744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
3538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
35418b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochHGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty(
35428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Variable* var, LookupResult* lookup, bool is_store) {
35438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (var->is_this() || !info()->has_global_object()) {
35448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return kUseGeneric;
3545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3546e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<GlobalObject> global(info()->global_object());
3547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  global->Lookup(*var->name(), lookup);
3548c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  if (!lookup->IsFound() ||
35498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      lookup->type() != NORMAL ||
35508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      (is_store && lookup->IsReadOnly()) ||
35518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      lookup->holder() != *global) {
35528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return kUseGeneric;
35531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
35548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
35558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return kUseCell;
35561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
35571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35591e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockHValue* HGraphBuilder::BuildContextChainWalk(Variable* var) {
35601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(var->IsContextSlot());
3561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
3562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int length = info()->scope()->ContextChainLength(var->scope());
35631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  while (length-- > 0) {
3564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HInstruction* context_instruction = new(zone()) HOuterContext(context);
3565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AddInstruction(context_instruction);
3566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    context = context_instruction;
35671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
35681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return context;
3569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
3573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3576589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Variable* variable = expr->var();
3577589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (variable->location()) {
3578589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::UNALLOCATED: {
3579c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      if (variable->mode() == LET || variable->mode() == CONST_HARMONY) {
3580c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        return Bailout("reference to global harmony declared variable");
3581c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      }
3582592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Handle known global constants like 'undefined' specially to avoid a
3583592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // load from a global cell for them.
3584592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Handle<Object> constant_value =
3585592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          isolate()->factory()->GlobalConstantFor(variable->name());
3586592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (!constant_value.is_null()) {
3587592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        HConstant* instr =
3588592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            new(zone()) HConstant(constant_value, Representation::Tagged());
3589592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        return ast_context()->ReturnInstruction(instr, expr->id());
3590592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
3591592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3592592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      LookupResult lookup(isolate());
3593589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      GlobalPropertyAccess type =
3594589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          LookupGlobalProperty(variable, &lookup, false);
3595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3596589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (type == kUseCell &&
3597589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          info()->global_object()->IsAccessCheckNeeded()) {
3598589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        type = kUseGeneric;
3599589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
3600589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3601589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (type == kUseCell) {
3602589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Handle<GlobalObject> global(info()->global_object());
3603589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3604592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        HLoadGlobalCell* instr =
3605592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
3606589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return ast_context()->ReturnInstruction(instr, expr->id());
3607589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else {
3608589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HValue* context = environment()->LookupContext();
3609589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HGlobalObject* global_object = new(zone()) HGlobalObject(context);
3610589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        AddInstruction(global_object);
3611589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HLoadGlobalGeneric* instr =
3612589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            new(zone()) HLoadGlobalGeneric(context,
3613589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                           global_object,
3614589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                           variable->name(),
3615589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                           ast_context()->is_for_typeof());
3616589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        instr->set_position(expr->position());
3617589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return ast_context()->ReturnInstruction(instr, expr->id());
3618589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
36198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
36208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
3621589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::PARAMETER:
3622589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOCAL: {
3623589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      HValue* value = environment()->Lookup(variable);
3624c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      if (value == graph()->GetConstantHole()) {
3625c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        ASSERT(variable->mode() == CONST ||
3626c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch               variable->mode() == CONST_HARMONY ||
3627c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch               variable->mode() == LET);
3628c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        return Bailout("reference to uninitialized variable");
3629589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
3630589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return ast_context()->ReturnValue(value);
3631589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
3632589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3633589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::CONTEXT: {
3634589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      HValue* context = BuildContextChainWalk(variable);
3635c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable);
36363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnInstruction(instr, expr->id());
3637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3638589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3639589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOOKUP:
3640589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return Bailout("reference to a variable which requires dynamic lookup");
3641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitLiteral(Literal* expr) {
3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
36498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HConstant* instr =
36508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HConstant(expr->handle(), Representation::Tagged());
36513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
3652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
3656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
36593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
36603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context,
36623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                     expr->pattern(),
36638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                     expr->flags(),
36648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                     expr->literal_index());
36653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
3666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
36695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch// Determines whether the given array or object literal boilerplate satisfies
36705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch// all limits to be considered for fast deep-copying and computes the total
3671592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch// size of all objects that are part of the graph.
36725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochstatic bool IsFastLiteral(Handle<JSObject> boilerplate,
36735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                          int max_depth,
36745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                          int* max_properties,
36755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                          int* total_size) {
36765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT(max_depth >= 0 && *max_properties >= 0);
36775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (max_depth == 0) return false;
3678592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3679c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  Handle<FixedArrayBase> elements(boilerplate->elements());
3680592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (elements->length() > 0 &&
36815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) {
36825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (boilerplate->HasFastDoubleElements()) {
36835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      *total_size += FixedDoubleArray::SizeFor(elements->length());
36845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    } else if (boilerplate->HasFastElements()) {
36855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      int length = elements->length();
36865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      for (int i = 0; i < length; i++) {
36875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if ((*max_properties)-- == 0) return false;
36885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        Handle<Object> value = JSObject::GetElement(boilerplate, i);
36895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (value->IsJSObject()) {
36905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          Handle<JSObject> value_object = Handle<JSObject>::cast(value);
36915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          if (!IsFastLiteral(value_object,
36925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             max_depth - 1,
36935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             max_properties,
36945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             total_size)) {
36955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            return false;
36965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          }
36975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        }
36985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
36995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      *total_size += FixedArray::SizeFor(length);
37005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    } else {
37015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      return false;
37025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
3703592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
3704592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3705c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  Handle<FixedArray> properties(boilerplate->properties());
3706592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (properties->length() > 0) {
3707592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return false;
3708592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  } else {
3709592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    int nof = boilerplate->map()->inobject_properties();
3710592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    for (int i = 0; i < nof; i++) {
37115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if ((*max_properties)-- == 0) return false;
3712592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Handle<Object> value(boilerplate->InObjectPropertyAt(i));
3713592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (value->IsJSObject()) {
3714592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        Handle<JSObject> value_object = Handle<JSObject>::cast(value);
37155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (!IsFastLiteral(value_object,
37165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                           max_depth - 1,
37175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                           max_properties,
37185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                           total_size)) {
3719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          return false;
3720592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        }
3721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
3722592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
3723592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
3724592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3725592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  *total_size += boilerplate->map()->instance_size();
3726592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return true;
3727592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
3728592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3729592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
3731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3734592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<JSFunction> closure = function_state()->compilation_info()->closure();
3735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
3736592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HInstruction* literal;
3737592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3738592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Check whether to use fast or slow deep-copying for boilerplate.
3739592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  int total_size = 0;
37405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int max_properties = HFastLiteral::kMaxLiteralProperties;
3741592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<Object> boilerplate(closure->literals()->get(expr->literal_index()));
3742592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (boilerplate->IsJSObject() &&
37435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      IsFastLiteral(Handle<JSObject>::cast(boilerplate),
37445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                    HFastLiteral::kMaxLiteralDepth,
37455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                    &max_properties,
37465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                    &total_size)) {
3747592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate);
37485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    literal = new(zone()) HFastLiteral(context,
37495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       boilerplate_object,
37505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       total_size,
37515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       expr->literal_index(),
37525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       expr->depth());
3753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  } else {
37545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    literal = new(zone()) HObjectLiteral(context,
37555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                         expr->constant_properties(),
37565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                         expr->fast_elements(),
37575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                         expr->literal_index(),
37585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                         expr->depth(),
37595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                         expr->has_function());
3760592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
3761592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The object is expected in the bailout environment during computation
3763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // of the property values and is the value of the entire expression.
3764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushAndAdd(literal);
3765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->CalculateEmitStore();
3767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < expr->properties()->length(); i++) {
3769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ObjectLiteral::Property* property = expr->properties()->at(i);
3770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (property->IsCompileTimeValue()) continue;
3771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Literal* key = property->key();
3773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Expression* value = property->value();
3774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    switch (property->kind()) {
3776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
3777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
3778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Fall through.
3779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::COMPUTED:
3780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (key->handle()->IsSymbol()) {
3781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (property->emit_store()) {
37825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            property->RecordTypeFeedback(oracle());
3783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            CHECK_ALIVE(VisitForValue(value));
3784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HValue* value = Pop();
37855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            HInstruction* store = BuildStoreNamed(literal, value, property);
37861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            AddInstruction(store);
37875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            if (store->HasObservableSideEffects()) AddSimulate(key->id());
3788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else {
3789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            CHECK_ALIVE(VisitForEffect(value));
3790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
3791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          break;
3792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
3793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Fall through.
3794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::PROTOTYPE:
3795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::SETTER:
3796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::GETTER:
3797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return Bailout("Object literal with complex property");
3798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      default: UNREACHABLE();
3799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
380144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
380244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (expr->has_function()) {
380344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Return the result of the transformation to fast properties
380444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // instead of the original since this operation changes the map
380544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // of the object. This makes sure that the original object won't
380644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // be used by other optimized code before it is transformed
380744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // (e.g. because of code motion).
38088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HToFastProperties* result = new(zone()) HToFastProperties(Pop());
380944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AddInstruction(result);
38103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnValue(result);
381144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
38123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnValue(Pop());
381344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
3814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
3818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<Expression*>* subexprs = expr->values();
3822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = subexprs->length();
38233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
38245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HInstruction* literal;
3825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3826c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  Handle<FixedArray> literals(environment()->closure()->literals());
3827c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  Handle<Object> raw_boilerplate(literals->get(expr->literal_index()));
3828c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
3829c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  if (raw_boilerplate->IsUndefined()) {
3830c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate(
3831c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        isolate(), literals, expr->constant_elements());
3832c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    if (raw_boilerplate.is_null()) {
3833c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      return Bailout("array boilerplate creation failed");
3834c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    }
3835c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    literals->set(expr->literal_index(), *raw_boilerplate);
3836c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    if (JSObject::cast(*raw_boilerplate)->elements()->map() ==
3837c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        isolate()->heap()->fixed_cow_array_map()) {
3838c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      isolate()->counters()->cow_arrays_created_runtime()->Increment();
3839c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    }
3840c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
3841c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
3842c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  Handle<JSObject> boilerplate = Handle<JSObject>::cast(raw_boilerplate);
3843c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  ElementsKind boilerplate_elements_kind =
3844c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        Handle<JSObject>::cast(boilerplate)->GetElementsKind();
3845c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
38465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // Check whether to use fast or slow deep-copying for boilerplate.
38475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int total_size = 0;
38485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int max_properties = HFastLiteral::kMaxLiteralProperties;
38495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (IsFastLiteral(boilerplate,
38505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                    HFastLiteral::kMaxLiteralDepth,
38515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                    &max_properties,
38525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                    &total_size)) {
38535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    literal = new(zone()) HFastLiteral(context,
38545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       boilerplate,
38555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       total_size,
38565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       expr->literal_index(),
38575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       expr->depth());
38585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  } else {
38595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    literal = new(zone()) HArrayLiteral(context,
38605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                        boilerplate,
38615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                        length,
38625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                        expr->literal_index(),
38635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                        expr->depth());
38645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
3865c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
3866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The array is expected in the bailout environment during computation
3867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // of the property values and is the value of the entire expression.
3868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushAndAdd(literal);
3869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HLoadElements* elements = NULL;
3871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; i++) {
3873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Expression* subexpr = subexprs->at(i);
3874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // If the subexpression is a literal or a simple materialized literal it
3875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // is already set in the cloned array.
3876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
3877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(subexpr));
3879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = Pop();
3880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal");
3881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3882592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    elements = new(zone()) HLoadElements(literal);
3883592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    AddInstruction(elements);
3884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
38858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HValue* key = AddInstruction(
38868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)),
38878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                              Representation::Integer32()));
3888592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3889c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    switch (boilerplate_elements_kind) {
3890c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      case FAST_SMI_ONLY_ELEMENTS:
3891c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        // Smi-only arrays need a smi check.
3892c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        AddInstruction(new(zone()) HCheckSmi(value));
3893c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        // Fall through.
3894c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      case FAST_ELEMENTS:
3895c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        AddInstruction(new(zone()) HStoreKeyedFastElement(
3896c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            elements,
3897c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            key,
3898c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            value,
3899c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            boilerplate_elements_kind));
3900c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        break;
3901c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      case FAST_DOUBLE_ELEMENTS:
3902c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        AddInstruction(new(zone()) HStoreKeyedFastDoubleElement(elements,
3903c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                                                key,
3904c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                                                value));
3905c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        break;
3906c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      default:
3907c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        UNREACHABLE();
3908c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        break;
3909c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    }
3910592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddSimulate(expr->GetIdForElement(i));
3912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
39133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnValue(Pop());
3914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Sets the lookup result and returns true if the store can be inlined.
3918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool ComputeStoredField(Handle<Map> type,
3919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               Handle<String> name,
3920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               LookupResult* lookup) {
3921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  type->LookupInDescriptors(NULL, *name, lookup);
3922c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  if (!lookup->IsFound()) return false;
3923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup->type() == FIELD) return true;
3924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return (lookup->type() == MAP_TRANSITION) &&
3925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      (type->unused_property_fields() > 0);
3926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic int ComputeStoredFieldIndex(Handle<Map> type,
3930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                   Handle<String> name,
3931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                   LookupResult* lookup) {
3932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(lookup->type() == FIELD || lookup->type() == MAP_TRANSITION);
3933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup->type() == FIELD) {
3934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return lookup->GetLocalFieldIndexFromMap(*type);
3935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Map* transition = lookup->GetTransitionMapFromMap(*type);
3937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return transition->PropertyIndexFor(*name) - type->inobject_properties();
3938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
3943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  Handle<String> name,
3944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  HValue* value,
3945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  Handle<Map> type,
3946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  LookupResult* lookup,
3947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  bool smi_and_map_check) {
3948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (smi_and_map_check) {
39498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(object));
3950c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    AddInstruction(new(zone()) HCheckMap(object, type, NULL,
3951c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                         ALLOW_ELEMENT_TRANSITION_MAPS));
3952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = ComputeStoredFieldIndex(type, name, lookup);
3955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_in_object = index < 0;
3956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int offset = index * kPointerSize;
3957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (index < 0) {
3958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Negative property indices are in-object properties, indexed
3959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // from the end of the fixed part of the object.
3960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset += type->instance_size();
3961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset += FixedArray::kHeaderSize;
3963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HStoreNamedField* instr =
39658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HStoreNamedField(object, name, value, is_in_object, offset);
3966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup->type() == MAP_TRANSITION) {
3967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Map> transition(lookup->GetTransitionMapFromMap(*type));
3968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_transition(transition);
3969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // TODO(fschneider): Record the new map type of the object in the IR to
3970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // enable elimination of redundant checks after the transition store.
3971c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    instr->SetGVNFlag(kChangesMaps);
3972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
3974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
3978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    Handle<String> name,
3979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    HValue* value) {
3980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
39818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HStoreNamedGeneric(
39828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         context,
39838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         object,
39848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         name,
39858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         value,
3986592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                         function_strict_mode_flag());
3987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
3991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             HValue* value,
39925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                             ObjectLiteral::Property* prop) {
39935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Literal* key = prop->key()->AsLiteral();
39945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Handle<String> name = Handle<String>::cast(key->handle());
39955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT(!name.is_null());
39965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
39975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  LookupResult lookup(isolate());
39985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Handle<Map> type = prop->GetReceiverType();
39995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  bool is_monomorphic = prop->IsMonomorphic() &&
40005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ComputeStoredField(type, name, &lookup);
40015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
40025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  return is_monomorphic
40035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ? BuildStoreNamedField(object, name, value, type, &lookup,
40045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             true)  // Needs smi and map check.
40055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : BuildStoreNamedGeneric(object, name, value);
40065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
40075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
40085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
40095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen MurdochHInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
40105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                             HValue* value,
4011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             Expression* expr) {
4012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = (expr->AsProperty() != NULL)
4013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ? expr->AsProperty()
4014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : expr->AsAssignment()->target()->AsProperty();
4015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Literal* key = prop->key()->AsLiteral();
4016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<String> name = Handle<String>::cast(key->handle());
4017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!name.is_null());
4018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4019592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  LookupResult lookup(isolate());
402069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  SmallMapList* types = expr->GetReceiverTypes();
4021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_monomorphic = expr->IsMonomorphic() &&
4022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ComputeStoredField(types->first(), name, &lookup);
4023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return is_monomorphic
4025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ? BuildStoreNamedField(object, name, value, types->first(), &lookup,
4026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             true)  // Needs smi and map check.
4027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : BuildStoreNamedGeneric(object, name, value);
4028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
4032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     HValue* object,
4033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     HValue* value,
403469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                                     SmallMapList* types,
4035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Handle<String> name) {
4036e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // TODO(ager): We should recognize when the prototype chains for different
4037e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // maps are identical. In that case we can avoid repeatedly generating the
4038e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // same prototype map checks.
4039e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int count = 0;
4040e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* join = NULL;
4041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
4042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Map> map = types->at(i);
4043592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    LookupResult lookup(isolate());
4044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (ComputeStoredField(map, name, &lookup)) {
4045e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (count == 0) {
40468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckNonSmi(object));  // Only needed once.
4047e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        join = graph()->CreateBasicBlock();
4048e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
4049e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ++count;
4050e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* if_true = graph()->CreateBasicBlock();
4051e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* if_false = graph()->CreateBasicBlock();
40528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HCompareMap* compare =
40538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          new(zone()) HCompareMap(object, map, if_true, if_false);
4054e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      current_block()->Finish(compare);
4055e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4056e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(if_true);
4057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instr =
4058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          BuildStoreNamedField(object, name, value, map, &lookup, false);
4059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr->set_position(expr->position());
4060e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Goto will add the HSimulate for the store.
4061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(instr);
4062e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (!ast_context()->IsEffect()) Push(value);
4063e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      current_block()->Goto(join);
4064e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4065e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(if_false);
4066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4069e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Finish up.  Unconditionally deoptimize if we've handled all the maps we
4070e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // know about and do not want to handle ones we've never seen.  Otherwise
4071e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // use a generic IC.
4072e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
4073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
4074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
40751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
4076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_position(expr->position());
4077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(instr);
4078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4079e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (join != NULL) {
4080e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (!ast_context()->IsEffect()) Push(value);
4081e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      current_block()->Goto(join);
4082e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
4083e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // The HSimulate for the store should not see the stored value in
4084e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // effect contexts (it is not materialized at expr->id() in the
4085e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // unoptimized code).
4086592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (instr->HasObservableSideEffects()) {
4087e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (ast_context()->IsEffect()) {
4088e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          AddSimulate(expr->id());
4089e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else {
4090e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          Push(value);
4091e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          AddSimulate(expr->id());
4092e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          Drop(1);
4093e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
4094e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
40953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnValue(value);
40969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
4097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(join != NULL);
4100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  join->SetJoinId(expr->id());
4101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(join);
41023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
4103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
4107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = expr->target()->AsProperty();
4108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(prop != NULL);
4109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->RecordTypeFeedback(oracle());
4110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(prop->obj()));
4111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = NULL;
4113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = NULL;
4114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (prop->key()->IsPropertyName()) {
4116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Named store.
4117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->value()));
4118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    value = Pop();
4119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* object = Pop();
4120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Literal* key = prop->key()->AsLiteral();
4122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = Handle<String>::cast(key->handle());
4123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!name.is_null());
4124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
412569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    SmallMapList* types = expr->GetReceiverTypes();
4126592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    LookupResult lookup(isolate());
4127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (expr->IsMonomorphic()) {
4129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = BuildStoreNamed(object, value, expr);
4130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (types != NULL && types->length() > 1) {
4132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandlePolymorphicStoreNamedField(expr, object, value, types, name);
4133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
4134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
41361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      instr = BuildStoreNamedGeneric(object, name, value);
4137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Keyed store.
4141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(prop->key()));
4142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->value()));
4143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    value = Pop();
4144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* key = Pop();
4145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* object = Pop();
41463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool has_side_effects = false;
41473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(),
41483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             expr->position(),
41493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             true,  // is_store
41503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             &has_side_effects);
41513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Push(value);
41523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(has_side_effects);  // Stores always have side effects.
41533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddSimulate(expr->AssignmentId());
41543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnValue(Pop());
4155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Push(value);
4157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(expr->position());
4158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(instr);
4159592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (instr->HasObservableSideEffects()) AddSimulate(expr->AssignmentId());
41603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnValue(Pop());
4161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Because not every expression has a position and there is not common
4165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// superclass of Assignment and CountOperation, we cannot just pass the
4166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// owning expression instead of position and ast_id separately.
4167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
4168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   HValue* value,
4169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   int position,
4170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   int ast_id) {
4171592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  LookupResult lookup(isolate());
41728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
41738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (type == kUseCell) {
41748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Handle<GlobalObject> global(info()->global_object());
41758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
4176592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    HInstruction* instr =
4177592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails());
41788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr->set_position(position);
41798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(instr);
4180592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (instr->HasObservableSideEffects()) AddSimulate(ast_id);
41818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
4182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HValue* context =  environment()->LookupContext();
41838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HGlobalObject* global_object = new(zone()) HGlobalObject(context);
41848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(global_object);
41858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HStoreGlobalGeneric* instr =
41868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        new(zone()) HStoreGlobalGeneric(context,
41878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                        global_object,
41888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                        var->name(),
41898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                        value,
4190592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        function_strict_mode_flag());
41918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr->set_position(position);
41928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(instr);
4193592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ASSERT(instr->HasObservableSideEffects());
4194592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (instr->HasObservableSideEffects()) AddSimulate(ast_id);
41958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
4196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
4200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Expression* target = expr->target();
4201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = target->AsVariableProxy();
4202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = target->AsProperty();
4203589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(proxy == NULL || prop == NULL);
4204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We have a second position recorded in the FullCodeGenerator to have
4206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // type feedback for the binary operation.
4207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BinaryOperation* operation = expr->binary_operation();
4208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4209589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (proxy != NULL) {
4210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Variable* var = proxy->var();
4211c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    if (var->mode() == LET)  {
4212c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      return Bailout("unsupported let compound assignment");
42133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
42143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(operation));
4216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4217589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    switch (var->location()) {
4218589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::UNALLOCATED:
4219589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HandleGlobalVariableAssignment(var,
4220589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       Top(),
4221589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       expr->position(),
4222589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       expr->AssignmentId());
4223589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        break;
4224589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4225589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::PARAMETER:
4226589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::LOCAL:
4227c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        if (var->mode() == CONST)  {
4228c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          return Bailout("unsupported const compound assignment");
4229c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        }
4230589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Bind(var, Top());
4231589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        break;
4232589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4233589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::CONTEXT: {
4234589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // Bail out if we try to mutate a parameter value in a function
4235589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // using the arguments object.  We do not (yet) correctly handle the
4236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // arguments property of the function.
4237589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (info()->scope()->arguments() != NULL) {
4238589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // Parameters will be allocated to context slots.  We have no
4239589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // direct way to detect that the variable is a parameter so we do
4240589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // a linear search of the parameter variables.
4241589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          int count = info()->scope()->num_parameters();
4242589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          for (int i = 0; i < count; ++i) {
4243589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            if (var == info()->scope()->parameter(i)) {
4244589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch              Bailout(
4245589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                  "assignment to parameter, function uses arguments object");
4246589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            }
42473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          }
42483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
4249589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4250c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        HStoreContextSlot::Mode mode;
4251c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4252c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        switch (var->mode()) {
4253c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          case LET:
4254c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            mode = HStoreContextSlot::kCheckDeoptimize;
4255c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            break;
4256c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          case CONST:
4257c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            return ast_context()->ReturnValue(Pop());
4258c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          case CONST_HARMONY:
4259c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            // This case is checked statically so no need to
4260c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            // perform checks here
4261c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            UNREACHABLE();
4262c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          default:
4263c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            mode = HStoreContextSlot::kNoCheck;
4264c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        }
4265c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4266589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HValue* context = BuildContextChainWalk(var);
4267589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HStoreContextSlot* instr =
4268c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            new(zone()) HStoreContextSlot(context, var->index(), mode, Top());
4269589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        AddInstruction(instr);
4270592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        if (instr->HasObservableSideEffects()) {
4271592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          AddSimulate(expr->AssignmentId());
4272592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        }
4273589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        break;
42743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
42753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4276589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::LOOKUP:
4277589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return Bailout("compound assignment to lookup slot");
4278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
42793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnValue(Pop());
4280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (prop != NULL) {
4282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    prop->RecordTypeFeedback(oracle());
4283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (prop->key()->IsPropertyName()) {
4285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Named property.
4286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->obj()));
4287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = Top();
4288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* load = NULL;
4290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (prop->IsMonomorphic()) {
4291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<Map> map = prop->GetReceiverTypes()->first();
4293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamed(obj, prop, map, name);
4294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
4295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamedGeneric(obj, prop);
4296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
4297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(load);
4298592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (load->HasObservableSideEffects()) AddSimulate(expr->CompoundLoadId());
4299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(expr->value()));
4301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* right = Pop();
4302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* left = Pop();
4303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instr = BuildBinaryOperation(operation, left, right);
4305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(instr);
4306592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (instr->HasObservableSideEffects()) AddSimulate(operation->id());
4307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* store = BuildStoreNamed(obj, instr, prop);
4309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(store);
4310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Drop the simulated receiver and value.  Return the value.
4311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(2);
4312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(instr);
4313592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId());
43143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnValue(Pop());
4315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
4317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Keyed property.
4318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->obj()));
4319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->key()));
4320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = environment()->ExpressionStackAt(1);
4321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* key = environment()->ExpressionStackAt(0);
4322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
43233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bool has_side_effects = false;
43243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HValue* load = HandleKeyedElementAccess(
43253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          obj, key, NULL, prop, expr->CompoundLoadId(), RelocInfo::kNoPosition,
43263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          false,  // is_store
43273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          &has_side_effects);
43283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Push(load);
43293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (has_side_effects) AddSimulate(expr->CompoundLoadId());
43303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(expr->value()));
4333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* right = Pop();
4334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* left = Pop();
4335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instr = BuildBinaryOperation(operation, left, right);
4337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(instr);
4338592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (instr->HasObservableSideEffects()) AddSimulate(operation->id());
4339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
43408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      expr->RecordTypeFeedback(oracle());
43413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(),
43423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               RelocInfo::kNoPosition,
43433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               true,  // is_store
43443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               &has_side_effects);
43453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Drop the simulated receiver, key, and value.  Return the value.
4347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(3);
4348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(instr);
43493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(has_side_effects);  // Stores always have side effects.
43503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      AddSimulate(expr->AssignmentId());
43513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnValue(Pop());
4352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Bailout("invalid lhs in compound assignment");
4356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitAssignment(Assignment* expr) {
4361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
4362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
4363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
4364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = expr->target()->AsVariableProxy();
4365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = expr->target()->AsProperty();
4366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(proxy == NULL || prop == NULL);
4367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->is_compound()) {
4369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HandleCompoundAssignment(expr);
4370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
4371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4373589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (prop != NULL) {
4374589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    HandlePropertyAssignment(expr);
4375589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL) {
4376589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Variable* var = proxy->var();
4377c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4378592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (var->mode() == CONST) {
43793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (expr->op() != Token::INIT_CONST) {
4380c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        CHECK_ALIVE(VisitForValue(expr->value()));
4381c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        return ast_context()->ReturnValue(Pop());
4382c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      }
4383c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4384c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      if (var->IsStackAllocated()) {
4385c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        // We insert a use of the old value to detect unsupported uses of const
4386c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        // variables (e.g. initialization inside a loop).
4387c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        HValue* old_value = environment()->Lookup(var);
4388c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        AddInstruction(new HUseConst(old_value));
43893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
4390c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    } else if (var->mode() == CONST_HARMONY) {
4391c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      if (expr->op() != Token::INIT_CONST_HARMONY) {
4392c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        return Bailout("non-initializer assignment to const");
43933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
43943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
43953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (proxy->IsArguments()) return Bailout("assignment to arguments");
4397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Handle the assignment.
4399589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    switch (var->location()) {
4400589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::UNALLOCATED:
4401589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        CHECK_ALIVE(VisitForValue(expr->value()));
4402589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HandleGlobalVariableAssignment(var,
4403589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       Top(),
4404589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       expr->position(),
4405589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       expr->AssignmentId());
4406589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return ast_context()->ReturnValue(Pop());
4407589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4408589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::PARAMETER:
4409589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::LOCAL: {
4410c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        // Perform an initialization check for let declared variables
4411c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        // or parameters.
4412c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        if (var->mode() == LET && expr->op() == Token::ASSIGN) {
4413c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          HValue* env_value = environment()->Lookup(var);
4414c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          if (env_value == graph()->GetConstantHole()) {
4415c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            return Bailout("assignment to let variable before initialization");
4416c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          }
4417c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        }
4418589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // We do not allow the arguments object to occur in a context where it
4419589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // may escape, but assignments to stack-allocated locals are
4420589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // permitted.
4421589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
4422589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HValue* value = Pop();
4423589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Bind(var, value);
4424589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return ast_context()->ReturnValue(value);
4425589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
44263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::CONTEXT: {
4428589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // Bail out if we try to mutate a parameter value in a function using
4429589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // the arguments object.  We do not (yet) correctly handle the
4430589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // arguments property of the function.
4431589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (info()->scope()->arguments() != NULL) {
4432589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // Parameters will rewrite to context slots.  We have no direct way
4433589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // to detect that the variable is a parameter.
4434589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          int count = info()->scope()->num_parameters();
4435589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          for (int i = 0; i < count; ++i) {
4436589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            if (var == info()->scope()->parameter(i)) {
4437589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch              return Bailout("assignment to parameter in arguments object");
4438589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            }
44393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          }
44403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
44411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4442589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        CHECK_ALIVE(VisitForValue(expr->value()));
4443c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        HStoreContextSlot::Mode mode;
4444c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        if (expr->op() == Token::ASSIGN) {
4445c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          switch (var->mode()) {
4446c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            case LET:
4447c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch              mode = HStoreContextSlot::kCheckDeoptimize;
4448c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch              break;
4449c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            case CONST:
4450c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch              return ast_context()->ReturnValue(Pop());
4451c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            case CONST_HARMONY:
4452c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch              // This case is checked statically so no need to
4453c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch              // perform checks here
4454c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch              UNREACHABLE();
4455c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            default:
4456c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch              mode = HStoreContextSlot::kNoCheck;
4457c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          }
4458c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        } else if (expr->op() == Token::INIT_VAR ||
4459c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                   expr->op() == Token::INIT_LET ||
4460c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                   expr->op() == Token::INIT_CONST_HARMONY) {
4461c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          mode = HStoreContextSlot::kNoCheck;
4462c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        } else {
4463c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          ASSERT(expr->op() == Token::INIT_CONST);
4464c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4465c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          mode = HStoreContextSlot::kCheckIgnoreAssignment;
4466c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        }
4467c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
4468589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HValue* context = BuildContextChainWalk(var);
4469c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        HStoreContextSlot* instr = new(zone()) HStoreContextSlot(
4470c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            context, var->index(), mode, Top());
4471589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        AddInstruction(instr);
4472592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        if (instr->HasObservableSideEffects()) {
4473592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          AddSimulate(expr->AssignmentId());
4474592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        }
4475589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return ast_context()->ReturnValue(Pop());
4476589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
44771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4478589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::LOOKUP:
4479589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return Bailout("assignment to LOOKUP variable");
4480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Bailout("invalid left-hand side in assignment");
4483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThrow(Throw* expr) {
4488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
4489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
4490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
4491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We don't optimize functions with invalid left-hand sides in
4492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // assignments, count operations, or for-in.  Consequently throw can
4493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // currently only occur in an effect context.
4494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(ast_context()->IsEffect());
4495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->exception()));
4496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
44973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
4498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = environment()->Pop();
44993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HThrow* instr = new(zone()) HThrow(context, value);
4500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(expr->position());
45011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(instr);
45021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddSimulate(expr->id());
45038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  current_block()->FinishExit(new(zone()) HAbnormalExit);
4504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(NULL);
4505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
4509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    Property* expr,
4510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    Handle<Map> type,
4511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    LookupResult* lookup,
4512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    bool smi_and_map_check) {
4513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (smi_and_map_check) {
45148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(object));
4515c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    AddInstruction(new(zone()) HCheckMap(object, type, NULL,
4516c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                         ALLOW_ELEMENT_TRANSITION_MAPS));
4517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = lookup->GetLocalFieldIndexFromMap(*type);
4520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (index < 0) {
4521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Negative property indices are in-object properties, indexed
4522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // from the end of the fixed part of the object.
4523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int offset = (index * kPointerSize) + type->instance_size();
45248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return new(zone()) HLoadNamedField(object, true, offset);
4525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Non-negative property indices are in the properties array.
4527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
45288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return new(zone()) HLoadNamedField(object, false, offset);
4529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj,
4534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   Property* expr) {
45355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (expr->IsUninitialized() && !FLAG_always_opt) {
45365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    AddInstruction(new(zone()) HSoftDeoptimize);
45375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    current_block()->MarkAsDeoptimizing();
45385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
4539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(expr->key()->IsPropertyName());
4540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Object> name = expr->key()->AsLiteral()->handle();
4541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
45428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HLoadNamedGeneric(context, obj, name);
4543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj,
4547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            Property* expr,
4548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            Handle<Map> map,
4549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            Handle<String> name) {
4550592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  LookupResult lookup(isolate());
4551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  map->LookupInDescriptors(NULL, *name, &lookup);
4552c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  if (lookup.IsFound() && lookup.type() == FIELD) {
4553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return BuildLoadNamedField(obj,
4554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               expr,
4555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               map,
4556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               &lookup,
4557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               true);
4558c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  } else if (lookup.IsFound() && lookup.type() == CONSTANT_FUNCTION) {
45598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(obj));
4560c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    AddInstruction(new(zone()) HCheckMap(obj, map, NULL,
4561c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                         ALLOW_ELEMENT_TRANSITION_MAPS));
4562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map));
45638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return new(zone()) HConstant(function, Representation::Tagged());
4564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return BuildLoadNamedGeneric(obj, expr);
4566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
4571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   HValue* key) {
4572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
45738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HLoadKeyedGeneric(context, object, key);
4574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
45773fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHInstruction* HGraphBuilder::BuildExternalArrayElementAccess(
45783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HValue* external_elements,
45793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HValue* checked_key,
45803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HValue* val,
4581589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind,
45823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool is_store) {
45833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (is_store) {
45843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(val != NULL);
45853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    switch (elements_kind) {
4586589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_PIXEL_ELEMENTS: {
45875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        val = AddInstruction(new(zone()) HClampToUint8(val));
45883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
45893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
4590589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_BYTE_ELEMENTS:
4591589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4592589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_SHORT_ELEMENTS:
4593589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4594589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_INT_ELEMENTS:
4595589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
45965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (!val->representation().IsInteger32()) {
45975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          val = AddInstruction(new(zone()) HChange(
45985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch              val,
45995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch              Representation::Integer32(),
46005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch              true,  // Truncate to int32.
46015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch              false));  // Don't deoptimize undefined (irrelevant here).
46025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        }
46033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
46043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
4605589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_FLOAT_ELEMENTS:
4606589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_DOUBLE_ELEMENTS:
46073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
4608592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      case FAST_SMI_ONLY_ELEMENTS:
4609589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case FAST_ELEMENTS:
4610589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case FAST_DOUBLE_ELEMENTS:
4611589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case DICTIONARY_ELEMENTS:
4612589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case NON_STRICT_ARGUMENTS_ELEMENTS:
46133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        UNREACHABLE();
46143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
46153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
46163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return new(zone()) HStoreKeyedSpecializedArrayElement(
46173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        external_elements, checked_key, val, elements_kind);
46183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
46195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ASSERT(val == NULL);
46203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return new(zone()) HLoadKeyedSpecializedArrayElement(
46213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        external_elements, checked_key, elements_kind);
46223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
46233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
46243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
46253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4626592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements,
4627592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                    HValue* checked_key,
4628592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                    HValue* val,
4629592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                    ElementsKind elements_kind,
4630592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                    bool is_store) {
4631592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (is_store) {
4632592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ASSERT(val != NULL);
4633c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    switch (elements_kind) {
4634c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      case FAST_DOUBLE_ELEMENTS:
4635c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        return new(zone()) HStoreKeyedFastDoubleElement(
4636c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            elements, checked_key, val);
4637c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      case FAST_SMI_ONLY_ELEMENTS:
4638c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        // Smi-only arrays need a smi check.
4639c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        AddInstruction(new(zone()) HCheckSmi(val));
4640c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        // Fall through.
4641c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      case FAST_ELEMENTS:
4642c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        return new(zone()) HStoreKeyedFastElement(
4643c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            elements, checked_key, val, elements_kind);
4644c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      default:
4645c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        UNREACHABLE();
4646c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        return NULL;
4647592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
4648592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
4649592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // It's an element load (!is_store).
4650592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (elements_kind == FAST_DOUBLE_ELEMENTS) {
4651592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key);
4652592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  } else {  // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS.
4653592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return new(zone()) HLoadKeyedFastElement(elements, checked_key);
4654592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
4655592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
4656592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4657592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
46583fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
46593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                           HValue* key,
46603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                           HValue* val,
4661592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                           Handle<Map> map,
46623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                           bool is_store) {
4663592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map));
4664592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  bool fast_smi_only_elements = map->has_fast_smi_only_elements();
4665592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  bool fast_elements = map->has_fast_elements();
466669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
4667592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (is_store && (fast_elements || fast_smi_only_elements)) {
466869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    AddInstruction(new(zone()) HCheckMap(
466969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        elements, isolate()->factory()->fixed_array_map()));
467069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
46719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  HInstruction* length = NULL;
46727d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  HInstruction* checked_key = NULL;
46733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (map->has_external_array_elements()) {
467469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
46753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
46763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HLoadExternalArrayPointer* external_elements =
46773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        new(zone()) HLoadExternalArrayPointer(elements);
46783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(external_elements);
46793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return BuildExternalArrayElementAccess(external_elements, checked_key,
46803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                           val, map->elements_kind(), is_store);
46813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
4682c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  ASSERT(fast_smi_only_elements ||
4683c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch         fast_elements ||
4684c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch         map->has_fast_double_elements());
46853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (map->instance_type() == JS_ARRAY_TYPE) {
468669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck));
46879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
468869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
46899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
469069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4691592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return BuildFastElementAccess(elements, checked_key, val,
4692592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                map->elements_kind(), is_store);
4693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
46963fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
46973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      HValue* key,
46983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      HValue* val,
46993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      Expression* prop,
47003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      int ast_id,
47013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      int position,
47023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      bool is_store,
47033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      bool* has_side_effects) {
47043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  *has_side_effects = false;
47058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckNonSmi(object));
470669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  SmallMapList* maps = prop->GetReceiverTypes();
47073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool todo_external_array = false;
47083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4709589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  static const int kNumElementTypes = kElementsKindCount;
47103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool type_todo[kNumElementTypes];
47113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < kNumElementTypes; ++i) {
47123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    type_todo[i] = false;
47133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
47143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4715592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Elements_kind transition support.
4716592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  MapHandleList transition_target(maps->length());
4717592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Collect possible transition targets.
4718592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  MapHandleList possible_transitioned_maps(maps->length());
4719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  for (int i = 0; i < maps->length(); ++i) {
4720592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Map> map = maps->at(i);
4721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ElementsKind elements_kind = map->elements_kind();
4722592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (elements_kind == FAST_DOUBLE_ELEMENTS ||
4723592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        elements_kind == FAST_ELEMENTS) {
4724592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      possible_transitioned_maps.Add(map);
4725592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
4726592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
4727592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Get transition target for each map (NULL == no transition).
4728592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  for (int i = 0; i < maps->length(); ++i) {
4729592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Map> map = maps->at(i);
4730592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Map> transitioned_map =
4731592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        map->FindTransitionedMap(&possible_transitioned_maps);
4732592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    transition_target.Add(transitioned_map);
4733592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
4734592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4735592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  int num_untransitionable_maps = 0;
4736592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<Map> untransitionable_map;
47373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < maps->length(); ++i) {
4738592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Map> map = maps->at(i);
4739592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ASSERT(map->IsMap());
4740592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (!transition_target.at(i).is_null()) {
47415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      AddInstruction(new(zone()) HTransitionElementsKind(
4742592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          object, map, transition_target.at(i)));
4743592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    } else {
4744592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      type_todo[map->elements_kind()] = true;
4745592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) {
4746592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        todo_external_array = true;
4747592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
4748592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      num_untransitionable_maps++;
4749592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      untransitionable_map = map;
47503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
47513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
47523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // If only one map is left after transitioning, handle this case
4754592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // monomorphically.
4755592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (num_untransitionable_maps == 1) {
4756c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    HInstruction* instr = NULL;
4757c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    if (untransitionable_map->has_slow_elements_kind()) {
4758c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
4759c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                      : BuildLoadKeyedGeneric(object, key));
4760c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    } else {
4761c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      instr = AddInstruction(BuildMonomorphicElementAccess(
4762c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          object, key, val, untransitionable_map, is_store));
4763c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    }
4764592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    *has_side_effects |= instr->HasObservableSideEffects();
4765592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    instr->set_position(position);
4766592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return is_store ? NULL : instr;
4767592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
4768592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4769592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  AddInstruction(HCheckInstanceType::NewIsSpecObject(object));
47703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* join = graph()->CreateBasicBlock();
47713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* elements_kind_instr =
47733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      AddInstruction(new(zone()) HElementsKind(object));
477469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HCompareConstantEqAndBranch* elements_kind_branch = NULL;
477569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
47763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HLoadExternalArrayPointer* external_elements = NULL;
47773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* checked_key = NULL;
47783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4779592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Generated code assumes that FAST_SMI_ONLY_ELEMENTS, FAST_ELEMENTS,
4780592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS are handled before external
4781592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // arrays.
4782592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
4783592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
4784592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
4785592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
47863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4787592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND;
4788589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch       elements_kind <= LAST_ELEMENTS_KIND;
4789589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch       elements_kind = ElementsKind(elements_kind + 1)) {
4790592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // After having handled FAST_ELEMENTS, FAST_SMI_ONLY_ELEMENTS,
4791592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS, we need to add some code
4792592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // that's executed for all external array cases.
4793589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND ==
4794589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                  LAST_ELEMENTS_KIND);
4795589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND
47963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        && todo_external_array) {
47973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HInstruction* length =
479869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
47993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
48003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      external_elements = new(zone()) HLoadExternalArrayPointer(elements);
48013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      AddInstruction(external_elements);
48023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
48033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (type_todo[elements_kind]) {
48043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HBasicBlock* if_true = graph()->CreateBasicBlock();
48053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HBasicBlock* if_false = graph()->CreateBasicBlock();
480669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      elements_kind_branch = new(zone()) HCompareConstantEqAndBranch(
480769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          elements_kind_instr, elements_kind, Token::EQ_STRICT);
480869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      elements_kind_branch->SetSuccessorAt(0, if_true);
480969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      elements_kind_branch->SetSuccessorAt(1, if_false);
481069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      current_block()->Finish(elements_kind_branch);
48113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
48123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      set_current_block(if_true);
48133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HInstruction* access;
4814592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (elements_kind == FAST_SMI_ONLY_ELEMENTS ||
4815592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          elements_kind == FAST_ELEMENTS ||
4816589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          elements_kind == FAST_DOUBLE_ELEMENTS) {
4817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        if (is_store && elements_kind != FAST_DOUBLE_ELEMENTS) {
481869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          AddInstruction(new(zone()) HCheckMap(
481969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              elements, isolate()->factory()->fixed_array_map(),
482069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              elements_kind_branch));
482169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
4822592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // TODO(jkummerow): The need for these two blocks could be avoided
4823592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // in one of two ways:
4824592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // (1) Introduce ElementsKinds for JSArrays that are distinct from
4825592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        //     those for fast objects.
4826592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // (2) Put the common instructions into a third "join" block. This
4827592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        //     requires additional AST IDs that we can deopt to from inside
4828592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        //     that join block. They must be added to the Property class (when
4829592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        //     it's a keyed property) and registered in the full codegen.
48303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
48313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
48323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HHasInstanceTypeAndBranch* typecheck =
48333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE);
48343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        typecheck->SetSuccessorAt(0, if_jsarray);
48353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        typecheck->SetSuccessorAt(1, if_fastobject);
48363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        current_block()->Finish(typecheck);
48373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
48383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        set_current_block(if_jsarray);
4839592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        HInstruction* length;
4840592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck));
48413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4842592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        access = AddInstruction(BuildFastElementAccess(
4843592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            elements, checked_key, val, elements_kind, is_store));
4844592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        if (!is_store) {
48453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          Push(access);
48463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
4847592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4848592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        *has_side_effects |= access->HasObservableSideEffects();
48493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (position != -1) {
48503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          access->set_position(position);
48513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
48523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if_jsarray->Goto(join);
48533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
48543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        set_current_block(if_fastobject);
485569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
48563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4857592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        access = AddInstruction(BuildFastElementAccess(
4858592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            elements, checked_key, val, elements_kind, is_store));
4859589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (elements_kind == DICTIONARY_ELEMENTS) {
48603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (is_store) {
48613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
48623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        } else {
48633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          access = AddInstruction(BuildLoadKeyedGeneric(object, key));
48643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
48653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {  // External array elements.
48663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        access = AddInstruction(BuildExternalArrayElementAccess(
48673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            external_elements, checked_key, val, elements_kind, is_store));
48683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
4869592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      *has_side_effects |= access->HasObservableSideEffects();
48703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      access->set_position(position);
48713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (!is_store) {
48723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Push(access);
48733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
48743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      current_block()->Goto(join);
48753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      set_current_block(if_false);
48763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
48773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
48783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
48793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Deopt if none of the cases matched.
48803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
48813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  join->SetJoinId(ast_id);
48823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  set_current_block(join);
48833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return is_store ? NULL : Pop();
48841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
48851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
48861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
48873fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj,
48883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                HValue* key,
48893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                HValue* val,
48903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                Expression* expr,
48913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                int ast_id,
48923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                int position,
48933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                bool is_store,
48943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                bool* has_side_effects) {
48953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(!expr->IsPropertyName());
48963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* instr = NULL;
48973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (expr->IsMonomorphic()) {
4898592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Map> map = expr->GetMonomorphicReceiverType();
4899c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    if (map->has_slow_elements_kind()) {
4900c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
4901c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                       : BuildLoadKeyedGeneric(obj, key);
4902c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    } else {
4903c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      AddInstruction(new(zone()) HCheckNonSmi(obj));
4904c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      instr = BuildMonomorphicElementAccess(obj, key, val, map, is_store);
4905c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    }
49063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else if (expr->GetReceiverTypes() != NULL &&
49073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch             !expr->GetReceiverTypes()->is_empty()) {
49083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return HandlePolymorphicElementAccess(
49093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        obj, key, val, expr, ast_id, position, is_store, has_side_effects);
49103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
49113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (is_store) {
49123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      instr = BuildStoreKeyedGeneric(obj, key, val);
49133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
49143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      instr = BuildLoadKeyedGeneric(obj, key);
49158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
49168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
49173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  instr->set_position(position);
49183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AddInstruction(instr);
4919592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  *has_side_effects = instr->HasObservableSideEffects();
49203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return instr;
49218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
49228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
49238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
4925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    HValue* key,
4926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    HValue* value) {
4927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
49288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HStoreKeyedGeneric(
49298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         context,
49308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         object,
49318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         key,
49328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         value,
4933592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                         function_strict_mode_flag());
4934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryArgumentsAccess(Property* expr) {
4937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = expr->obj()->AsVariableProxy();
4938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (proxy == NULL) return false;
4939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!proxy->var()->IsStackAllocated()) return false;
4940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
4941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
4942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
494442effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // Our implementation of arguments (based on this stack frame or an
494542effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // adapter below it) does not work for inlined functions.
494642effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  if (function_state()->outer() != NULL) {
494742effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch    Bailout("arguments access in inlined function");
494842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch    return true;
494942effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  }
495042effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch
4951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* result = NULL;
4952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->key()->IsPropertyName()) {
4953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
4954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!name->IsEqualTo(CStrVector("length"))) return false;
49558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
49568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    result = new(zone()) HArgumentsLength(elements);
4957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4958e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Push(graph()->GetArgumentsObject());
4959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitForValue(expr->key());
4960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (HasStackOverflow() || current_block() == NULL) return true;
4961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* key = Pop();
4962e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Drop(1);  // Arguments object.
49638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
49648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* length = AddInstruction(
49658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        new(zone()) HArgumentsLength(elements));
49667d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    HInstruction* checked_key =
49677d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch        AddInstruction(new(zone()) HBoundsCheck(key, length));
49687d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
4969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, expr->id());
4971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
4972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitProperty(Property* expr) {
4976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
4977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
4978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
4979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->RecordTypeFeedback(oracle());
4980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (TryArgumentsAccess(expr)) return;
4982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->obj()));
4984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = NULL;
4986592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (expr->AsProperty()->IsArrayLength()) {
4987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* array = Pop();
49888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(array));
498969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    HInstruction* mapcheck =
499069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        AddInstruction(HCheckInstanceType::NewIsJSArray(array));
499169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    instr = new(zone()) HJSArrayLength(array, mapcheck);
49929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
49931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else if (expr->IsStringLength()) {
49941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    HValue* string = Pop();
49958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(string));
4996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AddInstruction(HCheckInstanceType::NewIsString(string));
49978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr = new(zone()) HStringLength(string);
499844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (expr->IsStringAccess()) {
4999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->key()));
500044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* index = Pop();
500144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* string = Pop();
50023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HValue* context = environment()->LookupContext();
50033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HStringCharCodeAt* char_code =
50043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      BuildStringCharCodeAt(context, string, index);
500544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AddInstruction(char_code);
50063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    instr = new(zone()) HStringCharFromCode(context, char_code);
50071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
50089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else if (expr->IsFunctionPrototype()) {
50099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    HValue* function = Pop();
50108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(function));
50118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr = new(zone()) HLoadFunctionPrototype(function);
5012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (expr->key()->IsPropertyName()) {
5014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
501569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    SmallMapList* types = expr->GetReceiverTypes();
5016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* obj = Pop();
5018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (expr->IsMonomorphic()) {
5019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = BuildLoadNamed(obj, expr, types->first(), name);
5020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (types != NULL && types->length() > 1) {
50218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      AddInstruction(new(zone()) HCheckNonSmi(obj));
50223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HValue* context = environment()->LookupContext();
50233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      instr = new(zone()) HLoadNamedFieldPolymorphic(context, obj, types, name);
5024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
5025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = BuildLoadNamedGeneric(obj, expr);
5026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
5029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->key()));
5030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* key = Pop();
5032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* obj = Pop();
50333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
50343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool has_side_effects = false;
50353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HValue* load = HandleKeyedElementAccess(
50363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        obj, key, NULL, expr, expr->id(), expr->position(),
50373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        false,  // is_store
50383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        &has_side_effects);
50393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (has_side_effects) {
50403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (ast_context()->IsEffect()) {
50413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AddSimulate(expr->id());
50423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
50433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Push(load);
50443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AddSimulate(expr->id());
50453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Drop(1);
50463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
50473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
50483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnValue(load);
5049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(expr->position());
50513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
5052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddCheckConstantFunction(Call* expr,
5056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             HValue* receiver,
5057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             Handle<Map> receiver_map,
5058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             bool smi_and_map_check) {
5059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Constant functions have the nice property that the map will change if they
5060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // are overwritten.  Therefore it is enough to check the map of the holder and
5061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // its prototypes.
5062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (smi_and_map_check) {
50638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(receiver));
5064c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    AddInstruction(new(zone()) HCheckMap(receiver, receiver_map, NULL,
5065c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                         ALLOW_ELEMENT_TRANSITION_MAPS));
5066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!expr->holder().is_null()) {
50688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckPrototypeMaps(
5069b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        Handle<JSObject>(JSObject::cast(receiver_map->prototype())),
5070b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        expr->holder()));
5071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
5076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                               HValue* receiver,
507769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                               SmallMapList* types,
5078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                               Handle<String> name) {
5079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(ager): We should recognize when the prototype chains for different
5080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // maps are identical. In that case we can avoid repeatedly generating the
5081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // same prototype map checks.
508244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int argument_count = expr->arguments()->length() + 1;  // Includes receiver.
508344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int count = 0;
508444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* join = NULL;
508544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < types->length() && count < kMaxCallPolymorphism; ++i) {
5086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Map> map = types->at(i);
5087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (expr->ComputeTarget(map, name)) {
508844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (count == 0) {
50898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        // Only needed once.
50908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckNonSmi(receiver));
509144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        join = graph()->CreateBasicBlock();
509244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
509344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ++count;
509444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HBasicBlock* if_true = graph()->CreateBasicBlock();
509544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HBasicBlock* if_false = graph()->CreateBasicBlock();
50968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HCompareMap* compare =
50978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          new(zone()) HCompareMap(receiver, map, if_true, if_false);
509844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      current_block()->Finish(compare);
509944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
510044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      set_current_block(if_true);
5101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddCheckConstantFunction(expr, receiver, map, false);
5102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
5103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF("Trying to inline the polymorphic call to %s\n",
5104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               *name->ToCString());
5105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
51065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (FLAG_polymorphic_inlining && TryInlineCall(expr)) {
5107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Trying to inline will signal that we should bailout from the
5108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // entire compilation by setting stack overflow on the visitor.
5109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (HasStackOverflow()) return;
5110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
5111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        HCallConstantFunction* call =
51128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) HCallConstantFunction(expr->target(), argument_count);
5113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        call->set_position(expr->position());
51141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        PreProcessCall(call);
511544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        AddInstruction(call);
511644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (!ast_context()->IsEffect()) Push(call);
5117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
511844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
511944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (current_block() != NULL) current_block()->Goto(join);
512044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      set_current_block(if_false);
5121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
512444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Finish up.  Unconditionally deoptimize if we've handled all the maps we
512544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // know about and do not want to handle ones we've never seen.  Otherwise
512644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // use a generic IC.
512744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
5128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
512944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
5130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HValue* context = environment()->LookupContext();
51318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count);
5132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    call->set_position(expr->position());
51331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    PreProcessCall(call);
5134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
513544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (join != NULL) {
513644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      AddInstruction(call);
513744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (!ast_context()->IsEffect()) Push(call);
513844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      current_block()->Goto(join);
513944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
51403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnInstruction(call, expr->id());
51419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
5142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
514344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
514444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // We assume that control flow is always live after an expression.  So
514544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // even without predecessors to the join block, we set it as the exit
514644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // block and continue by adding instructions there.
514744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(join != NULL);
514844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (join->HasPredecessor()) {
5149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(join);
515044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    join->SetJoinId(expr->id());
51513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
5152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
5153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(NULL);
515444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
5155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::TraceInline(Handle<JSFunction> target,
5159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Handle<JSFunction> caller,
5160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                const char* reason) {
5161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (FLAG_trace_inlining) {
5162589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SmartArrayPointer<char> target_name =
5163589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        target->shared()->DebugName()->ToCString();
5164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SmartArrayPointer<char> caller_name =
5165589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        caller->shared()->DebugName()->ToCString();
5166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (reason == NULL) {
5167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      PrintF("Inlined %s called from %s.\n", *target_name, *caller_name);
5168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
5169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      PrintF("Did not inline %s called from %s (%s).\n",
5170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch             *target_name, *caller_name, reason);
5171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
5172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
51765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochbool HGraphBuilder::TryInline(CallKind call_kind,
51775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                              Handle<JSFunction> target,
51785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                              ZoneList<Expression*>* arguments,
51795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                              HValue* receiver,
51805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                              int ast_id,
51815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                              int return_id,
51825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                              ReturnHandlingFlag return_handling) {
5183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!FLAG_use_inlining) return false;
5184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Precondition: call is monomorphic and we have found a target with the
5186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // appropriate arity.
5187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<JSFunction> caller = info()->closure();
5188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<SharedFunctionInfo> target_shared(target->shared());
5189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Do a quick check on source code length to avoid parsing large
5191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // inlining candidates.
51925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if ((FLAG_limit_inlining && target_shared->SourceSize() > kMaxSourceSize)
51935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      || target_shared->SourceSize() > kUnlimitedMaxSourceSize) {
5194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TraceInline(target, caller, "target text too big");
5195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
5196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Target must be inlineable.
5199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!target->IsInlineable()) {
5200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TraceInline(target, caller, "target not inlineable");
5201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return false;
5202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
52035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (target_shared->dont_inline() || target_shared->dont_optimize()) {
52045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    TraceInline(target, caller, "target contains unsupported syntax [early]");
52055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return false;
52065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
52075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
52085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int nodes_added = target_shared->ast_node_count();
52095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if ((FLAG_limit_inlining && nodes_added > kMaxInlinedSize) ||
52105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      nodes_added > kUnlimitedMaxInlinedSize) {
52115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    TraceInline(target, caller, "target AST is too large [early]");
52125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return false;
52135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
5214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5215592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#if !defined(V8_TARGET_ARCH_IA32)
5216592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Target must be able to use caller's context.
5217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompilationInfo* outer_info = info();
5218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (target->context() != outer_info->closure()->context() ||
5219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_info->scope()->contains_with() ||
5220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_info->scope()->num_heap_slots() > 0) {
5221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TraceInline(target, caller, "target requires context change");
5222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
5223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5224592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#endif
5225592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
5226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
52278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Don't inline deeper than kMaxInliningLevels calls.
5228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* env = environment();
52298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int current_level = 1;
52308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  while (env->outer() != NULL) {
52318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (current_level == Compiler::kMaxInliningLevels) {
5232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      TraceInline(target, caller, "inline depth limit reached");
52338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return false;
52348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
52355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (env->outer()->frame_type() == JS_FUNCTION) {
5236c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      current_level++;
5237c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    }
52388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    env = env->outer();
5239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
5240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Don't inline recursive functions.
5242592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  for (FunctionState* state = function_state();
5243592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch       state != NULL;
5244592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch       state = state->outer()) {
5245592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (state->compilation_info()->closure()->shared() == *target_shared) {
5246592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      TraceInline(target, caller, "target is recursive");
5247592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      return false;
5248592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
5249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
5250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We don't want to add more than a certain number of nodes from inlining.
52525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if ((FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) ||
52535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      inlined_count_ > kUnlimitedMaxInlinedNodes) {
5254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TraceInline(target, caller, "cumulative AST node limit reached");
5255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
5256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Parse and allocate variables.
5259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompilationInfo target_info(target);
5260592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!ParserApi::Parse(&target_info, kNoParsingFlags) ||
5261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      !Scope::Analyze(&target_info)) {
526244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (target_info.isolate()->has_pending_exception()) {
5263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Parse or scope error, never optimize this function.
52641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      SetStackOverflow();
52655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      target_shared->DisableOptimization();
52661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
5267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TraceInline(target, caller, "parse failure");
5268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return false;
5269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
5270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
5271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (target_info.scope()->num_heap_slots() > 0) {
5272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TraceInline(target, caller, "target has context-allocated variables");
5273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
5274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  FunctionLiteral* function = target_info.function();
5276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
52775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // The following conditions must be checked again after re-parsing, because
52785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // earlier the information might not have been complete due to lazy parsing.
52795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  nodes_added = function->ast_node_count();
52805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if ((FLAG_limit_inlining && nodes_added > kMaxInlinedSize) ||
52815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      nodes_added > kUnlimitedMaxInlinedSize) {
52825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    TraceInline(target, caller, "target AST is too large [late]");
52835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return false;
52845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
52855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  AstProperties::Flags* flags(function->flags());
52865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (flags->Contains(kDontInline) || flags->Contains(kDontOptimize)) {
52875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    TraceInline(target, caller, "target contains unsupported syntax [late]");
5288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
5289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
52915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // If the function uses the arguments object check that inlining of functions
52925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // with arguments object is enabled and the arguments-variable is
52935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // stack allocated.
5294c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  if (function->scope()->arguments() != NULL) {
52955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (!FLAG_inline_arguments) {
52965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      TraceInline(target, caller, "target uses arguments object");
52975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      return false;
52985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
52995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
53005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (!function->scope()->arguments()->IsStackAllocated()) {
53015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      TraceInline(target,
53025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                  caller,
53035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                  "target uses non-stackallocated arguments object");
53045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      return false;
53055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
5306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
53083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // All declarations must be inlineable.
53093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ZoneList<Declaration*>* decls = target_info.scope()->declarations();
53103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int decl_count = decls->length();
53113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < decl_count; ++i) {
53123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!decls->at(i)->IsInlineable()) {
53133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      TraceInline(target, caller, "target has non-trivial declaration");
53143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return false;
53153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
53163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Generate the deoptimization data for the unoptimized version of
5319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the target function if we don't already have it.
5320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!target_shared->has_deoptimization_support()) {
5321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Note that we compile here using the same AST that we will use for
5322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // generating the optimized inline code.
5323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    target_info.EnableDeoptimizationSupport();
5324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (!FullCodeGenerator::MakeCode(&target_info)) {
5325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      TraceInline(target, caller, "could not generate deoptimization info");
5326e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      return false;
5327e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
5328592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (target_shared->scope_info() == ScopeInfo::Empty()) {
53293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // The scope info might not have been set if a lazily compiled
53303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // function is inlined before being called for the first time.
5331592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Handle<ScopeInfo> target_scope_info =
5332592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          ScopeInfo::Create(target_info.scope());
53333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      target_shared->set_scope_info(*target_scope_info);
53343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5335e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    target_shared->EnableDeoptimizationSupport(*target_info.code());
5336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG,
5337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                        &target_info,
5338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                        target_shared);
5339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // ----------------------------------------------------------------
53423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // After this point, we've made a decision to inline this function (so
53433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // TryInline should always return true).
53443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Save the pending call context and type feedback oracle. Set up new ones
5346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // for the inlined function.
5347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(target_shared->has_deoptimization_support());
5348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  TypeFeedbackOracle target_oracle(
5349e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Handle<Code>(target_shared->code()),
5350592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Handle<Context>(target->context()->global_context()),
5351592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      isolate());
5352592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // The function state is new-allocated because we need to delete it
5353592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // in two different places.
53545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  FunctionState* target_state = new FunctionState(
53555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      this, &target_info, &target_oracle, return_handling);
5356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
535744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HConstant* undefined = graph()->GetConstantUndefined();
535844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEnvironment* inner_env =
5359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      environment()->CopyForInlining(target,
53605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                     arguments->length(),
5361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     function,
5362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     undefined,
53635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                     call_kind,
53645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                     function_state()->is_construct());
5365592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#ifdef V8_TARGET_ARCH_IA32
5366592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // IA32 only, overwrite the caller's context in the deoptimization
5367592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // environment with the correct one.
5368592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  //
5369592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // TODO(kmillikin): implement the same inlining on other platforms so we
5370592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // can remove the unsightly ifdefs in this function.
5371592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HConstant* context = new HConstant(Handle<Context>(target->context()),
5372592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                     Representation::Tagged());
5373592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  AddInstruction(context);
5374592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  inner_env->BindContext(context);
5375592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#endif
53765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  AddSimulate(return_id);
53775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  current_block()->UpdateEnvironment(inner_env);
5378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AddInstruction(new(zone()) HEnterInlined(target,
53795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                           arguments->length(),
5380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                           function,
53815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                           call_kind,
53825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                           function_state()->is_construct()));
53835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // If the function uses arguments object create and bind one.
53845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (function->scope()->arguments() != NULL) {
53855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ASSERT(function->scope()->arguments()->IsStackAllocated());
53865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    environment()->Bind(function->scope()->arguments(),
53875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                        graph()->GetArgumentsObject());
53885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
53893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  VisitDeclarations(target_info.scope()->declarations());
539044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  VisitStatements(function->body());
5391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (HasStackOverflow()) {
5392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Bail out if the inline function did, as we cannot residualize a call
5393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // instead.
5394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TraceInline(target, caller, "inline graph construction failed");
53955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    target_shared->DisableOptimization();
5396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    inline_bailout_ = true;
5397592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    delete target_state;
5398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return true;
5399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Update inlined nodes count.
5402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  inlined_count_ += nodes_added;
5403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TraceInline(target, caller, NULL);
5405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
540644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (current_block() != NULL) {
54075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // Add default return value (i.e. undefined for normals calls or the newly
54085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // allocated receiver for construct calls) if control can fall off the
54095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // body.  In a test context, undefined is false and any JSObject is true.
54105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (call_context()->IsValue()) {
5411e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(function_return() != NULL);
54125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HValue* return_value = function_state()->is_construct()
54135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          ? receiver
54145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          : undefined;
54155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      current_block()->AddLeaveInlined(return_value,
54165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       function_return(),
54175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       function_state()->drop_extra());
54185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    } else if (call_context()->IsEffect()) {
54195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ASSERT(function_return() != NULL);
54205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      current_block()->Goto(function_return(), function_state()->drop_extra());
5421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
5422592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT(call_context()->IsTest());
54235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ASSERT(inlined_test_context() != NULL);
54245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HBasicBlock* target = function_state()->is_construct()
54255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          ? inlined_test_context()->if_true()
54265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          : inlined_test_context()->if_false();
54275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      current_block()->Goto(target, function_state()->drop_extra());
5428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Fix up the function exits.
5432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (inlined_test_context() != NULL) {
5433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* if_true = inlined_test_context()->if_true();
5434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* if_false = inlined_test_context()->if_false();
54353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Pop the return test context from the expression context stack.
54373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(ast_context() == inlined_test_context());
5438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ClearInlinedTestContext();
5439592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    delete target_state;
5440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Forward to the real test context.
5442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (if_true->HasPredecessor()) {
54435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if_true->SetJoinId(ast_id);
5444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
5445592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if_true->Goto(true_target, function_state()->drop_extra());
5446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
5447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (if_false->HasPredecessor()) {
54485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if_false->SetJoinId(ast_id);
5449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
5450592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if_false->Goto(false_target, function_state()->drop_extra());
5451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
5452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(NULL);
5453592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return true;
5454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (function_return()->HasPredecessor()) {
54565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    function_return()->SetJoinId(ast_id);
5457e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(function_return());
5458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
5459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(NULL);
5460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5461592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  delete target_state;
5462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
5463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
54665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochbool HGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) {
54675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // The function call we are inlining is a method call if the call
54685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // is a property call.
54695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  CallKind call_kind = (expr->expression()->AsProperty() == NULL)
54705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ? CALL_AS_FUNCTION
54715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : CALL_AS_METHOD;
54725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
54735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  return TryInline(call_kind,
54745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                   expr->target(),
54755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                   expr->arguments(),
54765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                   NULL,
54775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                   expr->id(),
54785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                   expr->ReturnId(),
54795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                   drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN);
54805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
54815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
54825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
54835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochbool HGraphBuilder::TryInlineConstruct(CallNew* expr, HValue* receiver) {
54845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  return TryInline(CALL_AS_FUNCTION,
54855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                   expr->target(),
54865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                   expr->arguments(),
54875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                   receiver,
54885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                   expr->id(),
54895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                   expr->ReturnId(),
54905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                   CONSTRUCT_CALL_RETURN);
54915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
54925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
54935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
54945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochbool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) {
54955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
54965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
54975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  switch (id) {
54985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    case kMathRound:
54995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    case kMathAbs:
55005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    case kMathSqrt:
55015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    case kMathLog:
55025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    case kMathSin:
55035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    case kMathCos:
55045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    case kMathTan:
55055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (expr->arguments()->length() == 1) {
55065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        HValue* argument = Pop();
55075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        HValue* context = environment()->LookupContext();
55085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        Drop(1);  // Receiver.
55095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        HUnaryMathOperation* op =
55105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            new(zone()) HUnaryMathOperation(context, argument, id);
55115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        op->set_position(expr->position());
55125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (drop_extra) Drop(1);  // Optionally drop the function.
55135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ast_context()->ReturnInstruction(op, expr->id());
55145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        return true;
55155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
55165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      break;
55175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    default:
55185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      // Not supported for inlining yet.
55195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      break;
55205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
55215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  return false;
55225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
55235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
55245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
55255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochbool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr,
55265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                               HValue* receiver,
55275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                               Handle<Map> receiver_map,
55285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                               CheckType check_type) {
55291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null());
5530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Try to inline calls like Math.* as operations in the calling function.
55311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
5532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
5533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
5534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (id) {
55351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case kStringCharCodeAt:
553644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    case kStringCharAt:
55371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (argument_count == 2 && check_type == STRING_CHECK) {
55381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        HValue* index = Pop();
55391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        HValue* string = Pop();
55403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HValue* context = environment()->LookupContext();
55411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ASSERT(!expr->holder().is_null());
55428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckPrototypeMaps(
55431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK),
55441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            expr->holder()));
55453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HStringCharCodeAt* char_code =
55463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            BuildStringCharCodeAt(context, string, index);
554744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (id == kStringCharCodeAt) {
554844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ast_context()->ReturnInstruction(char_code, expr->id());
554944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          return true;
555044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
555144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        AddInstruction(char_code);
55528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        HStringCharFromCode* result =
55533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            new(zone()) HStringCharFromCode(context, char_code);
55541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ast_context()->ReturnInstruction(result, expr->id());
55551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        return true;
55561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
55571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
5558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathRound:
5559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathFloor:
5560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathAbs:
5561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathSqrt:
5562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathLog:
5563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathSin:
5564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathCos:
55655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    case kMathTan:
55661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
55671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AddCheckConstantFunction(expr, receiver, receiver_map, true);
5568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* argument = Pop();
55693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HValue* context = environment()->LookupContext();
5570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Drop(1);  // Receiver.
55713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HUnaryMathOperation* op =
55723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            new(zone()) HUnaryMathOperation(context, argument, id);
5573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        op->set_position(expr->position());
5574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ast_context()->ReturnInstruction(op, expr->id());
5575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return true;
5576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
5578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathPow:
55791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
55801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AddCheckConstantFunction(expr, receiver, receiver_map, true);
5581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* right = Pop();
5582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* left = Pop();
5583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Pop();  // Pop receiver.
55843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HValue* context = environment()->LookupContext();
5585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HInstruction* result = NULL;
5586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Use sqrt() if exponent is 0.5 or -0.5.
5587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
5588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          double exponent = HConstant::cast(right)->DoubleValue();
5589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (exponent == 0.5) {
55903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            result =
55913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                new(zone()) HUnaryMathOperation(context, left, kMathPowHalf);
5592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (exponent == -0.5) {
5593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HConstant* double_one =
55948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                new(zone()) HConstant(Handle<Object>(Smi::FromInt(1)),
55958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                      Representation::Double());
5596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AddInstruction(double_one);
5597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HUnaryMathOperation* square_root =
55983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                new(zone()) HUnaryMathOperation(context, left, kMathPowHalf);
5599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AddInstruction(square_root);
5600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // MathPowHalf doesn't have side effects so there's no need for
5601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // an environment simulation here.
5602592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            ASSERT(!square_root->HasObservableSideEffects());
56033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            result = new(zone()) HDiv(context, double_one, square_root);
5604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (exponent == 2.0) {
56053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            result = new(zone()) HMul(context, left, left);
5606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
5607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else if (right->IsConstant() &&
56081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                   HConstant::cast(right)->HasInteger32Value() &&
56091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                   HConstant::cast(right)->Integer32Value() == 2) {
56103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          result = new(zone()) HMul(context, left, left);
5611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
5612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
56131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if (result == NULL) {
56148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          result = new(zone()) HPower(left, right);
56151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        }
5616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ast_context()->ReturnInstruction(result, expr->id());
5617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return true;
5618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
5620c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    case kMathRandom:
5621c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) {
5622c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        AddCheckConstantFunction(expr, receiver, receiver_map, true);
56235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        Drop(1);  // Receiver.
5624c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        HValue* context = environment()->LookupContext();
5625c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        HGlobalObject* global_object = new(zone()) HGlobalObject(context);
5626c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        AddInstruction(global_object);
5627c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        HRandom* result = new(zone()) HRandom(global_object);
5628c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        ast_context()->ReturnInstruction(result, expr->id());
5629c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        return true;
5630c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      }
5631c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      break;
5632c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    case kMathMax:
5633c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    case kMathMin:
5634c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
5635c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        AddCheckConstantFunction(expr, receiver, receiver_map, true);
5636c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        HValue* right = Pop();
5637c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        HValue* left = Pop();
56385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        Pop();  // Pop receiver.
56395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
56405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        HValue* left_operand = left;
56415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        HValue* right_operand = right;
56425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
56435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        // If we do not have two integers, we convert to double for comparison.
56445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (!left->representation().IsInteger32() ||
56455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            !right->representation().IsInteger32()) {
56465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          if (!left->representation().IsDouble()) {
56475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            HChange* left_convert = new(zone()) HChange(
56485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                left,
56495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                Representation::Double(),
56505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                false,  // Do not truncate when converting to double.
56515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                true);  // Deoptimize for undefined.
56525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            left_convert->SetFlag(HValue::kBailoutOnMinusZero);
56535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            left_operand = AddInstruction(left_convert);
56545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          }
56555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          if (!right->representation().IsDouble()) {
56565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            HChange* right_convert = new(zone()) HChange(
56575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                right,
56585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                Representation::Double(),
56595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                false,  // Do not truncate when converting to double.
56605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                true);  // Deoptimize for undefined.
56615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            right_convert->SetFlag(HValue::kBailoutOnMinusZero);
56625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            right_operand = AddInstruction(right_convert);
56635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          }
5664c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        }
5665c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
56665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ASSERT(left_operand->representation().Equals(
56675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch               right_operand->representation()));
56685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ASSERT(!left_operand->representation().IsTagged());
56695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
5670c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        Token::Value op = (id == kMathMin) ? Token::LT : Token::GT;
56715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
56725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        HCompareIDAndBranch* compare =
56735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            new(zone()) HCompareIDAndBranch(left_operand, right_operand, op);
56745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        compare->SetInputRepresentation(left_operand->representation());
5675c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
5676c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        HBasicBlock* return_left = graph()->CreateBasicBlock();
5677c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        HBasicBlock* return_right = graph()->CreateBasicBlock();
5678c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
5679c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        compare->SetSuccessorAt(0, return_left);
5680c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        compare->SetSuccessorAt(1, return_right);
5681c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        current_block()->Finish(compare);
5682c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
5683c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        set_current_block(return_left);
5684c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        Push(left);
5685c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        set_current_block(return_right);
5686c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        Push(right);
5687c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
5688c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        HBasicBlock* join = CreateJoin(return_left, return_right, expr->id());
5689c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        set_current_block(join);
5690c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        ast_context()->ReturnValue(Pop());
5691c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        return true;
5692c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      }
5693c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      break;
5694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    default:
5695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Not yet supported for inlining.
5696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
5697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return false;
5699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryCallApply(Call* expr) {
5703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Expression* callee = expr->expression();
5704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = callee->AsProperty();
5705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(prop != NULL);
5706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
570742effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) {
570842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch    return false;
570942effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  }
571042effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  Handle<Map> function_map = expr->GetReceiverTypes()->first();
571142effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  if (function_map->instance_type() != JS_FUNCTION_TYPE ||
571242effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch      !expr->target()->shared()->HasBuiltinFunctionId() ||
571342effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch      expr->target()->shared()->builtin_function_id() != kFunctionApply) {
571442effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch    return false;
571542effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  }
5716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
571742effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  if (info()->scope()->arguments() == NULL) return false;
5718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
5720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (args->length() != 2) return false;
5721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* arg_two = args->at(1)->AsVariableProxy();
5723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
5724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* arg_two_value = environment()->Lookup(arg_two->var());
5725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
5726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Found pattern f.apply(receiver, arguments).
5728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForValue(prop->obj());
5729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (HasStackOverflow() || current_block() == NULL) return true;
5730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* function = Top();
5731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AddCheckConstantFunction(expr, function, function_map, true);
5732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Drop(1);
5733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForValue(args->at(0));
5735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (HasStackOverflow() || current_block() == NULL) return true;
5736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* receiver = Pop();
57375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
57385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (function_state()->outer() == NULL) {
57395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
57405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HInstruction* length =
57415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        AddInstruction(new(zone()) HArgumentsLength(elements));
57425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HValue* wrapped_receiver =
57435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        AddInstruction(new(zone()) HWrapReceiver(receiver, function));
57445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HInstruction* result =
57455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        new(zone()) HApplyArguments(function,
57465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    wrapped_receiver,
57475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    length,
57485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    elements);
57495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    result->set_position(expr->position());
57505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ast_context()->ReturnInstruction(result, expr->id());
57515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return true;
57525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  } else {
57535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // We are inside inlined function and we know exactly what is inside
57545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // arguments object.
57555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HValue* context = environment()->LookupContext();
57565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
57575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HValue* wrapped_receiver =
57585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        AddInstruction(new(zone()) HWrapReceiver(receiver, function));
57595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    PushAndAdd(new(zone()) HPushArgument(wrapped_receiver));
57605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
57615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HEnvironment* arguments_env = environment()->arguments_environment();
57625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
57635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    int parameter_count = arguments_env->parameter_count();
57645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    for (int i = 1; i < arguments_env->parameter_count(); i++) {
57655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      PushAndAdd(new(zone()) HPushArgument(arguments_env->Lookup(i)));
57665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
57675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
57685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HInvokeFunction* call = new(zone()) HInvokeFunction(
57695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        context,
57705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        function,
57715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        parameter_count);
57725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    Drop(parameter_count);
57735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    call->set_position(expr->position());
57745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ast_context()->ReturnInstruction(call, expr->id());
57755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return true;
57765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
5777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCall(Call* expr) {
5781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
5782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
5783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
5784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Expression* callee = expr->expression();
5785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
5786e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HInstruction* call = NULL;
5787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = callee->AsProperty();
5789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (prop != NULL) {
5790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!prop->key()->IsPropertyName()) {
5791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Keyed function call.
57923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      CHECK_ALIVE(VisitArgument(prop->obj()));
5793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->key()));
5795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Push receiver and key like the non-optimized code generator expects it.
5796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* key = Pop();
5797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* receiver = Pop();
5798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(key);
5799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(receiver);
5800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
58013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      CHECK_ALIVE(VisitArgumentList(expr->arguments()));
5802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      HValue* context = environment()->LookupContext();
58043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      call = new(zone()) HCallKeyed(context, key, argument_count);
5805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      call->set_position(expr->position());
58063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Drop(argument_count + 1);  // 1 is the key.
58073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnInstruction(call, expr->id());
5808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Named function call.
5811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD);
5812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (TryCallApply(expr)) return;
5814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(prop->obj()));
5816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitExpressions(expr->arguments()));
5817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
5819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
582069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    SmallMapList* types = expr->GetReceiverTypes();
5821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
58221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    HValue* receiver =
58231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        environment()->ExpressionStackAt(expr->arguments()->length());
58241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (expr->IsMonomorphic()) {
582569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Handle<Map> receiver_map = (types == NULL || types->is_empty())
582669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          ? Handle<Map>::null()
582769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          : types->first();
58285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (TryInlineBuiltinMethodCall(expr,
58295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                     receiver,
58305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                     receiver_map,
58315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                     expr->check_type())) {
58325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (FLAG_trace_inlining) {
58335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          PrintF("Inlining builtin ");
58345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          expr->target()->ShortPrint();
58355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          PrintF("\n");
58365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        }
5837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return;
5838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5840592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (CallStubCompiler::HasCustomCallGenerator(expr->target()) ||
58411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          expr->check_type() != RECEIVER_MAP_CHECK) {
58421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // When the target has a custom call IC generator, use the IC,
584344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // because it is likely to generate better code.  Also use the IC
584444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // when a primitive receiver check is required.
5845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        HValue* context = environment()->LookupContext();
58468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        call = PreProcessCall(
58478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) HCallNamed(context, name, argument_count));
58481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
58491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AddCheckConstantFunction(expr, receiver, receiver_map, true);
58501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
58515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (TryInlineCall(expr)) return;
5852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        call = PreProcessCall(
5853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            new(zone()) HCallConstantFunction(expr->target(),
5854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              argument_count));
58551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
5856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (types != NULL && types->length() > 1) {
5857b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
5858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandlePolymorphicCallNamed(expr, receiver, types, name);
5859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
5860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
5862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      HValue* context = environment()->LookupContext();
58638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      call = PreProcessCall(
58648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          new(zone()) HCallNamed(context, name, argument_count));
5865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
5868592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION);
5869589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    VariableProxy* proxy = expr->expression()->AsVariableProxy();
5870589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
5871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
58725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (proxy != NULL && proxy->var()->is_possibly_eval()) {
58735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      return Bailout("possible direct call to eval");
58745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
58755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
5876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (global_call) {
5877589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Variable* var = proxy->var();
5878e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      bool known_global_function = false;
5879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // If there is a global property cell for the name at compile time and
5880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // access check is not enabled we assume that the function will not change
5881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // and generate optimized code for calling the function.
5882592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      LookupResult lookup(isolate());
58838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
58848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (type == kUseCell &&
5885e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          !info()->global_object()->IsAccessCheckNeeded()) {
5886e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        Handle<GlobalObject> global(info()->global_object());
58878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        known_global_function = expr->ComputeGlobalTarget(global, &lookup);
5888e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
5889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (known_global_function) {
5890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Push the global object instead of the global receiver because
5891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // code generated by the full code generator expects it.
5892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        HValue* context = environment()->LookupContext();
58938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        HGlobalObject* global_object = new(zone()) HGlobalObject(context);
58941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        PushAndAdd(global_object);
5895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        CHECK_ALIVE(VisitExpressions(expr->arguments()));
5896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        CHECK_ALIVE(VisitForValue(expr->expression()));
5898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* function = Pop();
58998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckFunction(function, expr->target()));
5900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Replace the global object with the global receiver.
59028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        HGlobalReceiver* global_receiver =
59038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) HGlobalReceiver(global_object);
5904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Index of the receiver from the top of the expression stack.
5905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        const int receiver_index = argument_count - 1;
5906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        AddInstruction(global_receiver);
5907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(environment()->ExpressionStackAt(receiver_index)->
5908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               IsGlobalObject());
5909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        environment()->SetExpressionStackAt(receiver_index, global_receiver);
5910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
59115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (TryInlineBuiltinFunctionCall(expr, false)) {  // Nothing to drop.
59125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          if (FLAG_trace_inlining) {
59135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            PrintF("Inlining builtin ");
59145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            expr->target()->ShortPrint();
59155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            PrintF("\n");
59165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          }
59175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          return;
59185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        }
59195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (TryInlineCall(expr)) return;
59208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
5921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                           argument_count));
5922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
5923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        HValue* context = environment()->LookupContext();
59243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HGlobalObject* receiver = new(zone()) HGlobalObject(context);
59253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AddInstruction(receiver);
59263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        PushAndAdd(new(zone()) HPushArgument(receiver));
59273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        CHECK_ALIVE(VisitArgumentList(expr->arguments()));
5928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
59293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        call = new(zone()) HCallGlobal(context, var->name(), argument_count);
59303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Drop(argument_count);
5931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5933592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    } else if (expr->IsMonomorphic()) {
5934592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // The function is on the stack in the unoptimized code during
5935592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // evaluation of the arguments.
5936592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      CHECK_ALIVE(VisitForValue(expr->expression()));
5937592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      HValue* function = Top();
5938592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      HValue* context = environment()->LookupContext();
5939592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      HGlobalObject* global = new(zone()) HGlobalObject(context);
5940592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global);
5941592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      AddInstruction(global);
5942592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      PushAndAdd(receiver);
5943592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      CHECK_ALIVE(VisitExpressions(expr->arguments()));
5944592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      AddInstruction(new(zone()) HCheckFunction(function, expr->target()));
59455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
59465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (TryInlineBuiltinFunctionCall(expr, true)) {  // Drop the function.
59475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (FLAG_trace_inlining) {
59485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          PrintF("Inlining builtin ");
59495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          expr->target()->ShortPrint();
59505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          PrintF("\n");
59515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        }
59525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        return;
59535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
59545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
59555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (TryInlineCall(expr, true)) {   // Drop function from environment.
5956592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        return;
5957592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      } else {
5958592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        call = PreProcessCall(new(zone()) HInvokeFunction(context,
5959592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                          function,
5960592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                          argument_count));
5961592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        Drop(1);  // The function.
5962592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
5963592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
5964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
5965592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      CHECK_ALIVE(VisitForValue(expr->expression()));
5966592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      HValue* function = Top();
5967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      HValue* context = environment()->LookupContext();
59688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HGlobalObject* global_object = new(zone()) HGlobalObject(context);
59693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object);
59701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      AddInstruction(global_object);
59713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      AddInstruction(receiver);
59723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      PushAndAdd(new(zone()) HPushArgument(receiver));
59733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      CHECK_ALIVE(VisitArgumentList(expr->arguments()));
5974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5975592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      call = new(zone()) HCallFunction(context, function, argument_count);
59763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Drop(argument_count + 1);
5977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  call->set_position(expr->position());
59813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(call, expr->id());
5982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
59855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch// Checks whether allocation using the given constructor can be inlined.
59865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochstatic bool IsAllocationInlineable(Handle<JSFunction> constructor) {
59875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  return constructor->has_initial_map() &&
59885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      constructor->initial_map()->instance_type() == JS_OBJECT_TYPE;
59895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
59905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
59915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
5992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallNew(CallNew* expr) {
5993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
5994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
5995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
59965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  expr->RecordTypeFeedback(oracle());
59975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int argument_count = expr->arguments()->length() + 1;  // Plus constructor.
5998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
59991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
60005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (FLAG_inline_construct &&
60015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      expr->IsMonomorphic() &&
60025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      IsAllocationInlineable(expr->target())) {
60035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // The constructor function is on the stack in the unoptimized code
60045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // during evaluation of the arguments.
60055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    CHECK_ALIVE(VisitForValue(expr->expression()));
60065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HValue* function = Top();
60075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    CHECK_ALIVE(VisitExpressions(expr->arguments()));
60085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    Handle<JSFunction> constructor = expr->target();
60095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HValue* check = AddInstruction(
60105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        new(zone()) HCheckFunction(function, constructor));
60115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
60125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // Force completion of inobject slack tracking before generating
60135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // allocation code to finalize instance size.
60145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (constructor->shared()->IsInobjectSlackTrackingInProgress()) {
60155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      constructor->shared()->CompleteInobjectSlackTracking();
60165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
60175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
60185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // Replace the constructor function with a newly allocated receiver.
60195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HInstruction* receiver = new(zone()) HAllocateObject(context, constructor);
60205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // Index of the receiver from the top of the expression stack.
60215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    const int receiver_index = argument_count - 1;
60225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    AddInstruction(receiver);
60235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ASSERT(environment()->ExpressionStackAt(receiver_index) == function);
60245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    environment()->SetExpressionStackAt(receiver_index, receiver);
60255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
60265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (TryInlineConstruct(expr, receiver)) return;
60275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
60285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // TODO(mstarzinger): For now we remove the previous HAllocateObject and
60295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // add HPushArgument for the arguments in case inlining failed.  What we
60305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // actually should do is emit HInvokeFunction on the constructor instead
60315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // of using HCallNew as a fallback.
60325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    receiver->DeleteAndReplaceWith(NULL);
60335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    check->DeleteAndReplaceWith(NULL);
60345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    environment()->SetExpressionStackAt(receiver_index, function);
60355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HInstruction* call = PreProcessCall(
60365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        new(zone()) HCallNew(context, function, argument_count));
60375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    call->set_position(expr->position());
60385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return ast_context()->ReturnInstruction(call, expr->id());
60395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  } else {
60405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // The constructor function is both an operand to the instruction and an
60415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // argument to the construct call.
60425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HValue* constructor = NULL;
60435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    CHECK_ALIVE(constructor = VisitArgument(expr->expression()));
60445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    CHECK_ALIVE(VisitArgumentList(expr->arguments()));
60455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HInstruction* call =
60465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        new(zone()) HCallNew(context, constructor, argument_count);
60475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    Drop(argument_count);
60485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    call->set_position(expr->position());
60495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return ast_context()->ReturnInstruction(call, expr->id());
60505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
6051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for generating inlined runtime functions.
6055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Lookup table for generators for runtime calls that are  generated inline.
6057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Elements of the table are member pointers to functions of HGraphBuilder.
6058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize)  \
6059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    &HGraphBuilder::Generate##Name,
6060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst HGraphBuilder::InlineFunctionGenerator
6062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HGraphBuilder::kInlineFunctionGenerators[] = {
6063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
6064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
6065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
6066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef INLINE_FUNCTION_GENERATOR_ADDRESS
6067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
6070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
6073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->is_jsruntime()) {
6074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Bailout("call to a JavaScript runtime function");
6075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
607744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Runtime::Function* function = expr->function();
6078e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(function != NULL);
6079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (function->intrinsic_type == Runtime::INLINE) {
6080e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(expr->name()->length() > 0);
6081e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(expr->name()->Get(0) == '_');
6082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Call to an inline function.
6083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int lookup_index = static_cast<int>(function->function_id) -
6084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        static_cast<int>(Runtime::kFirstInlineFunction);
6085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(lookup_index >= 0);
6086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(static_cast<size_t>(lookup_index) <
6087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           ARRAY_SIZE(kInlineFunctionGenerators));
6088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
6089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Call the inline code generator using the pointer-to-member.
6091e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    (this->*generator)(expr);
6092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
6093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(function->intrinsic_type == Runtime::RUNTIME);
6094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitArgumentList(expr->arguments()));
6095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
60963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HValue* context = environment()->LookupContext();
6097e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Handle<String> name = expr->name();
6098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int argument_count = expr->arguments()->length();
60998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HCallRuntime* call =
61003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        new(zone()) HCallRuntime(context, name, function, argument_count);
6101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    call->set_position(RelocInfo::kNoPosition);
6102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Drop(argument_count);
61033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnInstruction(call, expr->id());
6104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
6109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
6112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  switch (expr->op()) {
6113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::DELETE: return VisitDelete(expr);
6114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::VOID: return VisitVoid(expr);
6115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::TYPEOF: return VisitTypeof(expr);
6116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::ADD: return VisitAdd(expr);
6117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::SUB: return VisitSub(expr);
6118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::BIT_NOT: return VisitBitNot(expr);
6119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::NOT: return VisitNot(expr);
6120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    default: UNREACHABLE();
6121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitDelete(UnaryOperation* expr) {
6125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Property* prop = expr->expression()->AsProperty();
6126589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  VariableProxy* proxy = expr->expression()->AsVariableProxy();
6127589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (prop != NULL) {
612869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CHECK_ALIVE(VisitForValue(prop->obj()));
612969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CHECK_ALIVE(VisitForValue(prop->key()));
613069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    HValue* key = Pop();
613169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    HValue* obj = Pop();
613269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    HValue* context = environment()->LookupContext();
613369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key);
613469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return ast_context()->ReturnInstruction(instr, expr->id());
6135589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL) {
6136589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Variable* var = proxy->var();
6137589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (var->IsUnallocated()) {
6138589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Bailout("delete with global variable");
6139589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else if (var->IsStackAllocated() || var->IsContextSlot()) {
6140589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Result of deleting non-global variables is false.  'this' is not
6141589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // really a variable, though we implement it as one.  The
6142589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // subexpression does not have side effects.
6143589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      HValue* value = var->is_this()
6144589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          ? graph()->GetConstantTrue()
6145589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          : graph()->GetConstantFalse();
6146589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return ast_context()->ReturnValue(value);
6147589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else {
6148589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Bailout("delete with non-global variable");
6149589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
6150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
6151589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Result of deleting non-property, non-variable reference is true.
6152589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Evaluate the subexpression for side effects.
6153589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    CHECK_ALIVE(VisitForEffect(expr->expression()));
6154589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return ast_context()->ReturnValue(graph()->GetConstantTrue());
6155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
615844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitVoid(UnaryOperation* expr) {
6160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForEffect(expr->expression()));
61613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
6162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitTypeof(UnaryOperation* expr) {
6166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForTypeOf(expr->expression()));
6167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* value = Pop();
61683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
61693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* instr = new(zone()) HTypeof(context, value);
61703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
6171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitAdd(UnaryOperation* expr) {
6175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->expression()));
6176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* value = Pop();
61773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
61783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* instr =
61793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HMul(context, value, graph_->GetConstant1());
61803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
6181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitSub(UnaryOperation* expr) {
6185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->expression()));
6186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* value = Pop();
61873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
61883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* instr =
61893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HMul(context, value, graph_->GetConstantMinus1());
6190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TypeInfo info = oracle()->UnaryType(expr);
61913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (info.IsUninitialized()) {
61923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(new(zone()) HSoftDeoptimize);
61933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    current_block()->MarkAsDeoptimizing();
61943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    info = TypeInfo::Unknown();
61953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
6196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Representation rep = ToRepresentation(info);
6197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TraceRepresentation(expr->op(), info, instr, rep);
6198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  instr->AssumeRepresentation(rep);
61993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
6200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitBitNot(UnaryOperation* expr) {
6204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->expression()));
6205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* value = Pop();
62063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  TypeInfo info = oracle()->UnaryType(expr);
62073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (info.IsUninitialized()) {
62083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(new(zone()) HSoftDeoptimize);
62093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    current_block()->MarkAsDeoptimizing();
62103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
6211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HInstruction* instr = new(zone()) HBitNot(value);
62123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
6213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitNot(UnaryOperation* expr) {
6217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (ast_context()->IsTest()) {
6218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TestContext* context = TestContext::cast(ast_context());
6219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VisitForControl(expr->expression(),
6220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    context->if_false(),
6221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    context->if_true());
6222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return;
6223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (ast_context()->IsEffect()) {
6226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VisitForEffect(expr->expression());
6227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return;
6228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(ast_context()->IsValue());
6231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HBasicBlock* materialize_false = graph()->CreateBasicBlock();
6232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HBasicBlock* materialize_true = graph()->CreateBasicBlock();
6233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_BAILOUT(VisitForControl(expr->expression(),
6234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                materialize_false,
6235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                materialize_true));
6236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (materialize_false->HasPredecessor()) {
6238592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    materialize_false->SetJoinId(expr->MaterializeFalseId());
6239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(materialize_false);
6240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Push(graph()->GetConstantFalse());
624144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
6242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    materialize_false = NULL;
6243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (materialize_true->HasPredecessor()) {
6246592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    materialize_true->SetJoinId(expr->MaterializeTrueId());
6247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(materialize_true);
6248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Push(graph()->GetConstantTrue());
6249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
6250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    materialize_true = NULL;
6251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HBasicBlock* join =
6254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CreateJoin(materialize_false, materialize_true, expr->id());
6255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  set_current_block(join);
62563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (join != NULL) return ast_context()->ReturnValue(Pop());
6257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input,
6261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            CountOperation* expr) {
6262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // The input to the count operation is on top of the expression stack.
6263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TypeInfo info = oracle()->IncrementType(expr);
6264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Representation rep = ToRepresentation(info);
6265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (rep.IsTagged()) {
6266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    rep = Representation::Integer32();
6267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (returns_original_input) {
6270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // We need an explicit HValue representing ToNumber(input).  The
6271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // actual HChange instruction we need is (sometimes) added in a later
6272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // phase, so it is not available now to be used as an input to HAdd and
6273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // as the return value.
6274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep);
6275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AddInstruction(number_input);
6276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Push(number_input);
6277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // The addition has no side effects, so we do not need
6280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // to simulate the expression stack after this instruction.
6281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Any later failures deopt to the load of the input or earlier.
6282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HConstant* delta = (expr->op() == Token::INC)
6283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ? graph_->GetConstant1()
6284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : graph_->GetConstantMinus1();
62853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
62863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* instr = new(zone()) HAdd(context, Top(), delta);
6287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TraceRepresentation(expr->op(), info, instr, rep);
6288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  instr->AssumeRepresentation(rep);
6289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AddInstruction(instr);
6290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
6291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCountOperation(CountOperation* expr) {
6295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
62988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Expression* target = expr->expression();
6299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = target->AsVariableProxy();
6300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = target->AsProperty();
6301589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (proxy == NULL && prop == NULL) {
6302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Bailout("invalid lhs in count operation");
6303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Match the full code generator stack by simulating an extra stack
6306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // element for postfix operations in a non-effect context.  The return
6307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // value is ToNumber(input).
6308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool returns_original_input =
6309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      expr->is_postfix() && !ast_context()->IsEffect();
6310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* input = NULL;  // ToNumber(original_input).
6311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* after = NULL;  // The result after incrementing or decrementing.
6312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6313589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (proxy != NULL) {
6314589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Variable* var = proxy->var();
6315592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (var->mode() == CONST)  {
63163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return Bailout("unsupported count operation with const");
63173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
6318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Argument of the count operation is a variable, not a property.
6319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(prop == NULL);
6320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(target));
6321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    after = BuildIncrement(returns_original_input, expr);
6323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    input = returns_original_input ? Top() : Pop();
6324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Push(after);
6325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6326589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    switch (var->location()) {
6327589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::UNALLOCATED:
6328589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HandleGlobalVariableAssignment(var,
6329589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       after,
6330589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       expr->position(),
6331589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       expr->AssignmentId());
6332589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        break;
6333589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
6334589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::PARAMETER:
6335589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::LOCAL:
6336589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Bind(var, after);
6337589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        break;
6338589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
6339589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::CONTEXT: {
6340589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // Bail out if we try to mutate a parameter value in a function
6341589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // using the arguments object.  We do not (yet) correctly handle the
6342589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // arguments property of the function.
6343589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (info()->scope()->arguments() != NULL) {
6344589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // Parameters will rewrite to context slots.  We have no direct
6345589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // way to detect that the variable is a parameter so we use a
6346589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // linear search of the parameter list.
6347589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          int count = info()->scope()->num_parameters();
6348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          for (int i = 0; i < count; ++i) {
6349589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            if (var == info()->scope()->parameter(i)) {
6350589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch              return Bailout("assignment to parameter in arguments object");
6351589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            }
63523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          }
63533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
6354589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
6355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HValue* context = BuildContextChainWalk(var);
6356c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        HStoreContextSlot::Mode mode =
6357c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            (var->mode() == LET || var->mode() == CONST_HARMONY)
6358c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
6359589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HStoreContextSlot* instr =
6360c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch            new(zone()) HStoreContextSlot(context, var->index(), mode, after);
6361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        AddInstruction(instr);
6362592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        if (instr->HasObservableSideEffects()) {
6363592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          AddSimulate(expr->AssignmentId());
6364592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        }
6365589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        break;
63663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
63673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6368589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::LOOKUP:
6369589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return Bailout("lookup variable in count operation");
6370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
6371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
6373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Argument of the count operation is a property.
6374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(prop != NULL);
6375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    prop->RecordTypeFeedback(oracle());
6376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (prop->key()->IsPropertyName()) {
6378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Named property.
6379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (returns_original_input) Push(graph_->GetConstantUndefined());
6380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->obj()));
6382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = Top();
6383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* load = NULL;
6385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (prop->IsMonomorphic()) {
6386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
6387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<Map> map = prop->GetReceiverTypes()->first();
6388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamed(obj, prop, map, name);
6389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
6390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamedGeneric(obj, prop);
6391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
6392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(load);
6393592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (load->HasObservableSideEffects()) AddSimulate(expr->CountId());
6394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      after = BuildIncrement(returns_original_input, expr);
6396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      input = Pop();
6397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* store = BuildStoreNamed(obj, after, prop);
6399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(store);
6400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Overwrite the receiver in the bailout environment with the result
6402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // of the operation, and the placeholder with the original value if
6403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // necessary.
6404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      environment()->SetExpressionStackAt(0, after);
6405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (returns_original_input) environment()->SetExpressionStackAt(1, input);
6406592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId());
6407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
6409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Keyed property.
6410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (returns_original_input) Push(graph_->GetConstantUndefined());
6411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->obj()));
6413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->key()));
6414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = environment()->ExpressionStackAt(1);
6415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* key = environment()->ExpressionStackAt(0);
6416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
64173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bool has_side_effects = false;
64183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HValue* load = HandleKeyedElementAccess(
64193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          obj, key, NULL, prop, expr->CountId(), RelocInfo::kNoPosition,
64203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          false,  // is_store
64213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          &has_side_effects);
64223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Push(load);
64233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (has_side_effects) AddSimulate(expr->CountId());
6424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      after = BuildIncrement(returns_original_input, expr);
6426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      input = Pop();
6427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
64288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      expr->RecordTypeFeedback(oracle());
64293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(),
64303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               RelocInfo::kNoPosition,
64313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               true,  // is_store
64323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               &has_side_effects);
6433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Drop the key from the bailout environment.  Overwrite the receiver
6435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // with the result of the operation, and the placeholder with the
6436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // original value if necessary.
6437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(1);
6438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      environment()->SetExpressionStackAt(0, after);
6439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (returns_original_input) environment()->SetExpressionStackAt(1, input);
64403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(has_side_effects);  // Stores always have side effects.
64413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      AddSimulate(expr->AssignmentId());
6442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
6443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Drop(returns_original_input ? 2 : 1);
64463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
6447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
64503fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context,
64513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                        HValue* string,
64521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                                        HValue* index) {
64538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckNonSmi(string));
6454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AddInstruction(HCheckInstanceType::NewIsString(string));
64558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HStringLength* length = new(zone()) HStringLength(string);
64561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(length);
64577d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  HInstruction* checked_index =
64587d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch      AddInstruction(new(zone()) HBoundsCheck(index, length));
64593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return new(zone()) HStringCharCodeAt(context, string, checked_index);
64601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
64611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
64621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
6464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  HValue* left,
6465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  HValue* right) {
64663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
6467053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  TypeInfo info = oracle()->BinaryType(expr);
64683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (info.IsUninitialized()) {
64693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(new(zone()) HSoftDeoptimize);
64703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    current_block()->MarkAsDeoptimizing();
64713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    info = TypeInfo::Unknown();
64723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
64733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* instr = NULL;
64743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (expr->op()) {
64753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::ADD:
64763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (info.IsString()) {
64773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AddInstruction(new(zone()) HCheckNonSmi(left));
64783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AddInstruction(HCheckInstanceType::NewIsString(left));
64793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AddInstruction(new(zone()) HCheckNonSmi(right));
64803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AddInstruction(HCheckInstanceType::NewIsString(right));
64813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        instr = new(zone()) HStringAdd(context, left, right);
64823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
6483592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        instr = HAdd::NewHAdd(zone(), context, left, right);
64843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
64853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
64863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::SUB:
6487592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      instr = HSub::NewHSub(zone(), context, left, right);
64883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
64893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::MUL:
6490592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      instr = HMul::NewHMul(zone(), context, left, right);
64913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
64923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::MOD:
6493592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      instr = HMod::NewHMod(zone(), context, left, right);
64943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
64953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::DIV:
6496592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      instr = HDiv::NewHDiv(zone(), context, left, right);
64973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
64983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::BIT_XOR:
64993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::BIT_AND:
65003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::BIT_OR:
6501592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right);
65023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
65033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::SAR:
6504592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      instr = HSar::NewHSar(zone(), context, left, right);
65053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
65063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::SHR:
6507592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      instr = HShr::NewHShr(zone(), context, left, right);
65083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
65093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::SHL:
6510592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      instr = HShl::NewHShl(zone(), context, left, right);
65113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
65123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    default:
65133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      UNREACHABLE();
65143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
65153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If we hit an uninitialized binary op stub we will get type info
6517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // for a smi operation. If one of the operands is a constant string
6518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // do not generate code assuming it is a smi operation.
6519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsSmi() &&
6520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) ||
6521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch       (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) {
6522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return instr;
6523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
65241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Representation rep = ToRepresentation(info);
65251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We only generate either int32 or generic tagged bitwise operations.
65261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) {
65271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    rep = Representation::Integer32();
65281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
6529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TraceRepresentation(expr->op(), info, instr, rep);
6530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  instr->AssumeRepresentation(rep);
6531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
6532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check for the form (%_ClassOf(foo) === 'BarClass').
6536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool IsClassOfTest(CompareOperation* expr) {
6537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->op() != Token::EQ_STRICT) return false;
6538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CallRuntime* call = expr->left()->AsCallRuntime();
6539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (call == NULL) return false;
6540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Literal* literal = expr->right()->AsLiteral();
6541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (literal == NULL) return false;
6542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!literal->handle()->IsString()) return false;
6543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false;
6544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(call->arguments()->length() == 1);
6545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
6546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
6550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
6553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  switch (expr->op()) {
65543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::COMMA:
65553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return VisitComma(expr);
65563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::OR:
65573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::AND:
65583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return VisitLogicalExpression(expr);
65593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    default:
65603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return VisitArithmeticExpression(expr);
6561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitComma(BinaryOperation* expr) {
6566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForEffect(expr->left()));
6567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Visit the right subexpression in the same AST context as the entire
6568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // expression.
6569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Visit(expr->right());
6570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
6572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
65733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
65743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool is_logical_and = expr->op() == Token::AND;
6575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (ast_context()->IsTest()) {
6576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TestContext* context = TestContext::cast(ast_context());
6577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Translate left subexpression.
6578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* eval_right = graph()->CreateBasicBlock();
6579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (is_logical_and) {
6580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(VisitForControl(expr->left(),
6581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    eval_right,
6582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    context->if_false()));
6583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
6584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(VisitForControl(expr->left(),
6585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    context->if_true(),
6586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    eval_right));
6587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
6588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Translate right subexpression by visiting it in the same AST
6590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // context as the entire expression.
6591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (eval_right->HasPredecessor()) {
6592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      eval_right->SetJoinId(expr->RightId());
6593e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(eval_right);
6594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Visit(expr->right());
6595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
6596e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
6597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (ast_context()->IsValue()) {
6598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->left()));
6599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(current_block() != NULL);
6600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // We need an extra block to maintain edge-split form.
6602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* empty_block = graph()->CreateBasicBlock();
6603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* eval_right = graph()->CreateBasicBlock();
660469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    unsigned test_id = expr->left()->test_id();
660569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    ToBooleanStub::Types expected(oracle()->ToBooleanTypes(test_id));
66063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HBranch* test = is_logical_and
660769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      ? new(zone()) HBranch(Top(), eval_right, empty_block, expected)
660869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      : new(zone()) HBranch(Top(), empty_block, eval_right, expected);
6609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    current_block()->Finish(test);
6610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(eval_right);
6612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Drop(1);  // Value of the left subexpression.
6613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(VisitForValue(expr->right()));
6614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* join_block =
6616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CreateJoin(empty_block, current_block(), expr->id());
6617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(join_block);
66183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnValue(Pop());
6619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
6620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
6621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(ast_context()->IsEffect());
6622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // In an effect context, we don't need the value of the left subexpression,
6623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // only its control flow and side effects.  We need an extra block to
6624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // maintain edge-split form.
6625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* empty_block = graph()->CreateBasicBlock();
6626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* right_block = graph()->CreateBasicBlock();
6627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (is_logical_and) {
6628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
6629e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
6630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
6631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
6632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // TODO(kmillikin): Find a way to fix this.  It's ugly that there are
6634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // actually two empty blocks (one here and one inserted by
6635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // TestContext::BuildBranch, and that they both have an HSimulate though the
6636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // second one is not a merge node, and that we really have no good AST ID to
6637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // put on that first HSimulate.
6638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (empty_block->HasPredecessor()) {
6640053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block      empty_block->SetJoinId(expr->id());
6641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
6642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      empty_block = NULL;
6643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
6644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (right_block->HasPredecessor()) {
6646053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block      right_block->SetJoinId(expr->RightId());
6647053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block      set_current_block(right_block);
6648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(VisitForEffect(expr->right()));
6649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      right_block = current_block();
6650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
6651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      right_block = NULL;
6652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
6653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* join_block =
6655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CreateJoin(empty_block, right_block, expr->id());
6656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(join_block);
6657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // We did not materialize any value in the predecessor environments,
6658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // so there is no need to handle it here.
6659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
66633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
6664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->left()));
6665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->right()));
6666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* right = Pop();
6667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* left = Pop();
6668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HInstruction* instr = BuildBinaryOperation(expr, left, right);
6669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  instr->set_position(expr->position());
66703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
6671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::TraceRepresentation(Token::Value op,
6675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        TypeInfo info,
6676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        HValue* value,
6677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        Representation rep) {
6678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!FLAG_trace_representation) return;
6679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // TODO(svenpanne) Under which circumstances are we actually not flexible?
6680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // At first glance, this looks a bit weird...
6681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool flexible = value->CheckFlag(HValue::kFlexibleRepresentation);
6682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  PrintF("Operation %s has type info %s, %schange representation assumption "
6683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         "for %s (ID %d) from %s to %s\n",
6684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         Token::Name(op),
6685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         info.ToString(),
6686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         flexible ? "" : " DO NOT ",
6687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         value->Mnemonic(),
6688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         graph_->GetMaximumValueID(),
6689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         value->representation().Mnemonic(),
6690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         rep.Mnemonic());
6691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochRepresentation HGraphBuilder::ToRepresentation(TypeInfo info) {
6695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsSmi()) return Representation::Integer32();
6696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsInteger32()) return Representation::Integer32();
6697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsDouble()) return Representation::Double();
6698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsNumber()) return Representation::Double();
6699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Representation::Tagged();
6700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6703592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
6704592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                               HTypeof* typeof_expr,
67053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                               Handle<String> check) {
6706592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Note: The HTypeof itself is removed during canonicalization, if possible.
6707592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HValue* value = typeof_expr->value();
6708592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check);
6709592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  instr->set_position(expr->position());
6710592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return ast_context()->ReturnControl(instr, expr->id());
67113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
67123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
67133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6714592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic bool MatchLiteralCompareNil(HValue* left,
6715592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                   Token::Value op,
6716592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                   HValue* right,
6717592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                   Handle<Object> nil,
6718592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                   HValue** expr) {
6719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (left->IsConstant() &&
6720592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      HConstant::cast(left)->handle().is_identical_to(nil) &&
6721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Token::IsEqualityOp(op)) {
6722592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    *expr = right;
6723592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return true;
6724592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
6725592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return false;
6726592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
6727592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
6728592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
6729592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic bool MatchLiteralCompareTypeof(HValue* left,
6730592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      Token::Value op,
6731592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      HValue* right,
6732592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      HTypeof** typeof_expr,
6733592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      Handle<String>* check) {
6734592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (left->IsTypeof() &&
6735592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Token::IsEqualityOp(op) &&
6736592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      right->IsConstant() &&
6737592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      HConstant::cast(right)->HasStringValue()) {
6738592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    *typeof_expr = HTypeof::cast(left);
6739592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    *check = Handle<String>::cast(HConstant::cast(right)->handle());
6740592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return true;
6741592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
6742592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return false;
6743592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
6744592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
6745592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
6746592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic bool IsLiteralCompareTypeof(HValue* left,
6747592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                   Token::Value op,
6748592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                   HValue* right,
6749592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                   HTypeof** typeof_expr,
6750592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                   Handle<String>* check) {
6751592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return MatchLiteralCompareTypeof(left, op, right, typeof_expr, check) ||
6752592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      MatchLiteralCompareTypeof(right, op, left, typeof_expr, check);
6753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
6754592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
6755592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
6756592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic bool IsLiteralCompareNil(HValue* left,
6757592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                Token::Value op,
6758592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                HValue* right,
6759592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                Handle<Object> nil,
6760592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                HValue** expr) {
6761592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return MatchLiteralCompareNil(left, op, right, nil, expr) ||
6762592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      MatchLiteralCompareNil(right, op, left, nil, expr);
67633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
67643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
67653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6766c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochstatic bool IsLiteralCompareBool(HValue* left,
6767c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                 Token::Value op,
6768c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                 HValue* right) {
6769c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  return op == Token::EQ_STRICT &&
6770c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) ||
6771c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch       (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean()));
6772c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
6773c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
6774c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
6775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
6776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
6779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (IsClassOfTest(expr)) {
6780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CallRuntime* call = expr->left()->AsCallRuntime();
67813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(call->arguments()->length() == 1);
6782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
6783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = Pop();
6784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Literal* literal = expr->right()->AsLiteral();
6785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> rhs = Handle<String>::cast(literal->handle());
67863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HClassOfTestAndBranch* instr =
67873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        new(zone()) HClassOfTestAndBranch(value, rhs);
6788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_position(expr->position());
67893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnControl(instr, expr->id());
67903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
67913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
67923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  TypeInfo type_info = oracle()->CompareType(expr);
67933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check if this expression was ever executed according to type feedback.
6794592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Note that for the special typeof/null/undefined cases we get unknown here.
67953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (type_info.IsUninitialized()) {
67963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(new(zone()) HSoftDeoptimize);
67973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    current_block()->MarkAsDeoptimizing();
67983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    type_info = TypeInfo::Unknown();
67993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
68003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->left()));
6802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->right()));
6803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
68043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
6805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* right = Pop();
6806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* left = Pop();
6807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Token::Value op = expr->op();
6808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6809592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HTypeof* typeof_expr = NULL;
6810592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<String> check;
6811592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (IsLiteralCompareTypeof(left, op, right, &typeof_expr, &check)) {
6812592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return HandleLiteralCompareTypeof(expr, typeof_expr, check);
6813592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
6814592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HValue* sub_expr = NULL;
6815592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Factory* f = graph()->isolate()->factory();
6816592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (IsLiteralCompareNil(left, op, right, f->undefined_value(), &sub_expr)) {
6817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
6818592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
6819592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (IsLiteralCompareNil(left, op, right, f->null_value(), &sub_expr)) {
6820592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
6821592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
6822c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  if (IsLiteralCompareBool(left, op, right)) {
6823c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    HCompareObjectEqAndBranch* result =
6824c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        new(zone()) HCompareObjectEqAndBranch(left, right);
6825c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    result->set_position(expr->position());
6826c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    return ast_context()->ReturnControl(result, expr->id());
6827c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
6828592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
6829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (op == Token::INSTANCEOF) {
6830086aeeaae12517475c22695a200be45495516549Ben Murdoch    // Check to see if the rhs of the instanceof is a global function not
6831086aeeaae12517475c22695a200be45495516549Ben Murdoch    // residing in new space. If it is we assume that the function will stay the
6832086aeeaae12517475c22695a200be45495516549Ben Murdoch    // same.
6833086aeeaae12517475c22695a200be45495516549Ben Murdoch    Handle<JSFunction> target = Handle<JSFunction>::null();
6834589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    VariableProxy* proxy = expr->right()->AsVariableProxy();
6835589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated();
6836086aeeaae12517475c22695a200be45495516549Ben Murdoch    if (global_function &&
6837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        info()->has_global_object() &&
6838e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        !info()->global_object()->IsAccessCheckNeeded()) {
6839589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Handle<String> name = proxy->name();
6840e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Handle<GlobalObject> global(info()->global_object());
6841592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      LookupResult lookup(isolate());
6842086aeeaae12517475c22695a200be45495516549Ben Murdoch      global->Lookup(*name, &lookup);
6843c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      if (lookup.IsFound() &&
6844086aeeaae12517475c22695a200be45495516549Ben Murdoch          lookup.type() == NORMAL &&
6845086aeeaae12517475c22695a200be45495516549Ben Murdoch          lookup.GetValue()->IsJSFunction()) {
6846086aeeaae12517475c22695a200be45495516549Ben Murdoch        Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
6847086aeeaae12517475c22695a200be45495516549Ben Murdoch        // If the function is in new space we assume it's more likely to
6848086aeeaae12517475c22695a200be45495516549Ben Murdoch        // change and thus prefer the general IC code.
684944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (!isolate()->heap()->InNewSpace(*candidate)) {
6850086aeeaae12517475c22695a200be45495516549Ben Murdoch          target = candidate;
6851086aeeaae12517475c22695a200be45495516549Ben Murdoch        }
6852086aeeaae12517475c22695a200be45495516549Ben Murdoch      }
6853086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
6854086aeeaae12517475c22695a200be45495516549Ben Murdoch
6855086aeeaae12517475c22695a200be45495516549Ben Murdoch    // If the target is not null we have found a known global function that is
6856086aeeaae12517475c22695a200be45495516549Ben Murdoch    // assumed to stay the same for this instanceof.
6857086aeeaae12517475c22695a200be45495516549Ben Murdoch    if (target.is_null()) {
68583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HInstanceOf* result = new(zone()) HInstanceOf(context, left, right);
68593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      result->set_position(expr->position());
68603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnInstruction(result, expr->id());
6861086aeeaae12517475c22695a200be45495516549Ben Murdoch    } else {
68628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      AddInstruction(new(zone()) HCheckFunction(right, target));
68633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HInstanceOfKnownGlobal* result =
68643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          new(zone()) HInstanceOfKnownGlobal(context, left, target);
68653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      result->set_position(expr->position());
68663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnInstruction(result, expr->id());
6867086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
6868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::IN) {
68693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HIn* result = new(zone()) HIn(context, left, right);
68703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    result->set_position(expr->position());
68713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnInstruction(result, expr->id());
6872e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (type_info.IsNonPrimitive()) {
6873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    switch (op) {
6874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case Token::EQ:
6875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case Token::EQ_STRICT: {
6876c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        // Can we get away with map check and not instance type check?
6877c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        Handle<Map> map = oracle()->GetCompareMap(expr);
6878c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        if (!map.is_null()) {
6879c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          AddInstruction(new(zone()) HCheckNonSmi(left));
6880c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          AddInstruction(new(zone()) HCheckMap(left, map, NULL,
6881c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                               ALLOW_ELEMENT_TRANSITION_MAPS));
6882c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          AddInstruction(new(zone()) HCheckNonSmi(right));
6883c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          AddInstruction(new(zone()) HCheckMap(right, map, NULL,
6884c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                               ALLOW_ELEMENT_TRANSITION_MAPS));
6885c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          HCompareObjectEqAndBranch* result =
6886c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch              new(zone()) HCompareObjectEqAndBranch(left, right);
6887c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          result->set_position(expr->position());
6888c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          return ast_context()->ReturnControl(result, expr->id());
6889c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        } else {
6890c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          AddInstruction(new(zone()) HCheckNonSmi(left));
6891c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          AddInstruction(HCheckInstanceType::NewIsSpecObject(left));
6892c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          AddInstruction(new(zone()) HCheckNonSmi(right));
6893c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          AddInstruction(HCheckInstanceType::NewIsSpecObject(right));
6894c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          HCompareObjectEqAndBranch* result =
6895c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch              new(zone()) HCompareObjectEqAndBranch(left, right);
6896c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          result->set_position(expr->position());
6897c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          return ast_context()->ReturnControl(result, expr->id());
6898c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        }
6899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
6900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      default:
6901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return Bailout("Unsupported non-primitive compare");
6902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
6903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) &&
6904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch             (op == Token::EQ || op == Token::EQ_STRICT)) {
69053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(left));
69063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(HCheckInstanceType::NewIsSymbol(left));
69073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(right));
69083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(HCheckInstanceType::NewIsSymbol(right));
69093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HCompareObjectEqAndBranch* result =
69103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        new(zone()) HCompareObjectEqAndBranch(left, right);
69113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    result->set_position(expr->position());
69123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnControl(result, expr->id());
6913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
6914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Representation r = ToRepresentation(type_info);
69153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (r.IsTagged()) {
69163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HCompareGeneric* result =
69173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          new(zone()) HCompareGeneric(context, left, right, op);
69183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      result->set_position(expr->position());
69193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnInstruction(result, expr->id());
69203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
69213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HCompareIDAndBranch* result =
69223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          new(zone()) HCompareIDAndBranch(left, right, op);
69233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      result->set_position(expr->position());
69243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      result->SetInputRepresentation(r);
69253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnControl(result, expr->id());
69263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
6927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6931592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
6932592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                            HValue* value,
6933592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                            NilValue nil) {
6934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
6937592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  EqualityKind kind =
6938592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality;
6939592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil);
6940592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  instr->set_position(expr->position());
69413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(instr, expr->id());
6942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
6946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
6949592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HThisFunction* self = new(zone()) HThisFunction(
6950592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      function_state()->compilation_info()->closure());
69513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(self, expr->id());
6952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
69555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
69565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int length = declarations->length();
69575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int global_count = 0;
69585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  for (int i = 0; i < declarations->length(); i++) {
69595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    Declaration* decl = declarations->at(i);
69605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration();
69615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HandleDeclaration(decl->proxy(),
69625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                      decl->mode(),
69635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                      fun_decl != NULL ? fun_decl->fun() : NULL,
69645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                      &global_count);
69655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
69665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
69675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // Batch declare global functions and variables.
69685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (global_count > 0) {
69695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    Handle<FixedArray> array =
69705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        isolate()->factory()->NewFixedArray(2 * global_count, TENURED);
69715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    for (int j = 0, i = 0; i < length; i++) {
69725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      Declaration* decl = declarations->at(i);
69735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      Variable* var = decl->proxy()->var();
69745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
69755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (var->IsUnallocated()) {
69765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        array->set(j++, *(var->name()));
69775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration();
69785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (fun_decl == NULL) {
69795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          if (var->binding_needs_init()) {
69805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            // In case this binding needs initialization use the hole.
69815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            array->set_the_hole(j++);
69825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          } else {
69835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            array->set_undefined(j++);
69845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          }
69855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        } else {
69865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          Handle<SharedFunctionInfo> function =
69875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch              Compiler::BuildFunctionInfo(fun_decl->fun(), info()->script());
69885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          // Check for stack-overflow exception.
69895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          if (function.is_null()) {
69905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            SetStackOverflow();
69915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            return;
69925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          }
69935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          array->set(j++, *function);
69945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        }
69955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
69965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
69975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
69985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                DeclareGlobalsNativeFlag::encode(info()->is_native()) |
69995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                DeclareGlobalsLanguageMode::encode(info()->language_mode());
70005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HInstruction* result =
70015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        new(zone()) HDeclareGlobals(environment()->LookupContext(),
70025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    array,
70035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    flags);
70045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    AddInstruction(result);
70055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
7006589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
7007589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
7008589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
7009589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
7010592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      VariableMode mode,
70115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      FunctionLiteral* function,
70125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      int* global_count) {
7013589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Variable* var = proxy->var();
7014c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  bool binding_needs_init =
7015c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      (mode == CONST || mode == CONST_HARMONY || mode == LET);
7016589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (var->location()) {
7017589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::UNALLOCATED:
70185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ++(*global_count);
70195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      return;
7020589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::PARAMETER:
7021589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOCAL:
7022589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::CONTEXT:
7023c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      if (binding_needs_init || function != NULL) {
7024589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HValue* value = NULL;
7025c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        if (function != NULL) {
70265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          CHECK_ALIVE(VisitForValue(function));
7027589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          value = Pop();
7028c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        } else {
7029c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          value = graph()->GetConstantHole();
7030589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        }
7031589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (var->IsContextSlot()) {
7032589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          HValue* context = environment()->LookupContext();
7033c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch          HStoreContextSlot* store = new HStoreContextSlot(
7034c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch              context, var->index(), HStoreContextSlot::kNoCheck, value);
7035589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          AddInstruction(store);
7036592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          if (store->HasObservableSideEffects()) AddSimulate(proxy->id());
7037589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        } else {
7038589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          environment()->Bind(var, value);
7039589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        }
7040589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
7041589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
7042589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOOKUP:
7043589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return Bailout("unsupported lookup slot in declaration");
70443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
7045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
70485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
70495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  UNREACHABLE();
70505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
70515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
70545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  UNREACHABLE();
70555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
70565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) {
70595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  UNREACHABLE();
70605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
70615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
70645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  UNREACHABLE();
70655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
70665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
70695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  UNREACHABLE();
70705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
70715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) {
70745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // TODO(rossberg)
70755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
70765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitModuleVariable(ModuleVariable* module) {
70795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // TODO(rossberg)
70805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
70815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitModulePath(ModulePath* module) {
70845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // TODO(rossberg)
70855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
70865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitModuleUrl(ModuleUrl* module) {
70895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // TODO(rossberg)
70905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
70915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
70925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
7093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Generators for inline runtime functions.
7094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for types.
7095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsSmi(CallRuntime* call) {
7096e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
70993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value);
71003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
7105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
71083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HHasInstanceTypeAndBranch* result =
71093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HHasInstanceTypeAndBranch(value,
71103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                            FIRST_SPEC_OBJECT_TYPE,
71113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                            LAST_SPEC_OBJECT_TYPE);
71123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsFunction(CallRuntime* call) {
7117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
71203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HHasInstanceTypeAndBranch* result =
7121592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE);
71223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
7127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
71303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HHasCachedArrayIndexAndBranch* result =
71313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HHasCachedArrayIndexAndBranch(value);
71323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsArray(CallRuntime* call) {
7137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
71403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HHasInstanceTypeAndBranch* result =
71413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE);
71423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
7147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
71503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HHasInstanceTypeAndBranch* result =
71513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE);
71523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsObject(CallRuntime* call) {
7157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
71603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value);
71613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
7166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("inlined runtime function: IsNonNegativeSmi");
7167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
7171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(call->arguments()->length() == 1);
7172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* value = Pop();
71743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HIsUndetectableAndBranch* result =
71753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HIsUndetectableAndBranch(value);
71763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
7181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    CallRuntime* call) {
7182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout(
7183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
7184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
71871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Support for construct call checks.
7188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
7189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 0);
71908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (function_state()->outer() != NULL) {
71915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // We are generating graph for inlined function.
71925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    HValue* value = function_state()->is_construct()
71935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ? graph()->GetConstantTrue()
71945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        : graph()->GetConstantFalse();
71955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return ast_context()->ReturnValue(value);
71968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
71973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch,
71983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                        call->id());
71998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
7200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for arguments.length and arguments[?].
7204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
720542effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // Our implementation of arguments (based on this stack frame or an
720642effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // adapter below it) does not work for inlined functions.  This runtime
720742effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // function is blacklisted by AstNode::IsInlineable.
720842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  ASSERT(function_state()->outer() == NULL);
7209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 0);
72108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
72118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HArgumentsLength* result = new(zone()) HArgumentsLength(elements);
72123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateArguments(CallRuntime* call) {
721742effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // Our implementation of arguments (based on this stack frame or an
721842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // adapter below it) does not work for inlined functions.  This runtime
721942effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // function is blacklisted by AstNode::IsInlineable.
722042effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  ASSERT(function_state()->outer() == NULL);
7221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* index = Pop();
72248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
72258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements));
72268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HAccessArgumentsAt* result =
72278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HAccessArgumentsAt(elements, length, index);
72283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for accessing the class and value fields of an object.
7233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateClassOf(CallRuntime* call) {
7234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The special form detected by IsClassOfTest is detected before we get here
7235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // and does not cause a bailout.
7236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("inlined runtime function: ClassOf");
7237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateValueOf(CallRuntime* call) {
7241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
72448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HValueOf* result = new(zone()) HValueOf(value);
72453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
72495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::GenerateDateField(CallRuntime* call) {
72505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT(call->arguments()->length() == 2);
72515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral());
72525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle()));
72535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
72545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HValue* date = Pop();
72555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HDateField* result = new(zone()) HDateField(date, index);
72565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  return ast_context()->ReturnInstruction(result, call->id());
72575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
72585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
72595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
7260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
7261592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  ASSERT(call->arguments()->length() == 2);
7262592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7263592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
7264592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HValue* value = Pop();
7265592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HValue* object = Pop();
7266592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Check if object is a not a smi.
7267592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(object);
7268592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HBasicBlock* if_smi = graph()->CreateBasicBlock();
7269592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HBasicBlock* if_heap_object = graph()->CreateBasicBlock();
7270592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HBasicBlock* join = graph()->CreateBasicBlock();
7271592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  smicheck->SetSuccessorAt(0, if_smi);
7272592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  smicheck->SetSuccessorAt(1, if_heap_object);
7273592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  current_block()->Finish(smicheck);
7274592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if_smi->Goto(join);
7275592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
7276592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Check if object is a JSValue.
7277592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  set_current_block(if_heap_object);
7278592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HHasInstanceTypeAndBranch* typecheck =
7279592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE);
7280592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HBasicBlock* if_js_value = graph()->CreateBasicBlock();
7281592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HBasicBlock* not_js_value = graph()->CreateBasicBlock();
7282592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  typecheck->SetSuccessorAt(0, if_js_value);
7283592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  typecheck->SetSuccessorAt(1, not_js_value);
7284592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  current_block()->Finish(typecheck);
7285592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  not_js_value->Goto(join);
7286592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
7287592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Create in-object property store to kValueOffset.
7288592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  set_current_block(if_js_value);
7289592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<String> name = isolate()->factory()->undefined_symbol();
7290592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  AddInstruction(new HStoreNamedField(object,
7291592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      name,
7292592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      value,
7293592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      true,  // in-object store.
7294592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      JSValue::kValueOffset));
7295592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if_js_value->Goto(join);
7296592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  join->SetJoinId(call->id());
7297592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  set_current_block(join);
7298592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return ast_context()->ReturnValue(value);
7299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for charCodeAt(n).
7303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
7304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 2);
7305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
73071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  HValue* index = Pop();
73081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  HValue* string = Pop();
73093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
73103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HStringCharCodeAt* result = BuildStringCharCodeAt(context, string, index);
73113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n].
7316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
731744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(call->arguments()->length() == 1);
7318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
731944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HValue* char_code = Pop();
73203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
73213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HStringCharFromCode* result =
73223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HStringCharFromCode(context, char_code);
73233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n].
7328e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
732944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(call->arguments()->length() == 2);
7330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
733244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HValue* index = Pop();
733344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HValue* string = Pop();
73343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
73353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index);
733644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  AddInstruction(char_code);
73373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HStringCharFromCode* result =
73383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HStringCharFromCode(context, char_code);
73393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for object equality testing.
7344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
7345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 2);
7346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
7348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* right = Pop();
7349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* left = Pop();
73503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HCompareObjectEqAndBranch* result =
73513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HCompareObjectEqAndBranch(left, right);
73523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7356e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateLog(CallRuntime* call) {
7357e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // %_Log is ignored in optimized code.
73583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
7359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for Math.random().
7363e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
7364c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  HValue* context = environment()->LookupContext();
7365c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  HGlobalObject* global_object = new(zone()) HGlobalObject(context);
7366c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  AddInstruction(global_object);
7367c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  HRandom* result = new(zone()) HRandom(global_object);
7368c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringAdd.
7373e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringAdd(CallRuntime* call) {
7374e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(2, call->arguments()->length());
7375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
73778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2);
7378e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(2);
73793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for SubString.
7384e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSubString(CallRuntime* call) {
7385e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(3, call->arguments()->length());
7386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
73888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3);
7389e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(3);
73903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringCompare.
7395e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCompare(CallRuntime* call) {
7396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(2, call->arguments()->length());
7397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
73998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
74008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::StringCompare, 2);
7401e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(2);
74023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for direct calls from JavaScript to native RegExp code.
7407e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
7408e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(4, call->arguments()->length());
7409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
74118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4);
7412e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(4);
74133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Construct a RegExp exec result with two in-object properties.
7418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
7419e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(3, call->arguments()->length());
7420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
7422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCallStub* result =
74238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3);
7424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(3);
74253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for fast native caches.
7430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
7431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("inlined runtime function: GetFromCache");
7432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for number to string.
7436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateNumberToString(CallRuntime* call) {
7437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(1, call->arguments()->length());
7438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
74408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
74418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::NumberToString, 1);
7442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(1);
74433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast swapping of elements. Takes three expressions, the object and two
7448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// indices. This should only be used if the indices are known to be
7449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// non-negative and within bounds of the elements array at the call site.
7450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSwapElements(CallRuntime* call) {
7451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("inlined runtime function: SwapElements");
7452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call for custom callbacks.
7456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateCallFunction(CallRuntime* call) {
7457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // 1 ~ The function to call is not itself an argument to the call.
7458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int arg_count = call->arguments()->length() - 1;
7459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(arg_count >= 1);  // There's always at least a receiver.
7460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < arg_count; ++i) {
7462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitArgument(call->arguments()->at(i)));
7463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
7464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->last()));
7465592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
7466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* function = Pop();
7467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
7468592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
7469592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Branch for function proxies, or other non-functions.
7470592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HHasInstanceTypeAndBranch* typecheck =
7471592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE);
7472592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HBasicBlock* if_jsfunction = graph()->CreateBasicBlock();
7473592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HBasicBlock* if_nonfunction = graph()->CreateBasicBlock();
7474592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HBasicBlock* join = graph()->CreateBasicBlock();
7475592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  typecheck->SetSuccessorAt(0, if_jsfunction);
7476592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  typecheck->SetSuccessorAt(1, if_nonfunction);
7477592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  current_block()->Finish(typecheck);
7478592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
7479592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  set_current_block(if_jsfunction);
7480592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HInstruction* invoke_result = AddInstruction(
7481592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      new(zone()) HInvokeFunction(context, function, arg_count));
7482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Drop(arg_count);
7483592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Push(invoke_result);
7484592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if_jsfunction->Goto(join);
7485592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
7486592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  set_current_block(if_nonfunction);
7487592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HInstruction* call_result = AddInstruction(
7488592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      new(zone()) HCallFunction(context, function, arg_count));
7489592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Drop(arg_count);
7490592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Push(call_result);
7491592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if_nonfunction->Goto(join);
7492592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
7493592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  set_current_block(join);
7494592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  join->SetJoinId(call->id());
7495592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return ast_context()->ReturnValue(Pop());
7496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call to math functions.
7500e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathPow(CallRuntime* call) {
7501e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(2, call->arguments()->length());
7502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
7504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* right = Pop();
7505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* left = Pop();
75068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HPower* result = new(zone()) HPower(left, right);
75073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7511e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathSin(CallRuntime* call) {
7512e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(1, call->arguments()->length());
7513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
75158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
75168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
7517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->set_transcendental_type(TranscendentalCache::SIN);
7518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(1);
75193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathCos(CallRuntime* call) {
7524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(1, call->arguments()->length());
7525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
75278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
75288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
7529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->set_transcendental_type(TranscendentalCache::COS);
7530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(1);
75313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7535592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid HGraphBuilder::GenerateMathTan(CallRuntime* call) {
7536592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  ASSERT_EQ(1, call->arguments()->length());
7537592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7538592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HValue* context = environment()->LookupContext();
7539592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HCallStub* result =
7540592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
7541592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  result->set_transcendental_type(TranscendentalCache::TAN);
7542592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Drop(1);
7543592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7544592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
7545592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
7546592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
7547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathLog(CallRuntime* call) {
7548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(1, call->arguments()->length());
7549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
75518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
75528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
7553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->set_transcendental_type(TranscendentalCache::LOG);
7554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(1);
75553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
7560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("inlined runtime function: MathSqrt");
7561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check whether two RegExps are equivalent
7565e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
7566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("inlined runtime function: IsRegExpEquivalent");
7567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7570e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
7571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HValue* value = Pop();
75748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value);
75753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
7580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("inlined runtime function: FastAsciiArrayJoin");
7581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef CHECK_BAILOUT
7585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#undef CHECK_ALIVE
7586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(HEnvironment* outer,
7589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           Scope* scope,
7590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           Handle<JSFunction> closure)
7591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : closure_(closure),
7592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      values_(0),
7593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      assigned_variables_(4),
75945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      frame_type_(JS_FUNCTION),
7595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parameter_count_(0),
7596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      specials_count_(1),
7597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      local_count_(0),
7598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_(outer),
7599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      pop_count_(0),
7600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      push_count_(0),
76015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ast_id_(AstNode::kNoNumber) {
7602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0);
7603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(const HEnvironment* other)
7607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : values_(0),
7608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      assigned_variables_(0),
76095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      frame_type_(JS_FUNCTION),
7610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parameter_count_(0),
7611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      specials_count_(1),
7612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      local_count_(0),
7613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_(NULL),
7614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      pop_count_(0),
7615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      push_count_(0),
76165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ast_id_(other->ast_id()) {
7617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Initialize(other);
7618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7621c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben MurdochHEnvironment::HEnvironment(HEnvironment* outer,
7622c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                           Handle<JSFunction> closure,
76235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                           FrameType frame_type,
7624c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                           int arguments)
7625c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    : closure_(closure),
7626c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      values_(arguments),
7627c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      assigned_variables_(0),
76285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      frame_type_(frame_type),
7629c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      parameter_count_(arguments),
7630c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      local_count_(0),
7631c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      outer_(outer),
7632c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      pop_count_(0),
7633c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      push_count_(0),
76345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ast_id_(AstNode::kNoNumber) {
7635c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
7636c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
7637c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
7638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::Initialize(int parameter_count,
7639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              int local_count,
7640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              int stack_height) {
7641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  parameter_count_ = parameter_count;
7642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  local_count_ = local_count;
7643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Avoid reallocating the temporaries' backing store on the first Push.
7645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int total = parameter_count + specials_count_ + local_count + stack_height;
7646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  values_.Initialize(total + 4);
7647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < total; ++i) values_.Add(NULL);
7648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
76519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Initialize(const HEnvironment* other) {
76529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  closure_ = other->closure();
76539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  values_.AddAll(other->values_);
76549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  assigned_variables_.AddAll(other->assigned_variables_);
76555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  frame_type_ = other->frame_type_;
76569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  parameter_count_ = other->parameter_count_;
76579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  local_count_ = other->local_count_;
76589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (other->outer_ != NULL) outer_ = other->outer_->Copy();  // Deep copy.
76599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  pop_count_ = other->pop_count_;
76609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  push_count_ = other->push_count_;
76619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ast_id_ = other->ast_id_;
76629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
76639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
76649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
7665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
7666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!block->IsLoopHeader());
7667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(values_.length() == other->values_.length());
7668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = values_.length();
7670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; ++i) {
7671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = values_[i];
7672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (value != NULL && value->IsPhi() && value->block() == block) {
7673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // There is already a phi for the i'th value.
7674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = HPhi::cast(value);
7675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Assert index is correct and that we haven't missed an incoming edge.
7676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(phi->merged_index() == i);
7677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(phi->OperandCount() == block->predecessors()->length());
7678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->AddInput(other->values_[i]);
7679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (values_[i] != other->values_[i]) {
7680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // There is a fresh value on the incoming edge, a phi is needed.
7681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(values_[i] != NULL && other->values_[i] != NULL);
76828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HPhi* phi = new(block->zone()) HPhi(i);
7683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* old_value = values_[i];
7684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < block->predecessors()->length(); j++) {
7685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->AddInput(old_value);
7686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
7687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->AddInput(other->values_[i]);
7688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      this->values_[i] = phi;
7689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->AddPhi(phi);
7690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
76959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Bind(int index, HValue* value) {
76969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(value != NULL);
76979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (!assigned_variables_.Contains(index)) {
76989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    assigned_variables_.Add(index);
76999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
77009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  values_[index] = value;
7701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
77049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::HasExpressionAt(int index) const {
7705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return index >= parameter_count_ + specials_count_ + local_count_;
77069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
77079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
77089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
77099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::ExpressionStackIsEmpty() const {
77105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT(length() >= first_expression_index());
77115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  return length() == first_expression_index();
77129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
77139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
77149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
77159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
77169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  int count = index_from_top + 1;
77179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  int index = values_.length() - count;
77189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(HasExpressionAt(index));
77199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // The push count must include at least the element in question or else
77209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // the new value will not be included in this environment's history.
77219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (push_count_ < count) {
77229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // This is the same effect as popping then re-pushing 'count' elements.
77239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    pop_count_ += (count - push_count_);
77249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    push_count_ = count;
77259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
77269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  values_[index] = value;
77279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
77289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
77299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
77309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Drop(int count) {
77319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  for (int i = 0; i < count; ++i) {
77329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Pop();
7733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::Copy() const {
77388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(closure()->GetIsolate()->zone()) HEnvironment(this);
7739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyWithoutHistory() const {
7743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* result = Copy();
7744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->ClearHistory();
7745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
7746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
7750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* new_env = Copy();
7751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < values_.length(); ++i) {
77528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HPhi* phi = new(loop_header->zone()) HPhi(i);
7753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    phi->AddInput(values_[i]);
7754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_env->values_[i] = phi;
7755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    loop_header->AddPhi(phi);
7756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  new_env->ClearHistory();
7758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return new_env;
7759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
77625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen MurdochHEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
77635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                                  Handle<JSFunction> target,
77645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                                  FrameType frame_type,
77655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                                  int arguments) const {
77665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  HEnvironment* new_env = new(closure()->GetIsolate()->zone())
77675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      HEnvironment(outer, target, frame_type, arguments + 1);
77685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  for (int i = 0; i <= arguments; ++i) {  // Include receiver.
77695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    new_env->Push(ExpressionStackAt(arguments - i));
77705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
77715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  new_env->ClearHistory();
77725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  return new_env;
77735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
77745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
77755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
7776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHEnvironment* HEnvironment::CopyForInlining(
7777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<JSFunction> target,
7778c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    int arguments,
7779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    FunctionLiteral* function,
7780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HConstant* undefined,
77815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    CallKind call_kind,
77825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    bool is_construct) const {
77835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT(frame_type() == JS_FUNCTION);
7784c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
7785c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  Zone* zone = closure()->GetIsolate()->zone();
7786c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
7787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Outer environment is a copy of this one without the arguments.
7788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int arity = function->scope()->num_parameters();
7789c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
7790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* outer = Copy();
7791c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  outer->Drop(arguments + 1);  // Including receiver.
7792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  outer->ClearHistory();
7793c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
77945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (is_construct) {
77955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // Create artificial constructor stub environment.  The receiver should
77965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // actually be the constructor function, but we pass the newly allocated
77975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // object instead, DoComputeConstructStubFrame() relies on that.
77985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
77995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
78005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
7801c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  if (arity != arguments) {
7802c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    // Create artificial arguments adaptation environment.
78035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
7804c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
7805c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
78068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HEnvironment* inner =
78078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone) HEnvironment(outer, function->scope(), target);
7808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Get the argument values from the original environment.
78093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i <= arity; ++i) {  // Include receiver.
7810c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    HValue* push = (i <= arguments) ?
7811c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        ExpressionStackAt(arguments - i) : undefined;
78123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    inner->SetValueAt(i, push);
78133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
78143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // If the function we are inlining is a strict mode function or a
78153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // builtin function, pass undefined as the receiver for function
78163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // calls (instead of the global receiver).
7817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if ((target->shared()->native() || !function->is_classic_mode()) &&
78185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      call_kind == CALL_AS_FUNCTION && !is_construct) {
7819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    inner->SetValueAt(0, undefined);
7820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
7821c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  inner->SetValueAt(arity + 1, LookupContext());
7822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = arity + 2; i < inner->length(); ++i) {
7823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    inner->SetValueAt(i, undefined);
7824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
78268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  inner->set_ast_id(AstNode::kFunctionEntryId);
7827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return inner;
7828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintTo(StringStream* stream) {
78329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  for (int i = 0; i < length(); i++) {
7833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (i == 0) stream->Add("parameters\n");
7834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (i == parameter_count()) stream->Add("specials\n");
7835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (i == parameter_count() + specials_count()) stream->Add("locals\n");
7836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (i == parameter_count() + specials_count() + local_count()) {
7837c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      stream->Add("expressions\n");
7838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
7839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* val = values_.at(i);
7840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    stream->Add("%d: ", i);
7841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (val != NULL) {
7842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      val->PrintNameTo(stream);
7843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
7844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      stream->Add("NULL");
7845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    stream->Add("\n");
7847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7848c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  PrintF("\n");
7849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintToStd() {
7853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HeapStringAllocator string_allocator;
7854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StringStream trace(&string_allocator);
7855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintTo(&trace);
7856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("%s", *trace.ToCString());
7857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceCompilation(FunctionLiteral* function) {
7861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Tag tag(this, "compilation");
7862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<String> name = function->debug_name();
7863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("name", *name->ToCString());
7864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("method", *name->ToCString());
7865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis()));
7866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLithium(const char* name, LChunk* chunk) {
7870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Trace(name, chunk->graph(), chunk);
7871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceHydrogen(const char* name, HGraph* graph) {
7875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Trace(name, graph, NULL);
7876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
7880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Tag tag(this, "cfg");
7881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("name", name);
7882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<HBasicBlock*>* blocks = graph->blocks();
7883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks->length(); i++) {
7884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* current = blocks->at(i);
7885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Tag block_tag(this, "block");
7886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintBlockProperty("name", current->block_id());
7887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintIntProperty("from_bci", -1);
7888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintIntProperty("to_bci", -1);
7889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!current->predecessors()->is_empty()) {
7891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintIndent();
7892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add("predecessors");
7893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < current->predecessors()->length(); ++j) {
7894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
7895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
7896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add("\n");
7897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
7898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintEmptyProperty("predecessors");
7899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
79013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (current->end()->SuccessorCount() == 0) {
7902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintEmptyProperty("successors");
79033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else  {
79043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      PrintIndent();
79053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      trace_.Add("successors");
79063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
79073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        trace_.Add(" \"B%d\"", it.Current()->block_id());
79083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
79093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      trace_.Add("\n");
7910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintEmptyProperty("xhandlers");
79135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    const char* flags = current->IsLoopSuccessorDominator()
79145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ? "dom-loop-succ"
79155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        : "";
79165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    PrintStringProperty("flags", flags);
7917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->dominator() != NULL) {
7919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintBlockProperty("dominator", current->dominator()->block_id());
7920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7922589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    PrintIntProperty("loop_depth", current->LoopNestingDepth());
7923589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
7924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (chunk != NULL) {
7925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int first_index = current->first_instruction_index();
7926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int last_index = current->last_instruction_index();
7927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintIntProperty(
7928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          "first_lir_id",
7929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          LifetimePosition::FromInstructionIndex(first_index).Value());
7930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintIntProperty(
7931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          "last_lir_id",
7932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          LifetimePosition::FromInstructionIndex(last_index).Value());
7933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    {
7936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag states_tag(this, "states");
7937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag locals_tag(this, "locals");
7938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int total = current->phis()->length();
7939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      PrintIntProperty("size", current->phis()->length());
7940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      PrintStringProperty("method", "None");
7941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < total; ++j) {
7942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HPhi* phi = current->phis()->at(j);
7943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        PrintIndent();
7944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add("%d ", phi->merged_index());
7945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->PrintNameTo(&trace_);
7946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" ");
7947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->PrintTo(&trace_);
7948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add("\n");
7949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
7950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    {
7953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag HIR_tag(this, "HIR");
7954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instruction = current->first();
7955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      while (instruction != NULL) {
7956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int bci = 0;
7957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        int uses = instruction->UseCount();
7958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        PrintIndent();
7959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add("%d %d ", bci, uses);
7960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instruction->PrintNameTo(&trace_);
7961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" ");
7962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instruction->PrintTo(&trace_);
7963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" <|@\n");
7964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instruction = instruction->next();
7965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
7966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (chunk != NULL) {
7970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag LIR_tag(this, "LIR");
7971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int first_index = current->first_instruction_index();
7972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int last_index = current->last_instruction_index();
7973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (first_index != -1 && last_index != -1) {
7974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        const ZoneList<LInstruction*>* instructions = chunk->instructions();
7975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        for (int i = first_index; i <= last_index; ++i) {
7976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          LInstruction* linstr = instructions->at(i);
7977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (linstr != NULL) {
7978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            PrintIndent();
7979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            trace_.Add("%d ",
7980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       LifetimePosition::FromInstructionIndex(i).Value());
7981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            linstr->PrintTo(&trace_);
7982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            trace_.Add(" <|@\n");
7983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
7984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
7985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
7986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
7992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Tag tag(this, "intervals");
7993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("name", name);
7994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
799544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
7996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < fixed_d->length(); ++i) {
7997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceLiveRange(fixed_d->at(i), "fixed");
7998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
800044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
8001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < fixed->length(); ++i) {
8002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceLiveRange(fixed->at(i), "fixed");
8003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
8006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < live_ranges->length(); ++i) {
8007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceLiveRange(live_ranges->at(i), "object");
8008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRange(LiveRange* range, const char* type) {
8013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (range != NULL && !range->IsEmpty()) {
8014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    PrintIndent();
8015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    trace_.Add("%d %s", range->id(), type);
8016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (range->HasRegisterAssigned()) {
80175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      LOperand* op = range->CreateAssignedOperand(ZONE);
8018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int assigned_reg = op->index();
8019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (op->IsDoubleRegister()) {
8020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"%s\"",
8021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   DoubleRegister::AllocationIndexToString(assigned_reg));
8022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
8023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(op->IsRegister());
8024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg));
8025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
8026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (range->IsSpilled()) {
8027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      LOperand* op = range->TopLevel()->GetSpillOperand();
8028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (op->IsDoubleStackSlot()) {
8029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"double_stack:%d\"", op->index());
8030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
8031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(op->IsStackSlot());
8032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"stack:%d\"", op->index());
8033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
8034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
8035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int parent_index = -1;
8036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (range->IsChild()) {
8037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parent_index = range->parent()->id();
8038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
8039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parent_index = range->id();
8040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
8041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LOperand* op = range->FirstHint();
8042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int hint_index = -1;
80435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (op != NULL && op->IsUnallocated()) {
80445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      hint_index = LUnallocated::cast(op)->virtual_register();
80455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
8046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    trace_.Add(" %d %d", parent_index, hint_index);
8047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    UseInterval* cur_interval = range->first_interval();
8048e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    while (cur_interval != NULL && range->Covers(cur_interval->start())) {
8049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add(" [%d, %d[",
8050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 cur_interval->start().Value(),
8051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 cur_interval->end().Value());
8052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      cur_interval = cur_interval->next();
8053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
8054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    UsePosition* current_pos = range->first_pos();
8056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current_pos != NULL) {
8057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
8058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" %d M", current_pos->pos().Value());
8059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
8060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current_pos = current_pos->next();
8061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
8062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    trace_.Add(" \"\"\n");
8064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::FlushToFile() {
8069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AppendChars(filename_, *trace_.ToCString(), trace_.length(), false);
8070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  trace_.Reset();
8071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
807444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HStatistics::Initialize(CompilationInfo* info) {
807544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  source_size_ += info->shared_info()->SourceSize();
807644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
807744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
807844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStatistics::Print() {
8080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("Timing results:\n");
8081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int64_t sum = 0;
8082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < timing_.length(); ++i) {
8083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    sum += timing_[i];
8084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < names_.length(); ++i) {
8087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("%30s", names_[i]);
8088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    double ms = static_cast<double>(timing_[i]) / 1000;
8089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    double percent = static_cast<double>(timing_[i]) * 100 / sum;
8090b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    PrintF(" - %7.3f ms / %4.1f %% ", ms, percent);
8091b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
8092b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    unsigned size = sizes_[i];
8093b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    double size_percent = static_cast<double>(size) * 100 / total_size_;
8094b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    PrintF(" %8u bytes / %4.1f %%\n", size, size_percent);
8095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
809644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  double source_size_in_kb = static_cast<double>(source_size_) / 1024;
809744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  double normalized_time =  source_size_in_kb > 0
809844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? (static_cast<double>(sum) / 1000) / source_size_in_kb
809944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : 0;
810044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  double normalized_bytes = source_size_in_kb > 0
810144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? total_size_ / source_size_in_kb
810244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : 0;
810344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  PrintF("%30s - %7.3f ms           %7.3f bytes\n", "Sum",
810444f0eee88ff00398ff7f715fab053374d808c90dSteve Block         normalized_time, normalized_bytes);
8105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("---------------------------------------------------------------\n");
8106b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  PrintF("%30s - %7.3f ms (%.1f times slower than full code gen)\n",
8107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         "Total",
8108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         static_cast<double>(total_) / 1000,
8109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         static_cast<double>(total_) / full_code_gen_);
8110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8113b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid HStatistics::SaveTiming(const char* name, int64_t ticks, unsigned size) {
8114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (name == HPhase::kFullCodeGen) {
8115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    full_code_gen_ += ticks;
8116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (name == HPhase::kTotal) {
8117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    total_ += ticks;
8118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
8119b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    total_size_ += size;
8120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < names_.length(); ++i) {
8121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (names_[i] == name) {
8122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        timing_[i] += ticks;
8123b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        sizes_[i] += size;
8124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return;
8125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
8126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
8127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    names_.Add(name);
8128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    timing_.Add(ticks);
8129b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    sizes_.Add(size);
8130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kFullCodeGen = "Full code generator";
8135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kTotal = "Total";
8136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::Begin(const char* name,
8139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   HGraph* graph,
8140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   LChunk* chunk,
8141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   LAllocator* allocator) {
8142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  name_ = name;
8143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_ = graph;
8144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  chunk_ = chunk;
8145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  allocator_ = allocator;
8146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (allocator != NULL && chunk_ == NULL) {
8147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    chunk_ = allocator->chunk();
8148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
814944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_hydrogen_stats) start_ = OS::Ticks();
8150b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  start_allocation_size_ = Zone::allocation_size_;
8151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::End() const {
815544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_hydrogen_stats) {
8156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int64_t end = OS::Ticks();
8157b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    unsigned size = Zone::allocation_size_ - start_allocation_size_;
8158b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    HStatistics::Instance()->SaveTiming(name_, end - start_, size);
8159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
81615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // Produce trace output if flag is set so that the first letter of the
81625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // phase name matches the command line parameter FLAG_trace_phase.
81635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (FLAG_trace_hydrogen &&
81645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL) {
8165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_);
8166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_);
8167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (allocator_ != NULL) {
8168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HTracer::Instance()->TraceLiveRanges(name_, allocator_);
8169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
8170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
8173592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (graph_ != NULL) graph_->Verify(false);  // No full verify.
8174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (allocator_ != NULL) allocator_->Verify();
8175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
8176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} }  // namespace v8::internal
8179