hydrogen.cc revision 8b112d2025046f85ef7f6be087c6129c872ebad2
1b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Copyright 2011 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 "data-flow.h"
33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h"
34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "hashmap.h"
35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "lithium-allocator.h"
36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "parser.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),
72b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      is_inline_return_target_(false) {
73b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
74b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
75b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AttachLoopInformation() {
77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsLoopHeader());
788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  loop_information_ = new(zone()) HLoopInformation(this);
79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::DetachLoopInformation() {
83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(IsLoopHeader());
84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  loop_information_ = NULL;
85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddPhi(HPhi* phi) {
89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsStartBlock());
90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phis_.Add(phi);
91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phi->SetBlock(this);
92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::RemovePhi(HPhi* phi) {
96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(phi->block() == this);
97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(phis_.Contains(phi));
9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(phi->HasNoUses() || !phi->is_live());
99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phi->ClearOperands();
100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phis_.RemoveElement(phi);
101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phi->SetBlock(NULL);
102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddInstruction(HInstruction* instr) {
106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsStartBlock() || !IsFinished());
107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!instr->IsLinked());
108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsFinished());
109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (first_ == NULL) {
1108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HBlockEntry* entry = new(zone()) HBlockEntry();
111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    entry->InitializeAsFirst(this);
112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    first_ = last_ = entry;
113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  instr->InsertAfter(last_);
115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  last_ = instr;
116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
11944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHDeoptimize* HBasicBlock::CreateDeoptimize() {
12044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(HasEnvironment());
12144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEnvironment* environment = last_environment();
12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HDeoptimize* instr = new(zone()) HDeoptimize(environment->length());
12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < environment->length(); i++) {
12644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* val = environment->values()->at(i);
12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    instr->AddEnvironmentValue(val);
12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return instr;
13144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHSimulate* HBasicBlock::CreateSimulate(int id) {
135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(HasEnvironment());
136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* environment = last_environment();
137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(id == AstNode::kNoNumber ||
138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         environment->closure()->shared()->VerifyBailoutId(id));
139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int push_count = environment->push_count();
141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int pop_count = environment->pop_count();
142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HSimulate* instr = new(zone()) HSimulate(id, pop_count);
144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = push_count - 1; i >= 0; --i) {
145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->AddPushedValue(environment->ExpressionStackAt(i));
146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < environment->assigned_variables()->length(); ++i) {
148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int index = environment->assigned_variables()->at(i);
149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->AddAssignedValue(index, environment->Lookup(index));
150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  environment->ClearHistory();
152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Finish(HControlInstruction* end) {
157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsFinished());
158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(end);
159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  end_ = end;
160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (end->FirstSuccessor() != NULL) {
161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    end->FirstSuccessor()->RegisterPredecessor(this);
162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (end->SecondSuccessor() != NULL) {
163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      end->SecondSuccessor()->RegisterPredecessor(this);
164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Goto(HBasicBlock* block, bool include_stack_check) {
17044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (block->IsInlineReturnTarget()) {
1718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HLeaveInlined);
17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    last_environment_ = last_environment()->outer();
17344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddSimulate(AstNode::kNoNumber);
1758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HGoto* instr = new(zone()) HGoto(block);
176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_include_stack_check(include_stack_check);
177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Finish(instr);
178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
18144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(target->IsInlineReturnTarget());
18344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(return_value != NULL);
1848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HLeaveInlined);
18544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  last_environment_ = last_environment()->outer();
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
200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::SetJoinId(int 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()
210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               ->VerifyBailoutId(id));
211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    simulate->set_ast_id(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
226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(IsLoopHeader());
228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetJoinId(stmt->EntryId());
230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (predecessors()->length() == 1) {
231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // This is a degenerated loop.
232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    DetachLoopInformation();
233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Only the first entry into the loop is from outside the loop. All other
237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // entries must be back edges.
238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 1; i < predecessors()->length(); ++i) {
239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    loop_information()->RegisterBackEdge(predecessors()->at(i));
240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
2458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (HasPredecessor()) {
246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Only loop header blocks can have a predecessor added after
247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // instructions have been added to the block (they have phis for all
248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // values in the environment, these phis may be eliminated later).
249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(IsLoopHeader() || first_ == NULL);
250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HEnvironment* incoming_env = pred->last_environment();
251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (IsLoopHeader()) {
2529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ASSERT(phis()->length() == incoming_env->length());
253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int i = 0; i < phis_.length(); ++i) {
254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phis_[i]->AddInput(incoming_env->values()->at(i));
255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      last_environment()->AddIncomingEdge(this, pred->last_environment());
258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (!HasEnvironment() && !IsFinished()) {
260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!IsLoopHeader());
261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetInitialEnvironment(pred->last_environment()->Copy());
262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  predecessors_.Add(pred);
265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!dominated_blocks_.Contains(block));
270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Keep the list of dominated blocks sorted such that if there is two
271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // succeeding block in this list, the predecessor is before the successor.
272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = 0;
273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (index < dominated_blocks_.length() &&
274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         dominated_blocks_[index]->block_id() < block->block_id()) {
275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ++index;
276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  dominated_blocks_.InsertAt(index, block);
278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (dominator_ == NULL) {
283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    dominator_ = other;
284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    other->AddDominatedBlock(this);
285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (other->dominator() != NULL) {
286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* first = dominator_;
287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* second = other;
288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (first != second) {
290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (first->block_id() > second->block_id()) {
291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        first = first->dominator();
292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        second = second->dominator();
294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(first != NULL && second != NULL);
296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (dominator_ != first) {
299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(dominator_->dominated_blocks_.Contains(this));
300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      dominator_->dominated_blocks_.RemoveElement(this);
301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      dominator_ = first;
302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      first->AddDominatedBlock(this);
303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const {
309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < predecessors_.length(); ++i) {
310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (predecessors_[i] == predecessor) return i;
311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UNREACHABLE();
313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return -1;
314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Verify() {
319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check that every block is finished.
320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(IsFinished());
321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(block_id() >= 0);
32244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
32344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the incoming edges are in edge split form.
32444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (predecessors_.length() > 1) {
32544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 0; i < predecessors_.length(); ++i) {
32644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(predecessors_[i]->end()->SecondSuccessor() == NULL);
32744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
32844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  this->back_edges_.Add(block);
335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddBlock(block);
336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HLoopInformation::GetLastBackEdge() const {
340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int max_id = -1;
341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* result = NULL;
342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < back_edges_.length(); ++i) {
343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* cur = back_edges_[i];
344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (cur->block_id() > max_id) {
345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      max_id = cur->block_id();
346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      result = cur;
347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HLoopInformation::AddBlock(HBasicBlock* block) {
354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block == loop_header()) return;
355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->parent_loop_header() == loop_header()) return;
356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->parent_loop_header() != NULL) {
357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddBlock(block->parent_loop_header());
358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    block->set_parent_loop_header(loop_header());
360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    blocks_.Add(block);
361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < block->predecessors()->length(); ++i) {
362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddBlock(block->predecessors()->at(i));
363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Checks reachability of the blocks in this graph and stores a bit in
371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the BitVector "reachable()" for every block that can be reached
372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// from the start block of the graph. If "dont_visit" is non-null, the given
373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// block is treated as if it would not be part of the graph. "visited_count()"
374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// returns the number of reachable blocks.
375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass ReachabilityAnalyzer BASE_EMBEDDED {
376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ReachabilityAnalyzer(HBasicBlock* entry_block,
378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       int block_count,
379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       HBasicBlock* dont_visit)
380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : visited_count_(0),
381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        stack_(16),
382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        reachable_(block_count),
383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        dont_visit_(dont_visit) {
384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PushBlock(entry_block);
385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Analyze();
386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int visited_count() const { return visited_count_; }
389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const BitVector* reachable() const { return &reachable_; }
390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void PushBlock(HBasicBlock* block) {
393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block != NULL && block != dont_visit_ &&
394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        !reachable_.Contains(block->block_id())) {
395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      reachable_.Add(block->block_id());
396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      stack_.Add(block);
397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      visited_count_++;
398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze() {
402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (!stack_.is_empty()) {
403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HControlInstruction* end = stack_.RemoveLast()->end();
404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushBlock(end->FirstSuccessor());
405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushBlock(end->SecondSuccessor());
406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int visited_count_;
410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HBasicBlock*> stack_;
411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BitVector reachable_;
412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* dont_visit_;
413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Verify() const {
417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); i++) {
418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = blocks_.at(i);
419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    block->Verify();
421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that every block contains at least one node and that only the last
423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // node is a control instruction.
424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = block->first();
425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(current != NULL && current->IsBlockEntry());
426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT((current->next() == NULL) == current->IsControlInstruction());
428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(current->block() == block);
429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current->Verify();
430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that successors are correctly set.
434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* first = block->end()->FirstSuccessor();
435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* second = block->end()->SecondSuccessor();
436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(second == NULL || first != NULL);
437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that the predecessor array is correct.
439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (first != NULL) {
440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(first->predecessors()->Contains(block));
441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (second != NULL) {
442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(second->predecessors()->Contains(block));
443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that phis have correct arguments.
447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < block->phis()->length(); j++) {
448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = block->phis()->at(j);
449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->Verify();
450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that all join blocks have predecessors that end with an
453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // unconditional goto and agree on their environment node id.
454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->predecessors()->length() >= 2) {
455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int id = block->predecessors()->first()->last_environment()->ast_id();
456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int k = 0; k < block->predecessors()->length(); k++) {
457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HBasicBlock* predecessor = block->predecessors()->at(k);
458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(predecessor->end()->IsGoto());
459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(predecessor->last_environment()->ast_id() == id);
460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check special property of first block to have no predecessors.
465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(blocks_.at(0)->predecessors()->is_empty());
466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check that the graph is fully connected.
468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(analyzer.visited_count() == blocks_.length());
470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check that entry block dominator is NULL.
472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(entry_block_->dominator() == NULL);
473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check dominators.
475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); ++i) {
476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = blocks_.at(i);
477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->dominator() == NULL) {
478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Only start block may have no dominator assigned to.
479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(i == 0);
480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Assert that block is unreachable if dominator must not be visited.
482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ReachabilityAnalyzer dominator_analyzer(entry_block_,
483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                              blocks_.length(),
484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                              block->dominator());
485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(!dominator_analyzer.reachable()->Contains(block->block_id()));
486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               Object* value) {
495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!pointer->is_set()) {
4968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HConstant* constant = new(zone()) HConstant(Handle<Object>(value),
4978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                Representation::Tagged());
498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    constant->InsertAfter(GetConstantUndefined());
499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    pointer->set(constant);
500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return pointer->get();
502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstant1() {
506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return GetConstant(&constant_1_, Smi::FromInt(1));
507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantMinus1() {
511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return GetConstant(&constant_minus1_, Smi::FromInt(-1));
512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantTrue() {
51644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return GetConstant(&constant_true_, isolate()->heap()->true_value());
517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantFalse() {
52144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return GetConstant(&constant_false_, isolate()->heap()->false_value());
522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateJoin(HBasicBlock* first,
526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* second,
527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       int join_id) {
528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (first == NULL) {
529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return second;
530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (second == NULL) {
531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return first;
532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* join_block = graph_->CreateBasicBlock();
534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    first->Goto(join_block);
535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    second->Goto(join_block);
536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    join_block->SetJoinId(join_id);
537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return join_block;
538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::JoinContinue(IterationStatement* statement,
543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         HBasicBlock* exit_block,
544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         HBasicBlock* continue_block) {
545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (continue_block != NULL) {
546e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (exit_block != NULL) exit_block->Goto(continue_block);
547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    continue_block->SetJoinId(statement->ContinueId());
548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return continue_block;
549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
550e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return exit_block;
551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement,
555e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* loop_entry,
556e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* body_exit,
557e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* loop_successor,
558e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* break_block) {
559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (body_exit != NULL) body_exit->Goto(loop_entry, true);
560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  loop_entry->PostProcessLoopHeader(statement);
561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (break_block != NULL) {
562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (loop_successor != NULL) loop_successor->Goto(break_block);
563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    break_block->SetJoinId(statement->ExitId());
564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return break_block;
565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
566e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return loop_successor;
567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
570e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HBasicBlock::FinishExit(HControlInstruction* instruction) {
571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Finish(instruction);
572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ClearEnvironment();
573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHGraph::HGraph(CompilationInfo* info)
57744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : isolate_(info->isolate()),
578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      next_block_id_(0),
57944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      entry_block_(NULL),
580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      blocks_(8),
581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      values_(16),
582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi_list_(NULL) {
5838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  start_environment_ =
5848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HEnvironment(NULL, info->scope(), info->closure());
5858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  start_environment_->set_ast_id(AstNode::kFunctionEntryId);
58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  entry_block_ = CreateBasicBlock();
58744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  entry_block_->SetInitialEnvironment(start_environment_);
588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
591e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHandle<Code> HGraph::Compile(CompilationInfo* info) {
592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int values = GetMaximumValueID();
593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (values > LAllocator::max_initial_value_ids()) {
594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (FLAG_trace_bailout) PrintF("Function is too big\n");
595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return Handle<Code>::null();
596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LAllocator allocator(values, this);
599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LChunkBuilder builder(info, this, &allocator);
600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LChunk* chunk = builder.Build();
601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (chunk == NULL) return Handle<Code>::null();
602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!FLAG_alloc_lithium) return Handle<Code>::null();
604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  allocator.Allocate(chunk);
606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!FLAG_use_lithium) return Handle<Code>::null();
608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(info->isolate(), NULL, 0);
610e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LCodeGen generator(chunk, &assembler, info);
611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_eliminate_empty_blocks) {
613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    chunk->MarkEmptyBlocks();
614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (generator.GenerateCode()) {
617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (FLAG_trace_codegen) {
618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintF("Crankshaft Compiler - ");
619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    CodeGenerator::MakeCodePrologue(info);
621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Code::Flags flags =
622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Code::ComputeFlags(Code::OPTIMIZED_FUNCTION, NOT_IN_LOOP);
623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Code> code =
624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        CodeGenerator::MakeCodeEpilogue(&assembler, flags, info);
625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    generator.FinishCode(code);
626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    CodeGenerator::PrintCode(code, info);
627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return code;
628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Handle<Code>::null();
630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraph::CreateBasicBlock() {
6348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HBasicBlock* result = new(zone()) HBasicBlock(this);
635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  blocks_.Add(result);
636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Canonicalize() {
641e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!FLAG_use_canonicalizing) return;
642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Canonicalize", this);
643e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < blocks()->length(); ++i) {
644e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HInstruction* instr = blocks()->at(i)->first();
645e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    while (instr != NULL) {
646e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HValue* value = instr->Canonicalize();
647e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (value != instr) instr->ReplaceAndDelete(value);
648e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      instr = instr->next();
649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::OrderBlocks() {
655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Block ordering");
656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BitVector visited(blocks_.length());
657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HBasicBlock*> reverse_result(8);
659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* start = blocks_[0];
660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Postorder(start, &visited, &reverse_result, NULL);
661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
66244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  blocks_.Rewind(0);
663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = 0;
664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = reverse_result.length() - 1; i >= 0; --i) {
665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* b = reverse_result[i];
666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    blocks_.Add(b);
667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    b->set_block_id(index++);
668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::PostorderLoopBlocks(HLoopInformation* loop,
673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 BitVector* visited,
674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 ZoneList<HBasicBlock*>* order,
675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 HBasicBlock* loop_header) {
676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < loop->blocks()->length(); ++i) {
677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* b = loop->blocks()->at(i);
678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Postorder(b->end()->SecondSuccessor(), visited, order, loop_header);
679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Postorder(b->end()->FirstSuccessor(), visited, order, loop_header);
680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (b->IsLoopHeader() && b != loop->loop_header()) {
681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PostorderLoopBlocks(b->loop_information(), visited, order, loop_header);
682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Postorder(HBasicBlock* block,
688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       BitVector* visited,
689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       ZoneList<HBasicBlock*>* order,
690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       HBasicBlock* loop_header) {
691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block == NULL || visited->Contains(block->block_id())) return;
692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->parent_loop_header() != loop_header) return;
693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  visited->Add(block->block_id());
694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->IsLoopHeader()) {
695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PostorderLoopBlocks(block->loop_information(), visited, order, loop_header);
696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Postorder(block->end()->SecondSuccessor(), visited, order, block);
697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Postorder(block->end()->FirstSuccessor(), visited, order, block);
698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Postorder(block->end()->SecondSuccessor(), visited, order, loop_header);
700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Postorder(block->end()->FirstSuccessor(), visited, order, loop_header);
701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(block->end()->FirstSuccessor() == NULL ||
703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         order->Contains(block->end()->FirstSuccessor()) ||
704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         block->end()->FirstSuccessor()->IsLoopHeader());
705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(block->end()->SecondSuccessor() == NULL ||
706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         order->Contains(block->end()->SecondSuccessor()) ||
707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         block->end()->SecondSuccessor()->IsLoopHeader());
708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  order->Add(block);
709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::AssignDominators() {
713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Assign dominators", this);
714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); ++i) {
715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (blocks_[i]->IsLoopHeader()) {
716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->first());
717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < blocks_[i]->predecessors()->length(); ++j) {
719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::EliminateRedundantPhis() {
72744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HPhase phase("Redundant phi elimination", this);
728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Worklist of phis that can potentially be eliminated. Initialized
730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // with all phi nodes. When elimination of a phi node modifies
731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // another phi node the modified phi node is added to the worklist.
732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HPhi*> worklist(blocks_.length());
733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); ++i) {
734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    worklist.AddAll(*blocks_[i]->phis());
735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (!worklist.is_empty()) {
738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = worklist.RemoveLast();
739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = phi->block();
740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Skip phi node if it was already replaced.
742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block == NULL) continue;
743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Get replacement value if phi is redundant.
745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = phi->GetRedundantReplacement();
746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (value != NULL) {
748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Iterate through uses finding the ones that should be
749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // replaced.
75044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      SmallPointerList<HValue>* uses = phi->uses();
75144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      while (!uses->is_empty()) {
75244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        HValue* use = uses->RemoveLast();
75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (use != NULL) {
75444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          phi->ReplaceAtUse(use, value);
75544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (use->IsPhi()) worklist.Add(HPhi::cast(use));
756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->RemovePhi(phi);
75944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
76044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
76144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
76244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
76444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HGraph::EliminateUnreachablePhis() {
76544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HPhase phase("Unreachable phi elimination", this);
76644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
76744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Initialize worklist.
76844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ZoneList<HPhi*> phi_list(blocks_.length());
76944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ZoneList<HPhi*> worklist(blocks_.length());
77044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < blocks_.length(); ++i) {
77144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int j = 0; j < blocks_[i]->phis()->length(); j++) {
77244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HPhi* phi = blocks_[i]->phis()->at(j);
77344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      phi_list.Add(phi);
7741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // We can't eliminate phis in the receiver position in the environment
7751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // because in case of throwing an error we need this value to
7761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // construct a stack trace.
77744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (phi->HasRealUses() || phi->IsReceiver())  {
77844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        phi->set_is_live(true);
77944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        worklist.Add(phi);
78044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
78144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Iteratively mark live phis.
78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  while (!worklist.is_empty()) {
78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HPhi* phi = worklist.RemoveLast();
78744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 0; i < phi->OperandCount(); i++) {
78844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HValue* operand = phi->OperandAt(i);
78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (operand->IsPhi() && !HPhi::cast(operand)->is_live()) {
79044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        HPhi::cast(operand)->set_is_live(true);
79144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        worklist.Add(HPhi::cast(operand));
79244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
79344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
79644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Remove unreachable phis.
79744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < phi_list.length(); i++) {
79844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HPhi* phi = phi_list[i];
79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!phi->is_live()) {
80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HBasicBlock* block = phi->block();
801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->RemovePhi(phi);
802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->RecordDeletedPhi(phi->merged_index());
803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraph::CollectPhis() {
80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int block_count = blocks_.length();
81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  phi_list_ = new ZoneList<HPhi*>(block_count);
81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < block_count; ++i) {
81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HPhi* phi = blocks_[i]->phis()->at(j);
814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi_list_->Add(phi);
815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // We don't support phi uses of arguments for now.
816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (phi->CheckFlag(HValue::kIsArguments)) return false;
817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InferTypes(ZoneList<HValue*>* worklist) {
824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BitVector in_worklist(GetMaximumValueID());
825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < worklist->length(); ++i) {
826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!in_worklist.Contains(worklist->at(i)->id()));
827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    in_worklist.Add(worklist->at(i)->id());
828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (!worklist->is_empty()) {
831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* current = worklist->RemoveLast();
832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    in_worklist.Remove(current->id());
833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->UpdateInferredType()) {
834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < current->uses()->length(); j++) {
835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* use = current->uses()->at(j);
836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (!in_worklist.Contains(use->id())) {
837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          in_worklist.Add(use->id());
838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          worklist->Add(use);
839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HRangeAnalysis BASE_EMBEDDED {
847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit HRangeAnalysis(HGraph* graph) : graph_(graph), changed_ranges_(16) {}
849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze();
851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void TraceRange(const char* msg, ...);
854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze(HBasicBlock* block);
8551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void InferControlFlowRange(HTest* test, HBasicBlock* dest);
856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferControlFlowRange(Token::Value op, HValue* value, HValue* other);
857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferPhiRange(HPhi* phi);
858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferRange(HValue* value);
859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void RollBackTo(int index);
860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AddRange(HValue* value, Range* range);
861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HValue*> changed_ranges_;
864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::TraceRange(const char* msg, ...) {
868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_range) {
869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_list arguments;
870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_start(arguments, msg);
871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    OS::VPrint(msg, arguments);
872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_end(arguments);
873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::Analyze() {
878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Range analysis", graph_);
879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Analyze(graph_->blocks()->at(0));
880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::Analyze(HBasicBlock* block) {
884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("Analyzing block B%d\n", block->block_id());
885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int last_changed_range = changed_ranges_.length() - 1;
887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Infer range based on control flow.
889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->predecessors()->length() == 1) {
890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* pred = block->predecessors()->first();
8911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (pred->end()->IsTest()) {
8921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      InferControlFlowRange(HTest::cast(pred->end()), block);
893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Process phi instructions.
897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < block->phis()->length(); ++i) {
898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = block->phis()->at(i);
899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferPhiRange(phi);
900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Go through all instructions of the current block.
903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = block->first();
904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (instr != block->end()) {
905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferRange(instr);
906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = instr->next();
907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Continue analysis in all dominated blocks.
910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Analyze(block->dominated_blocks()->at(i));
912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RollBackTo(last_changed_range);
915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
9181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) {
9191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
9201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (test->value()->IsCompare()) {
9211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    HCompare* compare = HCompare::cast(test->value());
92244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (compare->GetInputRepresentation().IsInteger32()) {
92344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Token::Value op = compare->token();
92444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (test->SecondSuccessor() == dest) {
92544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        op = Token::NegateCompareOp(op);
92644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
92744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Token::Value inverted_op = Token::InvertCompareOp(op);
92844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      InferControlFlowRange(op, compare->left(), compare->right());
92944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      InferControlFlowRange(inverted_op, compare->right(), compare->left());
930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// We know that value [op] other. Use this information to update the range on
936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// value.
937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferControlFlowRange(Token::Value op,
938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                           HValue* value,
939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                           HValue* other) {
940e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Range temp_range;
941e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Range* range = other->range() != NULL ? other->range() : &temp_range;
942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Range* new_range = NULL;
943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("Control flow range infer %d %s %d\n",
945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             value->id(),
946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             Token::Name(op),
947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             other->id());
948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (op == Token::EQ || op == Token::EQ_STRICT) {
950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // The same range has to apply for value.
951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_range = range->Copy();
952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::LT || op == Token::LTE) {
953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_range = range->CopyClearLower();
954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (op == Token::LT) {
955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new_range->AddConstant(-1);
956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::GT || op == Token::GTE) {
958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_range = range->CopyClearUpper();
959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (op == Token::GT) {
960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new_range->AddConstant(1);
961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (new_range != NULL && !new_range->IsMostGeneric()) {
965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddRange(value, new_range);
966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferPhiRange(HPhi* phi) {
971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(twuerthinger): Infer loop phi ranges.
972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  InferRange(phi);
973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferRange(HValue* value) {
977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!value->HasRange());
978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!value->representation().IsNone()) {
979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    value->ComputeInitialRange();
980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Range* range = value->range();
981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n",
982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               value->id(),
983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               value->Mnemonic(),
984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               range->lower(),
985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               range->upper());
986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::RollBackTo(int index) {
991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = index + 1; i < changed_ranges_.length(); ++i) {
992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    changed_ranges_[i]->RemoveLastAddedRange();
993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  changed_ranges_.Rewind(index + 1);
995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::AddRange(HValue* value, Range* range) {
999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Range* original_range = value->range();
1000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  value->AddNewRange(range);
1001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  changed_ranges_.Add(value);
1002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Range* new_range = value->range();
1003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("Updated range of %d set to [%d,%d]\n",
1004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             value->id(),
1005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             new_range->lower(),
1006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             new_range->upper());
1007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (original_range != NULL) {
1008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceRange("Original range was [%d,%d]\n",
1009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               original_range->lower(),
1010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               original_range->upper());
1011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("New information was [%d,%d]\n",
1013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             range->lower(),
1014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             range->upper());
1015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TraceGVN(const char* msg, ...) {
1019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_gvn) {
1020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_list arguments;
1021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_start(arguments, msg);
1022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    OS::VPrint(msg, arguments);
1023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_end(arguments);
1024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHValueMap::HValueMap(const HValueMap* other)
1029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : array_size_(other->array_size_),
1030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      lists_size_(other->lists_size_),
1031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      count_(other->count_),
1032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      present_flags_(other->present_flags_),
103344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      array_(ZONE->NewArray<HValueMapListElement>(other->array_size_)),
103444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      lists_(ZONE->NewArray<HValueMapListElement>(other->lists_size_)),
1035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      free_list_head_(other->free_list_head_) {
1036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memcpy(array_, other->array_, array_size_ * sizeof(HValueMapListElement));
1037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memcpy(lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement));
1038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Kill(int flags) {
1042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int depends_flags = HValue::ConvertChangesToDependsFlags(flags);
1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if ((present_flags_ & depends_flags) == 0) return;
1044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  present_flags_ = 0;
1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < array_size_; ++i) {
1046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = array_[i].value;
1047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (value != NULL) {
1048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Clear list of collisions first, so we know if it becomes empty.
1049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int kept = kNil;  // List of kept elements.
1050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int next;
1051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int current = array_[i].next; current != kNil; current = next) {
1052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        next = lists_[current].next;
1053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if ((lists_[current].value->flags() & depends_flags) != 0) {
1054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          // Drop it.
1055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          count_--;
1056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[current].next = free_list_head_;
1057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          free_list_head_ = current;
1058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else {
1059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          // Keep it.
1060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[current].next = kept;
1061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          kept = current;
1062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          present_flags_ |= lists_[current].value->flags();
1063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      array_[i].next = kept;
1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Now possibly drop directly indexed element.
1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if ((array_[i].value->flags() & depends_flags) != 0) {  // Drop it.
1069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        count_--;
1070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int head = array_[i].next;
1071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (head == kNil) {
1072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          array_[i].value = NULL;
1073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else {
1074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          array_[i].value = lists_[head].value;
1075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          array_[i].next = lists_[head].next;
1076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[head].next = free_list_head_;
1077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          free_list_head_ = head;
1078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        present_flags_ |= array_[i].value->flags();  // Keep it.
1081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHValue* HValueMap::Lookup(HValue* value) const {
1088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint32_t hash = static_cast<uint32_t>(value->Hashcode());
1089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint32_t pos = Bound(hash);
1090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (array_[pos].value != NULL) {
1091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (array_[pos].value->Equals(value)) return array_[pos].value;
1092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int next = array_[pos].next;
1093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (next != kNil) {
1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (lists_[next].value->Equals(value)) return lists_[next].value;
1095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      next = lists_[next].next;
1096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return NULL;
1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Resize(int new_size) {
1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(new_size > count_);
1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Hashing the values into the new array has no more collisions than in the
1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // old hash map, so we can use the existing lists_ array, if we are careful.
1106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Make sure we have at least one free element.
1108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (free_list_head_ == kNil) {
1109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ResizeLists(lists_size_ << 1);
1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* new_array =
111344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ZONE->NewArray<HValueMapListElement>(new_size);
1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(new_array, 0, sizeof(HValueMapListElement) * new_size);
1115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* old_array = array_;
1117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int old_size = array_size_;
1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int old_count = count_;
1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  count_ = 0;
1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Do not modify present_flags_.  It is currently correct.
1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  array_size_ = new_size;
1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  array_ = new_array;
1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (old_array != NULL) {
1126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Iterate over all the elements in lists, rehashing them.
1127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < old_size; ++i) {
1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (old_array[i].value != NULL) {
1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int current = old_array[i].next;
1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        while (current != kNil) {
1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          Insert(lists_[current].value);
1132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          int next = lists_[current].next;
1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[current].next = free_list_head_;
1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          free_list_head_ = current;
1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          current = next;
1136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Rehash the directly stored value.
1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Insert(old_array[i].value);
1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  USE(old_count);
1143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(count_ == old_count);
1144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::ResizeLists(int new_size) {
1148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(new_size > lists_size_);
1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* new_lists =
115144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ZONE->NewArray<HValueMapListElement>(new_size);
1152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(new_lists, 0, sizeof(HValueMapListElement) * new_size);
1153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* old_lists = lists_;
1155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int old_size = lists_size_;
1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  lists_size_ = new_size;
1158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  lists_ = new_lists;
1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (old_lists != NULL) {
1161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    memcpy(lists_, old_lists, old_size * sizeof(HValueMapListElement));
1162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = old_size; i < lists_size_; ++i) {
1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    lists_[i].next = free_list_head_;
1165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    free_list_head_ = i;
1166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Insert(HValue* value) {
1171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(value != NULL);
1172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Resizing when half of the hashtable is filled up.
1173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (count_ >= array_size_ >> 1) Resize(array_size_ << 1);
1174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(count_ < array_size_);
1175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  count_++;
1176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint32_t pos = Bound(static_cast<uint32_t>(value->Hashcode()));
1177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (array_[pos].value == NULL) {
1178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    array_[pos].value = value;
1179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    array_[pos].next = kNil;
1180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
1181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (free_list_head_ == kNil) {
1182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ResizeLists(lists_size_ << 1);
1183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int new_element_pos = free_list_head_;
1185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(new_element_pos != kNil);
1186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    free_list_head_ = lists_[free_list_head_].next;
1187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    lists_[new_element_pos].value = value;
1188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    lists_[new_element_pos].next = array_[pos].next;
1189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value != NULL);
1190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    array_[pos].next = new_element_pos;
1191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HStackCheckEliminator BASE_EMBEDDED {
1196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
1197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { }
1198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Process();
1200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
1202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void RemoveStackCheck(HBasicBlock* block);
1203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
1205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStackCheckEliminator::Process() {
1209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // For each loop block walk the dominator tree from the backwards branch to
1210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the loop header. If a call instruction is encountered the backwards branch
1211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // is dominated by a call and the stack check in the backwards branch can be
1212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // removed.
1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < graph_->blocks()->length(); i++) {
1214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
1216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge();
1217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* dominator = back_edge;
1218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool back_edge_dominated_by_call = false;
1219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      while (dominator != block && !back_edge_dominated_by_call) {
1220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HInstruction* instr = dominator->first();
1221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        while (instr != NULL && !back_edge_dominated_by_call) {
1222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (instr->IsCall()) {
1223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            RemoveStackCheck(back_edge);
1224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            back_edge_dominated_by_call = true;
1225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
1226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          instr = instr->next();
1227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        dominator = dominator->dominator();
1229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStackCheckEliminator::RemoveStackCheck(HBasicBlock* block) {
1236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = block->first();
1237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (instr != NULL) {
1238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (instr->IsGoto()) {
1239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HGoto::cast(instr)->set_include_stack_check(false);
1240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
1241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = instr->next();
1243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HGlobalValueNumberer BASE_EMBEDDED {
1248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
1249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info)
1250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : graph_(graph),
1251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        info_(info),
1252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        block_side_effects_(graph_->blocks()->length()),
1253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        loop_side_effects_(graph_->blocks()->length()) {
125444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(info->isolate()->heap()->allow_allocation(false));
1255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    block_side_effects_.AddBlock(0, graph_->blocks()->length());
1256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    loop_side_effects_.AddBlock(0, graph_->blocks()->length());
1257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ~HGlobalValueNumberer() {
125944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(!info_->isolate()->heap()->allow_allocation(true));
1260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze();
1263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
1265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
1266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void ComputeBlockSideEffects();
1267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void LoopInvariantCodeMotion();
1268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void ProcessLoopBlock(HBasicBlock* block,
1269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        HBasicBlock* before_loop,
1270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        int loop_kills);
1271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool AllowCodeMotion();
1272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
1273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HGraph* graph() { return graph_; }
1275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompilationInfo* info() { return info_; }
12768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Zone* zone() { return graph_->zone(); }
1277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
1279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompilationInfo* info_;
1280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // A map of block IDs to their side effects.
1282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<int> block_side_effects_;
1283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // A map of loop header block IDs to their loop's side effects.
1285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<int> loop_side_effects_;
1286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::Analyze() {
1290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ComputeBlockSideEffects();
1291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_loop_invariant_code_motion) {
1292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LoopInvariantCodeMotion();
1293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
12948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HValueMap* map = new(zone()) HValueMap();
1295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AnalyzeBlock(graph_->blocks()->at(0), map);
1296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::ComputeBlockSideEffects() {
1300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Compute side effects for the block.
1302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* instr = block->first();
1304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int id = block->block_id();
1305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int side_effects = 0;
1306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (instr != NULL) {
1307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      side_effects |= (instr->flags() & HValue::ChangesFlagsMask());
1308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = instr->next();
1309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    block_side_effects_[id] |= side_effects;
1311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Loop headers are part of their loop.
1313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
1314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      loop_side_effects_[id] |= side_effects;
1315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Propagate loop side effects upwards.
1318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->HasParentLoopHeader()) {
1319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int header_id = block->parent_loop_header()->block_id();
1320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      loop_side_effects_[header_id] |=
1321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          block->IsLoopHeader() ? loop_side_effects_[id] : side_effects;
1322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::LoopInvariantCodeMotion() {
1328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
1331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int side_effects = loop_side_effects_[block->block_id()];
1332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n",
1333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               block->block_id(),
1334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               side_effects);
1335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* last = block->loop_information()->GetLastBackEdge();
1337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = block->block_id(); j <= last->block_id(); ++j) {
1338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects);
1339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::ProcessLoopBlock(HBasicBlock* block,
1346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            HBasicBlock* loop_header,
1347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            int loop_kills) {
1348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* pre_header = loop_header->predecessors()->at(0);
1349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
1350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n",
1351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           block->block_id(),
1352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           depends_flags);
1353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = block->first();
1354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (instr != NULL) {
1355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* next = instr->next();
1356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (instr->CheckFlag(HValue::kUseGVN) &&
1357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        (instr->flags() & depends_flags) == 0) {
1358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TraceGVN("Checking instruction %d (%s)\n",
1359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               instr->id(),
1360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               instr->Mnemonic());
1361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool inputs_loop_invariant = true;
1362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int i = 0; i < instr->OperandCount(); ++i) {
1363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) {
1364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          inputs_loop_invariant = false;
1365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (inputs_loop_invariant && ShouldMove(instr, loop_header)) {
1369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        TraceGVN("Found loop invariant instruction %d\n", instr->id());
1370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Move the instruction out of the loop.
1371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instr->Unlink();
1372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instr->InsertBefore(pre_header->end());
1373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = next;
1376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
13791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1380e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool HGlobalValueNumberer::AllowCodeMotion() {
1381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
1382e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1383e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1384e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
1386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                      HBasicBlock* loop_header) {
13871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // If we've disabled code motion, don't move any instructions.
1388e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!AllowCodeMotion()) return false;
13891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
13901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // If --aggressive-loop-invariant-motion, move everything except change
13911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // instructions.
13921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (FLAG_aggressive_loop_invariant_motion && !instr->IsChange()) {
1393b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return true;
1394b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
13951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
13961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Otherwise only move instructions that postdominate the loop header
13971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // (i.e. are always executed inside the loop). This is to avoid
13981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // unnecessary deoptimizations assuming the loop is executed at least
13991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // once.  TODO(fschneider): Better type feedback should give us
14001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // information about code that was never executed.
1401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* block = instr->block();
1402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool result = true;
1403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block != loop_header) {
1404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 1; i < loop_header->predecessors()->length(); ++i) {
1405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool found = false;
1406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* pred = loop_header->predecessors()->at(i);
1407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      while (pred != loop_header) {
1408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (pred == block) found = true;
1409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        pred = pred->dominator();
1410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!found) {
1412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        result = false;
1413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        break;
1414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
1418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
1422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceGVN("Analyzing block B%d\n", block->block_id());
1423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If this is a loop header kill everything killed by the loop.
1425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->IsLoopHeader()) {
1426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    map->Kill(loop_side_effects_[block->block_id()]);
1427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Go through all instructions of the current block.
1430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = block->first();
1431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (instr != NULL) {
1432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* next = instr->next();
1433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int flags = (instr->flags() & HValue::ChangesFlagsMask());
1434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (flags != 0) {
1435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(!instr->CheckFlag(HValue::kUseGVN));
1436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Clear all instructions in the map that are affected by side effects.
1437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      map->Kill(flags);
1438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TraceGVN("Instruction %d kills\n", instr->id());
1439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (instr->CheckFlag(HValue::kUseGVN)) {
1440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* other = map->Lookup(instr);
1441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (other != NULL) {
1442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(instr->Equals(other) && other->Equals(instr));
1443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        TraceGVN("Replacing value %d (%s) with value %d (%s)\n",
1444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 instr->id(),
1445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 instr->Mnemonic(),
1446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 other->id(),
1447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 other->Mnemonic());
1448e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        instr->ReplaceAndDelete(other);
1449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
1450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        map->Add(instr);
1451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = next;
1454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Recursively continue analysis for all immediately dominated blocks.
1457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = block->dominated_blocks()->length();
1458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; ++i) {
1459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* dominated = block->dominated_blocks()->at(i);
1460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // No need to copy the map for the last child in the dominator tree.
14618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone());
1462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // If the dominated block is not a successor to this block we have to
1464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // kill everything killed on any path between this block and the
1465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // dominated block.  Note we rely on the block ordering.
1466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool is_successor = false;
1467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int predecessor_count = dominated->predecessors()->length();
1468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; !is_successor && j < predecessor_count; ++j) {
1469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      is_successor = (dominated->predecessors()->at(j) == block);
1470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!is_successor) {
1473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int side_effects = 0;
1474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = block->block_id() + 1; j < dominated->block_id(); ++j) {
1475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        side_effects |= block_side_effects_[j];
1476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      successor_map->Kill(side_effects);
1478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AnalyzeBlock(dominated, successor_map);
1481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HInferRepresentation BASE_EMBEDDED {
1486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
1487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit HInferRepresentation(HGraph* graph)
1488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : graph_(graph), worklist_(8), in_worklist_(graph->GetMaximumValueID()) {}
1489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze();
1491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
1493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation TryChange(HValue* current);
1494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AddToWorklist(HValue* current);
1495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferBasedOnInputs(HValue* current);
1496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AddDependantsToWorklist(HValue* current);
1497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferBasedOnUses(HValue* current);
1498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Zone* zone() { return graph_->zone(); }
15008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
1502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HValue*> worklist_;
1503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BitVector in_worklist_;
1504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::AddToWorklist(HValue* current) {
1508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (current->representation().IsSpecialization()) return;
1509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return;
1510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (in_worklist_.Contains(current->id())) return;
1511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  worklist_.Add(current);
1512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  in_worklist_.Add(current->id());
1513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This method tries to specialize the representation type of the value
1517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// given as a parameter. The value is asked to infer its representation type
1518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// based on its inputs. If the inferred type is more specialized, then this
1519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// becomes the new representation type of the node.
1520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::InferBasedOnInputs(HValue* current) {
1521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation r = current->representation();
1522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (r.IsSpecialization()) return;
1523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation));
1524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation inferred = current->InferredRepresentation();
1525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (inferred.IsSpecialization()) {
1526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current->ChangeRepresentation(inferred);
1527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddDependantsToWorklist(current);
1528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::AddDependantsToWorklist(HValue* current) {
1533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < current->uses()->length(); ++i) {
1534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddToWorklist(current->uses()->at(i));
1535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < current->OperandCount(); ++i) {
1537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddToWorklist(current->OperandAt(i));
1538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This method calculates whether specializing the representation of the value
1543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// given as the parameter has a benefit in terms of less necessary type
1544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// conversions. If there is a benefit, then the representation of the value is
1545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// specialized.
1546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::InferBasedOnUses(HValue* current) {
1547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation r = current->representation();
1548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (r.IsSpecialization() || current->HasNoUses()) return;
1549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation));
1550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation new_rep = TryChange(current);
1551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!new_rep.IsNone()) {
1552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!current->representation().Equals(new_rep)) {
1553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current->ChangeRepresentation(new_rep);
1554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddDependantsToWorklist(current);
1555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochRepresentation HInferRepresentation::TryChange(HValue* current) {
1561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Array of use counts for each representation.
1562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int use_count[Representation::kNumRepresentations];
1563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < Representation::kNumRepresentations; i++) {
1564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    use_count[i] = 0;
1565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < current->uses()->length(); ++i) {
1568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* use = current->uses()->at(i);
1569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int index = use->LookupOperandIndex(0, current);
1570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Representation req_rep = use->RequiredInputRepresentation(index);
1571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (req_rep.IsNone()) continue;
1572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (use->IsPhi()) {
1573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = HPhi::cast(use);
1574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->AddIndirectUsesTo(&use_count[0]);
1575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    use_count[req_rep.kind()]++;
1577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int tagged_count = use_count[Representation::kTagged];
1579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int double_count = use_count[Representation::kDouble];
1580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int int32_count = use_count[Representation::kInteger32];
1581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int non_tagged_count = double_count + int32_count;
1582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If a non-loop phi has tagged uses, don't convert it to untagged.
1584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (current->IsPhi() && !current->block()->IsLoopHeader()) {
1585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (tagged_count > 0) return Representation::None();
1586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (non_tagged_count >= tagged_count) {
1589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // More untagged than tagged.
1590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (double_count > 0) {
1591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // There is at least one usage that is a double => guess that the
1592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // correct representation is double.
1593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return Representation::Double();
1594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (int32_count > 0) {
1595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return Representation::Integer32();
1596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Representation::None();
1599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::Analyze() {
1603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Infer representations", graph_);
1604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // (1) Initialize bit vectors and count real uses. Each phi
1606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // gets a bit-vector of length <number of phis>.
1607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<HPhi*>* phi_list = graph_->phi_list();
1608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int num_phis = phi_list->length();
1609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ScopedVector<BitVector*> connected_phis(num_phis);
1610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < num_phis; i++) {
1611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    phi_list->at(i)->InitRealUses(i);
16128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    connected_phis[i] = new(zone()) BitVector(num_phis);
1613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    connected_phis[i]->Add(i);
1614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // (2) Do a fixed point iteration to find the set of connected phis.
1617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // A phi is connected to another phi if its value is used either
1618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // directly or indirectly through a transitive closure of the def-use
1619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // relation.
1620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool change = true;
1621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (change) {
1622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    change = false;
1623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < num_phis; i++) {
1624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = phi_list->at(i);
1625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < phi->uses()->length(); j++) {
1626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* use = phi->uses()->at(j);
1627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (use->IsPhi()) {
1628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          int phi_use = HPhi::cast(use)->phi_id();
1629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (connected_phis[i]->UnionIsChanged(*connected_phis[phi_use])) {
1630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            change = true;
1631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
1632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // (3) Sum up the non-phi use counts of all connected phis.
1638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Don't include the non-phi uses of the phi itself.
1639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < num_phis; i++) {
1640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = phi_list->at(i);
1641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (BitVector::Iterator it(connected_phis.at(i));
1642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         !it.Done();
1643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         it.Advance()) {
1644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int index = it.Current();
1645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (index != i) {
1646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HPhi* it_use = phi_list->at(it.Current());
1647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->AddNonPhiUsesFrom(it_use);
1648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < graph_->blocks()->length(); ++i) {
1653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const ZoneList<HPhi*>* phis = block->phis();
1655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < phis->length(); ++j) {
1656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddToWorklist(phis->at(j));
1657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = block->first();
1660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
1661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddToWorklist(current);
1662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
1663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (!worklist_.is_empty()) {
1667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* current = worklist_.RemoveLast();
1668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    in_worklist_.Remove(current->id());
1669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferBasedOnInputs(current);
1670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferBasedOnUses(current);
1671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InitializeInferredTypes() {
1676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Inferring types", this);
1677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  InitializeInferredTypes(0, this->blocks_.length() - 1);
1678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InitializeInferredTypes(int from_inclusive, int to_inclusive) {
1682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = from_inclusive; i <= to_inclusive; ++i) {
1683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = blocks_[i];
1684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const ZoneList<HPhi*>* phis = block->phis();
1686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < phis->length(); j++) {
1687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phis->at(j)->UpdateInferredType();
1688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = block->first();
1691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
1692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current->UpdateInferredType();
1693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
1694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
1697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* last_back_edge =
1698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          block->loop_information()->GetLastBackEdge();
1699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InitializeInferredTypes(i + 1, last_back_edge->block_id());
1700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Skip all blocks already processed by the recursive call.
1701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      i = last_back_edge->block_id();
1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Update phis of the loop header now after the whole loop body is
1703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // guaranteed to be processed.
1704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ZoneList<HValue*> worklist(block->phis()->length());
1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < block->phis()->length(); ++j) {
1706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        worklist.Add(block->phis()->at(j));
1707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InferTypes(&worklist);
1709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) {
1715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* current = value;
1716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (current != NULL) {
1717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (visited->Contains(current->id())) return;
1718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // For phis, we must propagate the check to all of its inputs.
1720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->IsPhi()) {
1721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      visited->Add(current->id());
1722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = HPhi::cast(current);
1723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int i = 0; i < phi->OperandCount(); ++i) {
1724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PropagateMinusZeroChecks(phi->OperandAt(i), visited);
1725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
1727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // For multiplication and division, we must propagate to the left and
1730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // the right side.
1731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->IsMul()) {
1732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HMul* mul = HMul::cast(current);
1733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      mul->EnsureAndPropagateNotMinusZero(visited);
1734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(mul->left(), visited);
1735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(mul->right(), visited);
1736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (current->IsDiv()) {
1737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HDiv* div = HDiv::cast(current);
1738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      div->EnsureAndPropagateNotMinusZero(visited);
1739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(div->left(), visited);
1740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(div->right(), visited);
1741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current = current->EnsureAndPropagateNotMinusZero(visited);
1744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChangeForUse(HValue* value,
1749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                              HValue* use,
1750e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              Representation to) {
1751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Insert the representation change right before its use. For phi-uses we
1752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // insert at the end of the corresponding predecessor.
17531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  HInstruction* next = NULL;
1754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (use->IsPhi()) {
1755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int index = 0;
1756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (use->OperandAt(index) != value) ++index;
17571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    next = use->block()->predecessors()->at(index)->end();
17581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
17591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    next = HInstruction::cast(use);
1760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // For constants we try to make the representation change at compile
1763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // time. When a representation change is not possible without loss of
1764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // information we treat constants like normal instructions and insert the
1765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // change instructions for them.
1766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* new_value = NULL;
1767e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32);
1768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (value->IsConstant()) {
1769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HConstant* constant = HConstant::cast(value);
1770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Try to create a new copy of the constant with the new representation.
1771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_value = is_truncating
1772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ? constant->CopyToTruncatedInt32()
1773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        : constant->CopyToRepresentation(to);
1774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (new_value == NULL) {
17778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    new_value =
17788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        new(zone()) HChange(value, value->representation(), to, is_truncating);
1779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  new_value->InsertBefore(next);
1782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  value->ReplaceFirstAtUse(use, new_value, to);
1783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint CompareConversionUses(HValue* a,
1787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          HValue* b,
1788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          Representation a_rep,
1789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          Representation b_rep) {
1790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (a_rep.kind() > b_rep.kind()) {
1791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Make sure specializations are separated in the result array.
1792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return 1;
1793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Put truncating conversions before non-truncating conversions.
1795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool a_truncate = a->CheckFlag(HValue::kTruncatingToInt32);
1796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool b_truncate = b->CheckFlag(HValue::kTruncatingToInt32);
1797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (a_truncate != b_truncate) {
1798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return a_truncate ? -1 : 1;
1799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Sort by increasing block ID.
1801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return a->block()->block_id() - b->block()->block_id();
1802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
180544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HGraph::InsertRepresentationChangesForValue(
180644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* current,
180744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ZoneList<HValue*>* to_convert,
180844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ZoneList<Representation>* to_convert_reps) {
1809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation r = current->representation();
1810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (r.IsNone()) return;
18118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (current->uses()->is_empty()) return;
1812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Collect the representation changes in a sorted list.  This allows
1814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // us to avoid duplicate changes without searching the list.
181544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(to_convert->is_empty());
181644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(to_convert_reps->is_empty());
1817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < current->uses()->length(); ++i) {
1818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* use = current->uses()->at(i);
1819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // The occurrences index means the index within the operand array of "use"
1820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // at which "current" is used. While iterating through the use array we
1821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // also have to iterate over the different occurrence indices.
1822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int occurrence_index = 0;
1823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (use->UsesMultipleTimes(current)) {
1824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      occurrence_index = current->uses()->CountOccurrences(use, 0, i - 1);
1825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_representation) {
1826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF("Instruction %d is used multiple times at %d; occurrence=%d\n",
1827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               current->id(),
1828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               use->id(),
1829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               occurrence_index);
1830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int operand_index = use->LookupOperandIndex(occurrence_index, current);
1833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Representation req = use->RequiredInputRepresentation(operand_index);
1834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (req.IsNone() || req.Equals(r)) continue;
1835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int index = 0;
183644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    while (index < to_convert->length() &&
183744f0eee88ff00398ff7f715fab053374d808c90dSteve Block           CompareConversionUses(to_convert->at(index),
1838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 use,
183944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 to_convert_reps->at(index),
1840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 req) < 0) {
1841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ++index;
1842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (FLAG_trace_representation) {
1844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintF("Inserting a representation change to %s of %d for use at %d\n",
1845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             req.Mnemonic(),
1846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             current->id(),
1847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             use->id());
1848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
184944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    to_convert->InsertAt(index, use);
185044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    to_convert_reps->InsertAt(index, req);
1851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
185344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < to_convert->length(); ++i) {
185444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* use = to_convert->at(i);
185544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Representation r_to = to_convert_reps->at(i);
1856e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    InsertRepresentationChangeForUse(current, use, r_to);
1857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (current->uses()->is_empty()) {
1860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(current->IsConstant());
1861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current->Delete();
1862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
186344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  to_convert->Rewind(0);
186444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  to_convert_reps->Rewind(0);
1865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChanges() {
1869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Insert representation changes", this);
1870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Compute truncation flag for phis: Initially assume that all
1873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // int32-phis allow truncation and iteratively remove the ones that
1874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // are used in an operation that does not allow a truncating
1875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // conversion.
1876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(fschneider): Replace this with a worklist-based iteration.
1877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < phi_list()->length(); i++) {
1878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = phi_list()->at(i);
1879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (phi->representation().IsInteger32()) {
1880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->SetFlag(HValue::kTruncatingToInt32);
1881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool change = true;
1884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (change) {
1885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    change = false;
1886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < phi_list()->length(); i++) {
1887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = phi_list()->at(i);
1888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue;
1889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < phi->uses()->length(); j++) {
1890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* use = phi->uses()->at(j);
1891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (!use->CheckFlag(HValue::kTruncatingToInt32)) {
1892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          phi->ClearFlag(HValue::kTruncatingToInt32);
1893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          change = true;
1894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          break;
1895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
190044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ZoneList<HValue*> value_list(4);
190144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ZoneList<Representation> rep_list(4);
1902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); ++i) {
1903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Process phi instructions first.
1904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < blocks_[i]->phis()->length(); j++) {
1905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = blocks_[i]->phis()->at(j);
190644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      InsertRepresentationChangesForValue(phi, &value_list, &rep_list);
1907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Process normal instructions.
1910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = blocks_[i]->first();
1911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
191244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      InsertRepresentationChangesForValue(current, &value_list, &rep_list);
1913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
1914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
19191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid HGraph::ComputeMinusZeroChecks() {
19201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  BitVector visited(GetMaximumValueID());
19211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = 0; i < blocks_.length(); ++i) {
19221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    for (HInstruction* current = blocks_[i]->first();
19231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block         current != NULL;
19241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block         current = current->next()) {
19251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (current->IsChange()) {
19261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        HChange* change = HChange::cast(current);
19271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // Propagate flags for negative zero checks upwards from conversions
19281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // int32-to-tagged and int32-to-double.
19291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Representation from = change->value()->representation();
19301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ASSERT(from.Equals(change->from()));
19311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if (from.IsInteger32()) {
19321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          ASSERT(change->to().IsTagged() || change->to().IsDouble());
19331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          ASSERT(visited.IsEmpty());
19341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          PropagateMinusZeroChecks(change->value(), &visited);
19351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          visited.Clear();
19361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        }
19371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
19381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
19391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
19401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
19411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
19421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Implementation of utility class to encapsulate the translation state for
1944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// a (possibly inlined) function.
1945e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochFunctionState::FunctionState(HGraphBuilder* owner,
1946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                             CompilationInfo* info,
1947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                             TypeFeedbackOracle* oracle)
1948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    : owner_(owner),
1949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      compilation_info_(info),
1950e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      oracle_(oracle),
1951e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      call_context_(NULL),
1952e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      function_return_(NULL),
1953e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      test_context_(NULL),
1954e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      outer_(owner->function_state()) {
1955e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (outer_ != NULL) {
1956e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // State for an inline function.
1957e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (owner->ast_context()->IsTest()) {
1958e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
1959e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
1960e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if_true->MarkAsInlineReturnTarget();
1961e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if_false->MarkAsInlineReturnTarget();
1962e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // The AstContext constructor pushed on the context stack.  This newed
1963e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // instance is the reason that AstContext can't be BASE_EMBEDDED.
1964e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      test_context_ = new TestContext(owner, if_true, if_false);
1965e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
1966e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      function_return_ = owner->graph()->CreateBasicBlock();
1967e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      function_return()->MarkAsInlineReturnTarget();
1968e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1969e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Set this after possibly allocating a new TestContext above.
1970e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    call_context_ = owner->ast_context();
1971e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1972e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1973e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Push on the state stack.
1974e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  owner->set_function_state(this);
1975e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1976e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1977e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1978e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochFunctionState::~FunctionState() {
1979e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  delete test_context_;
1980e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  owner_->set_function_state(outer_);
1981e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1982e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1983e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Implementation of utility classes to represent an expression's context in
1985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the AST.
1986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
19878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : owner_(owner),
19888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      kind_(kind),
19898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      outer_(owner->ast_context()),
19908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      for_typeof_(false) {
1991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner->set_ast_context(this);  // Push.
1992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
19939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  original_length_ = owner->environment()->length();
1994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
1995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAstContext::~AstContext() {
1999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner_->set_ast_context(outer_);  // Pop.
2000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochEffectContext::~EffectContext() {
2004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(owner()->HasStackOverflow() ||
2005e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         owner()->current_block() == NULL ||
20069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block         owner()->environment()->length() == original_length_);
2007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochValueContext::~ValueContext() {
2011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(owner()->HasStackOverflow() ||
2012e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         owner()->current_block() == NULL ||
20139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block         owner()->environment()->length() == original_length_ + 1);
2014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid EffectContext::ReturnValue(HValue* value) {
2018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The value is simply ignored.
2019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid ValueContext::ReturnValue(HValue* value) {
2023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The value is tracked in the bailout environment, and communicated
2024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // through the environment as the result of the expression.
2025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->Push(value);
2026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::ReturnValue(HValue* value) {
2030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BuildBranch(value);
2031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->AddInstruction(instr);
2036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (instr->HasSideEffects()) owner()->AddSimulate(ast_id);
2037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->AddInstruction(instr);
2042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->Push(instr);
2043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (instr->HasSideEffects()) owner()->AddSimulate(ast_id);
2044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraphBuilder* builder = owner();
2049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  builder->AddInstruction(instr);
2050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We expect a simulate after every expression with side effects, though
2051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // this one isn't actually needed (and wouldn't work if it were targeted).
2052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (instr->HasSideEffects()) {
2053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    builder->Push(instr);
2054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    builder->AddSimulate(ast_id);
2055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    builder->Pop();
2056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BuildBranch(instr);
2058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::BuildBranch(HValue* value) {
2062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We expect the graph to be in edge-split form: there is no edge that
2063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // connects a branch node to a join node.  We conservatively ensure that
2064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // property by always adding an empty block on the outgoing edges of this
2065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // branch.
2066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraphBuilder* builder = owner();
2067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
20698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HTest* test = new(zone()) HTest(value, empty_true, empty_false);
2070e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  builder->current_block()->Finish(test);
2071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
207244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  empty_true->Goto(if_true(), false);
207344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  empty_false->Goto(if_false(), false);
2074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  builder->set_current_block(NULL);
2075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// HGraphBuilder infrastructure for bailing out and checking bailouts.
20798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#define CHECK_BAILOUT(call)                     \
2080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  do {                                          \
20818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    call;                                       \
2082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (HasStackOverflow()) return;             \
2083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } while (false)
2084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
20868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#define CHECK_ALIVE(call)                                       \
2087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  do {                                                          \
20888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    call;                                                       \
20898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (HasStackOverflow() || current_block() == NULL) return;  \
2090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } while (false)
2091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::Bailout(const char* reason) {
2094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_bailout) {
2095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
2096e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *name, reason);
2097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetStackOverflow();
2099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForEffect(Expression* expr) {
2103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EffectContext for_effect(this);
2104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Visit(expr);
2105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForValue(Expression* expr) {
2109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ValueContext for_value(this);
2110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Visit(expr);
2111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
21148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid HGraphBuilder::VisitForTypeOf(Expression* expr) {
21158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ValueContext for_value(this);
21168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  for_value.set_for_typeof(true);
21178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Visit(expr);
21188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
21198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
21208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
21218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForControl(Expression* expr,
2123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    HBasicBlock* true_block,
2124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    HBasicBlock* false_block) {
2125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TestContext for_test(this, true_block, false_block);
2126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Visit(expr);
2127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
21301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid HGraphBuilder::VisitArgument(Expression* expr) {
21318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(expr));
21328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Push(AddInstruction(new(zone()) HPushArgument(Pop())));
2133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) {
2137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < arguments->length(); i++) {
21388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitArgument(arguments->at(i)));
2139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) {
2144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < exprs->length(); ++i) {
21458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(exprs->at(i)));
2146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHGraph* HGraphBuilder::CreateGraph() {
21518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  graph_ = new(zone()) HGraph(info());
215244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info());
2153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
2155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhase phase("Block building");
215644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    current_block_ = graph()->entry_block();
2157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Scope* scope = info()->scope();
2159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (scope->HasIllegalRedeclaration()) {
2160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Bailout("function with illegal redeclaration");
2161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      return NULL;
2162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetupScope(scope);
2164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitDeclarations(scope->declarations());
21658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HStackCheck());
2166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Add an edge to the body entry.  This is warty: the graph's start
2168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // environment will be used by the Lithium translation as the initial
2169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // environment on graph entry, but it has now been mutated by the
2170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Hydrogen translation of the instructions in the start block.  This
2171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // environment uses values which have not been defined yet.  These
2172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Hydrogen instructions will then be replayed by the Lithium
2173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // translation, so they cannot have an environment effect.  The edge to
2174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // the body's entry block (along with some special logic for the start
2175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // block in HInstruction::InsertAfter) seals the start block from
2176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // getting unwanted instructions inserted.
2177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    //
2178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // TODO(kmillikin): Fix this.  Stop mutating the initial environment.
2179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Make the Hydrogen instructions in the initial block into Hydrogen
2180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // values (but not instructions), present in the initial environment and
2181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // not replayed by the Lithium translation.
2182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HEnvironment* initial_env = environment()->CopyWithoutHistory();
2183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* body_entry = CreateBasicBlock(initial_env);
2184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    current_block()->Goto(body_entry);
21858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    body_entry->SetJoinId(AstNode::kFunctionEntryId);
2186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(body_entry);
2187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    VisitStatements(info()->function()->body());
2188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (HasStackOverflow()) return NULL;
2189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (current_block() != NULL) {
21918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined());
2192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      current_block()->FinishExit(instr);
2193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(NULL);
2194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  graph()->OrderBlocks();
2198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  graph()->AssignDominators();
2199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  graph()->EliminateRedundantPhis();
220044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis();
2201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!graph()->CollectPhis()) {
2202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Bailout("Phi-use of arguments object");
2203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return NULL;
2204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HInferRepresentation rep(graph());
2207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  rep.Analyze();
2208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_use_range) {
2210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HRangeAnalysis rangeAnalysis(graph());
2211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    rangeAnalysis.Analyze();
2212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  graph()->InitializeInferredTypes();
2215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  graph()->Canonicalize();
2216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  graph()->InsertRepresentationChanges();
2217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  graph()->ComputeMinusZeroChecks();
2218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Eliminate redundant stack checks on backwards branches.
2220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HStackCheckEliminator sce(graph());
2221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  sce.Process();
2222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Perform common subexpression elimination and loop-invariant code motion.
2224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_use_gvn) {
2225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HPhase phase("Global value numbering", graph());
2226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HGlobalValueNumberer gvn(graph(), info());
2227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    gvn.Analyze();
2228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return graph();
2231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
2235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
2236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->AddInstruction(instr);
2237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
2238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddSimulate(int id) {
2242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
2243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->AddSimulate(id);
2244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddPhi(HPhi* instr) {
2248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
2249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->AddPhi(instr);
2250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::PushAndAdd(HInstruction* instr) {
2254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Push(instr);
2255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(instr);
2256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochtemplate <int V>
2260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHInstruction* HGraphBuilder::PreProcessCall(HCall<V>* call) {
22611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int count = call->argument_count();
22621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ZoneList<HValue*> arguments(count);
22631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = 0; i < count; ++i) {
22641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    arguments.Add(Pop());
2265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  while (!arguments.is_empty()) {
22688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast()));
2269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return call;
2271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::SetupScope(Scope* scope) {
2275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We don't yet handle the function name for named function expressions.
22768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (scope->function() != NULL) return Bailout("named function expression");
2277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HConstant* undefined_constant = new(zone()) HConstant(
227944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->factory()->undefined_value(), Representation::Tagged());
2280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(undefined_constant);
2281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_->set_undefined_constant(undefined_constant);
2282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Set the initial values of parameters including "this".  "This" has
2284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // parameter index 0.
2285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int count = scope->num_parameters() + 1;
2286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < count; ++i) {
22878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* parameter = AddInstruction(new(zone()) HParameter(i));
2288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    environment()->Bind(i, parameter);
2289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Set the initial values of stack-allocated locals.
22929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  for (int i = count; i < environment()->length(); ++i) {
2293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    environment()->Bind(i, undefined_constant);
2294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Handle the arguments and arguments shadow variables specially (they do
2297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // not have declarations).
2298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (scope->arguments() != NULL) {
2299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (!scope->arguments()->IsStackAllocated() ||
230044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        (scope->arguments_shadow() != NULL &&
230144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        !scope->arguments_shadow()->IsStackAllocated())) {
23028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return Bailout("context-allocated arguments");
2303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
23048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HArgumentsObject* object = new(zone()) HArgumentsObject;
2305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(object);
2306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    graph()->SetArgumentsObject(object);
2307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    environment()->Bind(scope->arguments(), object);
230844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (scope->arguments_shadow() != NULL) {
230944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      environment()->Bind(scope->arguments_shadow(), object);
231044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
2311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
2316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < statements->length(); i++) {
23178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(Visit(statements->at(i)));
2318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
2323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* b = graph()->CreateBasicBlock();
2324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  b->SetInitialEnvironment(env);
2325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return b;
2326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
2330e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* header = graph()->CreateBasicBlock();
2331e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
2332e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  header->SetInitialEnvironment(entry_env);
2333e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  header->AttachLoopInformation();
2334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return header;
2335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBlock(Block* stmt) {
23398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
23408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
23418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueInfo break_info(stmt);
2343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  { BreakAndContinueScope push(&break_info, this);
23448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_BAILOUT(VisitStatements(stmt->statements()));
2345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* break_block = break_info.break_block();
2347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (break_block != NULL) {
2348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (current_block() != NULL) current_block()->Goto(break_block);
2349e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    break_block->SetJoinId(stmt->ExitId());
2350e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(break_block);
2351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
23568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
23578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
23588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForEffect(stmt->expression());
2360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
23648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
23658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
23668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitIfStatement(IfStatement* stmt) {
23718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
23728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
23738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (stmt->condition()->ToBooleanIsTrue()) {
2375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddSimulate(stmt->ThenId());
2376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Visit(stmt->then_statement());
2377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (stmt->condition()->ToBooleanIsFalse()) {
2378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddSimulate(stmt->ElseId());
2379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Visit(stmt->else_statement());
2380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* cond_true = graph()->CreateBasicBlock();
2382e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* cond_false = graph()->CreateBasicBlock();
23838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false));
2384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
23858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (cond_true->HasPredecessor()) {
23868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      cond_true->SetJoinId(stmt->ThenId());
23878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      set_current_block(cond_true);
23888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_BAILOUT(Visit(stmt->then_statement()));
23898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      cond_true = current_block();
23908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else {
23918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      cond_true = NULL;
23928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
2393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
23948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (cond_false->HasPredecessor()) {
23958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      cond_false->SetJoinId(stmt->ElseId());
23968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      set_current_block(cond_false);
23978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_BAILOUT(Visit(stmt->else_statement()));
23988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      cond_false = current_block();
23998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else {
24008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      cond_false = NULL;
24018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
2402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
24038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->id());
2404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(join);
2405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2409e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::BreakAndContinueScope::Get(
2410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    BreakableStatement* stmt,
2411e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    BreakType type) {
2412e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueScope* current = this;
2413e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while (current != NULL && current->info()->target() != stmt) {
2414e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    current = current->next();
2415e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current != NULL);  // Always found (unless stack is malformed).
2417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* block = NULL;
2418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  switch (type) {
2419e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case BREAK:
2420e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      block = current->info()->break_block();
2421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (block == NULL) {
2422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        block = current->owner()->graph()->CreateBasicBlock();
2423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        current->info()->set_break_block(block);
2424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2427e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case CONTINUE:
2428e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      block = current->info()->continue_block();
2429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (block == NULL) {
2430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        block = current->owner()->graph()->CreateBasicBlock();
2431e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        current->info()->set_continue_block(block);
2432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return block;
2437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
24418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
24428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
24438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE);
2445e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Goto(continue_block);
2446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(NULL);
2447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
24518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
24528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
24538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK);
2455e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Goto(break_block);
2456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(NULL);
2457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
24618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
24628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
24638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AstContext* context = call_context();
2465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (context == NULL) {
2466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Not an inlined return, so an actual one.
24678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(stmt->expression()));
2468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* result = environment()->Pop();
24698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    current_block()->FinishExit(new(zone()) HReturn(result));
2470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(NULL);
2471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Return from an inlined function, visit the subexpression in the
2473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // expression context of the call.
2474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (context->IsTest()) {
2475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TestContext* test = TestContext::cast(context);
2476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VisitForControl(stmt->expression(),
2477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      test->if_true(),
2478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      test->if_false());
247944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else if (context->IsEffect()) {
24808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForEffect(stmt->expression()));
248144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      current_block()->Goto(function_return(), false);
2482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
248344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(context->IsValue());
24848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(stmt->expression()));
248544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HValue* return_value = environment()->Pop();
248644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      current_block()->AddLeaveInlined(return_value, function_return());
2487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
248844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    set_current_block(NULL);
2489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
24948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
24958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
24968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
24978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("WithEnterStatement");
2498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
25028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
25038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
25048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
25058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("WithExitStatement");
2506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
25108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
25118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
25128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
251344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // We only optimize switch statements with smi-literal smi comparisons,
251444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // with a bounded number of clauses.
251544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kCaseClauseLimit = 128;
251644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ZoneList<CaseClause*>* clauses = stmt->cases();
251744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int clause_count = clauses->length();
251844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (clause_count > kCaseClauseLimit) {
25198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return Bailout("SwitchStatement: too many clauses");
252044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
252144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
25228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(stmt->tag()));
2523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddSimulate(stmt->EntryId());
252444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HValue* tag_value = Pop();
252544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* first_test_block = current_block();
2526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
252744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // 1. Build all the tests, with dangling true branches.  Unconditionally
252844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // deoptimize if we encounter a non-smi comparison.
252944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < clause_count; ++i) {
2530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CaseClause* clause = clauses->at(i);
2531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (clause->is_default()) continue;
2532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!clause->label()->IsSmiLiteral()) {
25338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return Bailout("SwitchStatement: non-literal switch label");
2534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
253644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Unconditionally deoptimize on the first non-smi compare.
253744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    clause->RecordTypeFeedback(oracle());
253844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!clause->IsSmiCompare()) {
253944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      current_block()->FinishExitWithDeoptimization();
254044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      set_current_block(NULL);
254144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
2542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
254444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Otherwise generate a compare and branch.
25458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(clause->label()));
254644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* label_value = Pop();
25478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HCompare* compare =
25488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        new(zone()) HCompare(tag_value, label_value, Token::EQ_STRICT);
254944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    compare->SetInputRepresentation(Representation::Integer32());
255044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(!compare->HasSideEffects());
255144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AddInstruction(compare);
255244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HBasicBlock* body_block = graph()->CreateBasicBlock();
255344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HBasicBlock* next_test_block = graph()->CreateBasicBlock();
25548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HTest* branch = new(zone()) HTest(compare, body_block, next_test_block);
255544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    current_block()->Finish(branch);
255644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    set_current_block(next_test_block);
255744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
255844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
255944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Save the current block to use for the default or to join with the
256044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // exit.  This block is NULL if we deoptimized.
256144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* last_block = current_block();
256244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
256344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // 2. Loop over the clauses and the linked list of tests in lockstep,
256444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // translating the clause bodies.
256544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* curr_test_block = first_test_block;
256644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* fall_through_block = NULL;
256744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BreakAndContinueInfo break_info(stmt);
256844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  { BreakAndContinueScope push(&break_info, this);
256944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 0; i < clause_count; ++i) {
257044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      CaseClause* clause = clauses->at(i);
257144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
257244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Identify the block where normal (non-fall-through) control flow
257344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // goes to.
257444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HBasicBlock* normal_block = NULL;
257544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (clause->is_default() && last_block != NULL) {
257644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        normal_block = last_block;
257744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        last_block = NULL;  // Cleared to indicate we've handled it.
257844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else if (!curr_test_block->end()->IsDeoptimize()) {
257944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        normal_block = curr_test_block->end()->FirstSuccessor();
258044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        curr_test_block = curr_test_block->end()->SecondSuccessor();
258144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
2582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
258344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Identify a block to emit the body into.
258444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (normal_block == NULL) {
258544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (fall_through_block == NULL) {
258644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          // (a) Unreachable.
258744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (clause->is_default()) {
258844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            continue;  // Might still be reachable clause bodies.
258944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
259044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
259144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
259244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
259344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          // (b) Reachable only as fall through.
259444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          set_current_block(fall_through_block);
2595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
259644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else if (fall_through_block == NULL) {
259744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // (c) Reachable only normally.
259844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        set_current_block(normal_block);
2599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
260044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // (d) Reachable both ways.
260144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        HBasicBlock* join = CreateJoin(fall_through_block,
260244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       normal_block,
260344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       clause->EntryId());
260444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        set_current_block(join);
2605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
2606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
26078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_BAILOUT(VisitStatements(clause->statements()));
260844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      fall_through_block = current_block();
2609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
261244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Create an up-to-3-way join.  Use the break block if it exists since
261344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // it's already a join block.
261444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* break_block = break_info.break_block();
261544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (break_block == NULL) {
261644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    set_current_block(CreateJoin(fall_through_block,
261744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 last_block,
261844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 stmt->ExitId()));
2619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
262044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (fall_through_block != NULL) fall_through_block->Goto(break_block);
262144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (last_block != NULL) last_block->Goto(break_block);
262244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    break_block->SetJoinId(stmt->ExitId());
262344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    set_current_block(break_block);
2624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
262744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
2629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return statement->OsrEntryId() == info()->osr_ast_id();
2630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
2634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!HasOsrEntryAt(statement)) return;
2635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
2637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* osr_entry = graph()->CreateBasicBlock();
2638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* true_value = graph()->GetConstantTrue();
26398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HTest* test = new(zone()) HTest(true_value, non_osr_entry, osr_entry);
2640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Finish(test);
2641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
2643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  non_osr_entry->Goto(loop_predecessor);
2644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2645e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(osr_entry);
2646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int osr_entry_id = statement->OsrEntryId();
2647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We want the correct environment at the OsrEntry instruction.  Build
2648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // it explicitly.  The expression stack should be empty.
2649e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int count = environment()->length();
2650e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(count ==
2651e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         (environment()->parameter_count() + environment()->local_count()));
2652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < count; ++i) {
26538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HUnknownOSRValue* unknown = new(zone()) HUnknownOSRValue;
2654e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    AddInstruction(unknown);
2655e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    environment()->Bind(i, unknown);
2656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2658e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  AddSimulate(osr_entry_id);
26598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HOsrEntry(osr_entry_id));
2660e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Goto(loop_predecessor);
2661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  loop_predecessor->SetJoinId(statement->EntryId());
2662e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_predecessor);
2663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
26678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
26688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
26698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2670e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
2671e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  PreProcessOsrEntry(stmt);
2672e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2673e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Goto(loop_entry, false);
2674e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_entry);
2675e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2676e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueInfo break_info(stmt);
2677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  { BreakAndContinueScope push(&break_info, this);
26788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_BAILOUT(Visit(stmt->body()));
2679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* body_exit =
2681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      JoinContinue(stmt, current_block(), break_info.continue_block());
2682e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_successor = NULL;
2683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
2684e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(body_exit);
2685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // The block for a true condition, the actual predecessor block of the
2686e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // back edge.
2687e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    body_exit = graph()->CreateBasicBlock();
2688e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    loop_successor = graph()->CreateBasicBlock();
26898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
26908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (body_exit->HasPredecessor()) {
26918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      body_exit->SetJoinId(stmt->BackEdgeId());
26928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else {
26938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      body_exit = NULL;
26948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
26958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (loop_successor->HasPredecessor()) {
26968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      loop_successor->SetJoinId(stmt->ExitId());
26978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else {
26988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      loop_successor = NULL;
26998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
2700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2701e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_exit = CreateLoop(stmt,
2702e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_entry,
2703e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      body_exit,
2704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_successor,
2705e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      break_info.break_block());
2706e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_exit);
2707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2710e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
27118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
27128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
27138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2714e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
2715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  PreProcessOsrEntry(stmt);
2716e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2717e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Goto(loop_entry, false);
2718e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_entry);
2719e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2720e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // If the condition is constant true, do not generate a branch.
2721e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_successor = NULL;
2722e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!stmt->cond()->ToBooleanIsTrue()) {
2723e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* body_entry = graph()->CreateBasicBlock();
2724e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    loop_successor = graph()->CreateBasicBlock();
27258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
27268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (body_entry->HasPredecessor()) {
27278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      body_entry->SetJoinId(stmt->BodyId());
27288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      set_current_block(body_entry);
27298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
27308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (loop_successor->HasPredecessor()) {
27318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      loop_successor->SetJoinId(stmt->ExitId());
27328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else {
27338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      loop_successor = NULL;
27348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
2735e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2736e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2737e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueInfo break_info(stmt);
27388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (current_block() != NULL) {
27398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    BreakAndContinueScope push(&break_info, this);
27408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_BAILOUT(Visit(stmt->body()));
2741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2742e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* body_exit =
2743e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      JoinContinue(stmt, current_block(), break_info.continue_block());
2744e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_exit = CreateLoop(stmt,
2745e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_entry,
2746e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      body_exit,
2747e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_successor,
2748e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      break_info.break_block());
2749e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_exit);
2750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForStatement(ForStatement* stmt) {
27548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
27558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
27568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2757e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (stmt->init() != NULL) {
27588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(Visit(stmt->init()));
2759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2760e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
2761e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  PreProcessOsrEntry(stmt);
2762e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2763e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Goto(loop_entry, false);
2764e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_entry);
2765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2766e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_successor = NULL;
2767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (stmt->cond() != NULL) {
2768e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* body_entry = graph()->CreateBasicBlock();
2769e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    loop_successor = graph()->CreateBasicBlock();
27708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
27718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (body_entry->HasPredecessor()) {
27728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      body_entry->SetJoinId(stmt->BodyId());
27738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      set_current_block(body_entry);
27748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
27758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (loop_successor->HasPredecessor()) {
27768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      loop_successor->SetJoinId(stmt->ExitId());
27778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else {
27788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      loop_successor = NULL;
27798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
2780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2782e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueInfo break_info(stmt);
27838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (current_block() != NULL) {
27848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    BreakAndContinueScope push(&break_info, this);
27858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_BAILOUT(Visit(stmt->body()));
2786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2787e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* body_exit =
2788e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      JoinContinue(stmt, current_block(), break_info.continue_block());
2789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2790e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (stmt->next() != NULL && body_exit != NULL) {
2791e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(body_exit);
27928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_BAILOUT(Visit(stmt->next()));
2793e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    body_exit = current_block();
2794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2796e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_exit = CreateLoop(stmt,
2797e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_entry,
2798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      body_exit,
2799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_successor,
2800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      break_info.break_block());
2801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_exit);
2802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
28068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
28078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
28088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
28098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("ForInStatement");
2810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
28148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
28158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
28168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
28178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("TryCatchStatement");
2818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
28228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
28238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
28248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
28258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("TryFinallyStatement");
2826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
28308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
28318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
28328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
28338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("DebuggerStatement");
28348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
28358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
28368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
28378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic Handle<SharedFunctionInfo> SearchSharedFunctionInfo(
28388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Code* unoptimized_code, FunctionLiteral* expr) {
28398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int start_position = expr->start_position();
28408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  RelocIterator it(unoptimized_code);
28418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  for (;!it.done(); it.next()) {
28428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    RelocInfo* rinfo = it.rinfo();
28438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue;
28448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Object* obj = rinfo->target_object();
28458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (obj->IsSharedFunctionInfo()) {
28468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
28478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (shared->start_position() == start_position) {
28488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        return Handle<SharedFunctionInfo>(shared);
28498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
28508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
28518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
28528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
28538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Handle<SharedFunctionInfo>();
2854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
28588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
28598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
28608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<SharedFunctionInfo> shared_info =
28628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      SearchSharedFunctionInfo(info()->shared_info()->code(),
28638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                               expr);
28648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (shared_info.is_null()) {
28658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    shared_info = Compiler::BuildFunctionInfo(expr, info()->script());
28668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
28678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // We also have a stack overflow if the recursive compilation did.
28688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (HasStackOverflow()) return;
2869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HFunctionLiteral* instr =
28708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HFunctionLiteral(shared_info, expr->pretenure());
2871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(instr, expr->id());
2872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitSharedFunctionInfoLiteral(
2876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SharedFunctionInfoLiteral* expr) {
28778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
28788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
28798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
28808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("SharedFunctionInfoLiteral");
2881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitConditional(Conditional* expr) {
28858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
28868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
28878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2888e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* cond_true = graph()->CreateBasicBlock();
2889e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* cond_false = graph()->CreateBasicBlock();
28908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
2891e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
289244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Visit the true and false subexpressions in the same AST context as the
289344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // whole expression.
28948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (cond_true->HasPredecessor()) {
28958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    cond_true->SetJoinId(expr->ThenId());
28968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    set_current_block(cond_true);
28978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_BAILOUT(Visit(expr->then_expression()));
28988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    cond_true = current_block();
28998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
29008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    cond_true = NULL;
29018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
2902e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
29038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (cond_false->HasPredecessor()) {
29048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    cond_false->SetJoinId(expr->ElseId());
29058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    set_current_block(cond_false);
29068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_BAILOUT(Visit(expr->else_expression()));
29078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    cond_false = current_block();
29088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
29098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    cond_false = NULL;
29108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
2911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
291244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!ast_context()->IsTest()) {
29138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
291444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    set_current_block(join);
29158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (join != NULL && !ast_context()->IsEffect()) {
29168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      ast_context()->ReturnValue(Pop());
29178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
291844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
2919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
29228b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochHGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty(
29238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Variable* var, LookupResult* lookup, bool is_store) {
29248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (var->is_this() || !info()->has_global_object()) {
29258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return kUseGeneric;
2926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2927e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<GlobalObject> global(info()->global_object());
2928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  global->Lookup(*var->name(), lookup);
29298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!lookup->IsProperty() ||
29308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      lookup->type() != NORMAL ||
29318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      (is_store && lookup->IsReadOnly()) ||
29328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      lookup->holder() != *global) {
29338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return kUseGeneric;
29341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
29358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
29368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return kUseCell;
29371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
29381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
29391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
29401e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockHValue* HGraphBuilder::BuildContextChainWalk(Variable* var) {
29411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(var->IsContextSlot());
29428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* context = new(zone()) HContext;
29431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
2944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int length = info()->scope()->ContextChainLength(var->scope());
29451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  while (length-- > 0) {
29468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    context = new(zone()) HOuterContext(context);
29471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    AddInstruction(context);
29481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
29491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return context;
2950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
29548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
29558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
29568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Variable* variable = expr->AsVariable();
2958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (variable == NULL) {
29598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return Bailout("reference to rewritten variable");
2960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (variable->IsStackAllocated()) {
2961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) {
29628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return Bailout("unsupported context for arguments object");
2963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnValue(environment()->Lookup(variable));
2965b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  } else if (variable->IsContextSlot()) {
2966b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    if (variable->mode() == Variable::CONST) {
29678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return Bailout("reference to const context slot");
2968b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
29691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    HValue* context = BuildContextChainWalk(variable);
29701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int index = variable->AsSlot()->index();
29718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, index);
2972b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    ast_context()->ReturnInstruction(instr, expr->id());
2973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (variable->is_global()) {
2974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LookupResult lookup;
29758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false);
2976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
29778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (type == kUseCell &&
29788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        info()->global_object()->IsAccessCheckNeeded()) {
29798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      type = kUseGeneric;
29808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
29818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
29828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (type == kUseCell) {
29838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      Handle<GlobalObject> global(info()->global_object());
29848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
29858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
29868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole);
29878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      ast_context()->ReturnInstruction(instr, expr->id());
29888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else {
29898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HContext* context = new(zone()) HContext;
29908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      AddInstruction(context);
29918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HGlobalObject* global_object = new(zone()) HGlobalObject(context);
29928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      AddInstruction(global_object);
29938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HLoadGlobalGeneric* instr =
29948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          new(zone()) HLoadGlobalGeneric(context,
29958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                         global_object,
29968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                         variable->name(),
29978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                         ast_context()->is_for_typeof());
29988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      instr->set_position(expr->position());
29998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      ASSERT(instr->HasSideEffects());
30008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      ast_context()->ReturnInstruction(instr, expr->id());
3001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
30038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return Bailout("reference to a variable which requires dynamic lookup");
3004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitLiteral(Literal* expr) {
30098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
30108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
30118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
30128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HConstant* instr =
30138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HConstant(expr->handle(), Representation::Tagged());
3014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(instr, expr->id());
3015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
30198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
30208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
30218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
30228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HRegExpLiteral* instr = new(zone()) HRegExpLiteral(expr->pattern(),
30238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                     expr->flags(),
30248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                     expr->literal_index());
3025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(instr, expr->id());
3026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
30308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
30318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
30328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
30338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
30341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
30358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HObjectLiteral* literal =
30368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HObjectLiteral(context,
30378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                 expr->constant_properties(),
30388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                 expr->fast_elements(),
30398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                 expr->literal_index(),
30408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                 expr->depth(),
30418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                 expr->has_function());
3042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The object is expected in the bailout environment during computation
3043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // of the property values and is the value of the entire expression.
3044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushAndAdd(literal);
3045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->CalculateEmitStore();
3047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < expr->properties()->length(); i++) {
3049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ObjectLiteral::Property* property = expr->properties()->at(i);
3050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (property->IsCompileTimeValue()) continue;
3051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Literal* key = property->key();
3053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Expression* value = property->value();
3054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    switch (property->kind()) {
3056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
3057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
3058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Fall through.
3059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::COMPUTED:
3060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (key->handle()->IsSymbol()) {
3061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (property->emit_store()) {
30628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            CHECK_ALIVE(VisitForValue(value));
3063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HValue* value = Pop();
3064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            Handle<String> name = Handle<String>::cast(key->handle());
30651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            HStoreNamedGeneric* store =
30668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                new(zone()) HStoreNamedGeneric(
30678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                context,
30688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                literal,
30698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                name,
30708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                value,
30718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                function_strict_mode());
30721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            AddInstruction(store);
3073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AddSimulate(key->id());
3074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else {
30758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            CHECK_ALIVE(VisitForEffect(value));
3076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
3077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          break;
3078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
3079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Fall through.
3080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::PROTOTYPE:
3081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::SETTER:
3082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::GETTER:
30838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        return Bailout("Object literal with complex property");
3084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      default: UNREACHABLE();
3085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
308744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
308844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (expr->has_function()) {
308944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Return the result of the transformation to fast properties
309044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // instead of the original since this operation changes the map
309144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // of the object. This makes sure that the original object won't
309244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // be used by other optimized code before it is transformed
309344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // (e.g. because of code motion).
30948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HToFastProperties* result = new(zone()) HToFastProperties(Pop());
309544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AddInstruction(result);
309644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ast_context()->ReturnValue(result);
309744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
309844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ast_context()->ReturnValue(Pop());
309944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
3100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
31048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
31058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
31068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<Expression*>* subexprs = expr->values();
3108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = subexprs->length();
3109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
31108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HArrayLiteral* literal = new(zone()) HArrayLiteral(expr->constant_elements(),
31118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                     length,
31128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                     expr->literal_index(),
31138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                     expr->depth());
3114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The array is expected in the bailout environment during computation
3115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // of the property values and is the value of the entire expression.
3116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushAndAdd(literal);
3117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HLoadElements* elements = NULL;
3119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; i++) {
3121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Expression* subexpr = subexprs->at(i);
3122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // If the subexpression is a literal or a simple materialized literal it
3123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // is already set in the cloned array.
3124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
3125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
31268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(subexpr));
3127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = Pop();
31288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal");
3129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Load the elements array before the first store.
3131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (elements == NULL)  {
31328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch     elements = new(zone()) HLoadElements(literal);
3133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch     AddInstruction(elements);
3134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
31368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HValue* key = AddInstruction(
31378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)),
31388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                              Representation::Integer32()));
31398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value));
3140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddSimulate(expr->GetIdForElement(i));
3141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnValue(Pop());
3143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
31478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
31488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
31498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
31508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("CatchExtensionObject");
3151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Sets the lookup result and returns true if the store can be inlined.
3155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool ComputeStoredField(Handle<Map> type,
3156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               Handle<String> name,
3157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               LookupResult* lookup) {
3158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  type->LookupInDescriptors(NULL, *name, lookup);
3159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!lookup->IsPropertyOrTransition()) return false;
3160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup->type() == FIELD) return true;
3161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return (lookup->type() == MAP_TRANSITION) &&
3162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      (type->unused_property_fields() > 0);
3163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic int ComputeStoredFieldIndex(Handle<Map> type,
3167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                   Handle<String> name,
3168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                   LookupResult* lookup) {
3169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(lookup->type() == FIELD || lookup->type() == MAP_TRANSITION);
3170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup->type() == FIELD) {
3171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return lookup->GetLocalFieldIndexFromMap(*type);
3172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Map* transition = lookup->GetTransitionMapFromMap(*type);
3174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return transition->PropertyIndexFor(*name) - type->inobject_properties();
3175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
3180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  Handle<String> name,
3181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  HValue* value,
3182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  Handle<Map> type,
3183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  LookupResult* lookup,
3184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  bool smi_and_map_check) {
3185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (smi_and_map_check) {
31868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(object));
31878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckMap(object, type));
3188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = ComputeStoredFieldIndex(type, name, lookup);
3191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_in_object = index < 0;
3192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int offset = index * kPointerSize;
3193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (index < 0) {
3194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Negative property indices are in-object properties, indexed
3195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // from the end of the fixed part of the object.
3196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset += type->instance_size();
3197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset += FixedArray::kHeaderSize;
3199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HStoreNamedField* instr =
32018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HStoreNamedField(object, name, value, is_in_object, offset);
3202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup->type() == MAP_TRANSITION) {
3203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Map> transition(lookup->GetTransitionMapFromMap(*type));
3204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_transition(transition);
3205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // TODO(fschneider): Record the new map type of the object in the IR to
3206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // enable elimination of redundant checks after the transition store.
3207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->SetFlag(HValue::kChangesMaps);
3208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
3210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
3214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    Handle<String> name,
3215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    HValue* value) {
32168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
32171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
32188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HStoreNamedGeneric(
32198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         context,
32208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         object,
32218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         name,
32228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         value,
32238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         function_strict_mode());
3224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
3228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             HValue* value,
3229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             Expression* expr) {
3230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = (expr->AsProperty() != NULL)
3231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ? expr->AsProperty()
3232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : expr->AsAssignment()->target()->AsProperty();
3233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Literal* key = prop->key()->AsLiteral();
3234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<String> name = Handle<String>::cast(key->handle());
3235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!name.is_null());
3236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LookupResult lookup;
3238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneMapList* types = expr->GetReceiverTypes();
3239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_monomorphic = expr->IsMonomorphic() &&
3240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ComputeStoredField(types->first(), name, &lookup);
3241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return is_monomorphic
3243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ? BuildStoreNamedField(object, name, value, types->first(), &lookup,
3244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             true)  // Needs smi and map check.
3245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : BuildStoreNamedGeneric(object, name, value);
3246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
3250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     HValue* object,
3251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     HValue* value,
3252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     ZoneMapList* types,
3253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Handle<String> name) {
3254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // TODO(ager): We should recognize when the prototype chains for different
3255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // maps are identical. In that case we can avoid repeatedly generating the
3256e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // same prototype map checks.
3257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int count = 0;
3258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* join = NULL;
3259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
3260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Map> map = types->at(i);
3261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LookupResult lookup;
3262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (ComputeStoredField(map, name, &lookup)) {
3263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (count == 0) {
32648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckNonSmi(object));  // Only needed once.
3265e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        join = graph()->CreateBasicBlock();
3266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
3267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ++count;
3268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* if_true = graph()->CreateBasicBlock();
3269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* if_false = graph()->CreateBasicBlock();
32708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HCompareMap* compare =
32718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          new(zone()) HCompareMap(object, map, if_true, if_false);
3272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      current_block()->Finish(compare);
3273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(if_true);
3275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instr =
3276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          BuildStoreNamedField(object, name, value, map, &lookup, false);
3277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr->set_position(expr->position());
3278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Goto will add the HSimulate for the store.
3279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(instr);
3280e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (!ast_context()->IsEffect()) Push(value);
3281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      current_block()->Goto(join);
3282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(if_false);
3284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Finish up.  Unconditionally deoptimize if we've handled all the maps we
3288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // know about and do not want to handle ones we've never seen.  Otherwise
3289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // use a generic IC.
3290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
329144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    current_block()->FinishExitWithDeoptimization();
3292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
32931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
3294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_position(expr->position());
3295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(instr);
3296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (join != NULL) {
3298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (!ast_context()->IsEffect()) Push(value);
3299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      current_block()->Goto(join);
3300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
3301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // The HSimulate for the store should not see the stored value in
3302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // effect contexts (it is not materialized at expr->id() in the
3303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // unoptimized code).
3304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (instr->HasSideEffects()) {
3305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (ast_context()->IsEffect()) {
3306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          AddSimulate(expr->id());
3307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else {
3308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          Push(value);
3309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          AddSimulate(expr->id());
3310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          Drop(1);
3311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
3312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
3313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ast_context()->ReturnValue(value);
3314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      return;
33159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
3316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(join != NULL);
3319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  join->SetJoinId(expr->id());
3320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(join);
3321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
3322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
3326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = expr->target()->AsProperty();
3327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(prop != NULL);
3328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->RecordTypeFeedback(oracle());
33298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(prop->obj()));
3330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = NULL;
3332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = NULL;
3333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (prop->key()->IsPropertyName()) {
3335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Named store.
33368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->value()));
3337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    value = Pop();
3338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* object = Pop();
3339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Literal* key = prop->key()->AsLiteral();
3341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = Handle<String>::cast(key->handle());
3342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!name.is_null());
3343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ZoneMapList* types = expr->GetReceiverTypes();
3345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LookupResult lookup;
3346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (expr->IsMonomorphic()) {
3348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = BuildStoreNamed(object, value, expr);
3349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (types != NULL && types->length() > 1) {
3351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandlePolymorphicStoreNamedField(expr, object, value, types, name);
3352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
3353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
33551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      instr = BuildStoreNamedGeneric(object, name, value);
3356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Keyed store.
33608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(prop->key()));
33618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->value()));
3362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    value = Pop();
3363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* key = Pop();
3364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* object = Pop();
33658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr = BuildStoreKeyed(object, key, value, expr);
3366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Push(value);
3368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(expr->position());
3369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(instr);
3370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnValue(Pop());
3372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Because not every expression has a position and there is not common
3376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// superclass of Assignment and CountOperation, we cannot just pass the
3377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// owning expression instead of position and ast_id separately.
3378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
3379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   HValue* value,
3380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   int position,
3381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   int ast_id) {
3382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LookupResult lookup;
33838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
33848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (type == kUseCell) {
33858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
33868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Handle<GlobalObject> global(info()->global_object());
33878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
33888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* instr = new(zone()) HStoreGlobalCell(value, cell, check_hole);
33898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr->set_position(position);
33908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(instr);
33918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (instr->HasSideEffects()) AddSimulate(ast_id);
33928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
33938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HContext* context = new(zone()) HContext;
33948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(context);
33958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HGlobalObject* global_object = new(zone()) HGlobalObject(context);
33968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(global_object);
33978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HStoreGlobalGeneric* instr =
33988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        new(zone()) HStoreGlobalGeneric(context,
33998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                        global_object,
34008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                        var->name(),
34018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                        value,
34028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                        function_strict_mode());
34038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr->set_position(position);
34048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(instr);
34058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(instr->HasSideEffects());
34068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (instr->HasSideEffects()) AddSimulate(ast_id);
34078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
3408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Expression* target = expr->target();
3413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = target->AsVariableProxy();
3414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Variable* var = proxy->AsVariable();
3415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = target->AsProperty();
3416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(var == NULL || prop == NULL);
3417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We have a second position recorded in the FullCodeGenerator to have
3419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // type feedback for the binary operation.
3420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BinaryOperation* operation = expr->binary_operation();
3421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (var != NULL) {
34238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(operation));
3424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (var->is_global()) {
3426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandleGlobalVariableAssignment(var,
3427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     Top(),
3428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     expr->position(),
3429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     expr->AssignmentId());
3430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else if (var->IsStackAllocated()) {
3431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Bind(var, Top());
3432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else if (var->IsContextSlot()) {
3433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HValue* context = BuildContextChainWalk(var);
3434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      int index = var->AsSlot()->index();
34358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HStoreContextSlot* instr =
34368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          new(zone()) HStoreContextSlot(context, index, Top());
3437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      AddInstruction(instr);
3438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
34408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return Bailout("compound assignment to lookup slot");
3441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnValue(Pop());
3443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (prop != NULL) {
3445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    prop->RecordTypeFeedback(oracle());
3446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (prop->key()->IsPropertyName()) {
3448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Named property.
34498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->obj()));
3450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = Top();
3451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* load = NULL;
3453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (prop->IsMonomorphic()) {
3454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
3455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<Map> map = prop->GetReceiverTypes()->first();
3456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamed(obj, prop, map, name);
3457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
3458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamedGeneric(obj, prop);
3459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
3460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(load);
3461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId());
3462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
34638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(expr->value()));
3464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* right = Pop();
3465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* left = Pop();
3466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instr = BuildBinaryOperation(operation, left, right);
3468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(instr);
3469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (instr->HasSideEffects()) AddSimulate(operation->id());
3470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* store = BuildStoreNamed(obj, instr, prop);
3472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(store);
3473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Drop the simulated receiver and value.  Return the value.
3474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(2);
3475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(instr);
3476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
3477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(Pop());
3478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
3480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Keyed property.
34818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->obj()));
34828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->key()));
3483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = environment()->ExpressionStackAt(1);
3484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* key = environment()->ExpressionStackAt(0);
3485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
34868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HInstruction* load = BuildLoadKeyed(obj, key, prop);
3487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(load);
3488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId());
3489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
34908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(expr->value()));
3491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* right = Pop();
3492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* left = Pop();
3493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instr = BuildBinaryOperation(operation, left, right);
3495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(instr);
3496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (instr->HasSideEffects()) AddSimulate(operation->id());
3497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
34988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      expr->RecordTypeFeedback(oracle());
34998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HInstruction* store = BuildStoreKeyed(obj, key, instr, expr);
3500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(store);
3501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Drop the simulated receiver, key, and value.  Return the value.
3502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(3);
3503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(instr);
3504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
3505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(Pop());
3506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
35098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return Bailout("invalid lhs in compound assignment");
3510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitAssignment(Assignment* expr) {
35158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
35168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
35178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = expr->target()->AsVariableProxy();
3519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Variable* var = proxy->AsVariable();
3520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = expr->target()->AsProperty();
3521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(var == NULL || prop == NULL);
3522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->is_compound()) {
3524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HandleCompoundAssignment(expr);
3525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
3526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (var != NULL) {
35298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (proxy->IsArguments()) return Bailout("assignment to arguments");
3530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Handle the assignment.
35321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (var->IsStackAllocated()) {
35331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      HValue* value = NULL;
35341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Handle stack-allocated variables on the right-hand side directly.
35351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // We do not allow the arguments object to occur in a context where it
35361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // may escape, but assignments to stack-allocated locals are
35371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // permitted.  Handling such assignments here bypasses the check for
35381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // the arguments object in VisitVariableProxy.
35391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Variable* rhs_var = expr->value()->AsVariableProxy()->AsVariable();
35401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (rhs_var != NULL && rhs_var->IsStackAllocated()) {
35411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        value = environment()->Lookup(rhs_var);
35421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
35438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        CHECK_ALIVE(VisitForValue(expr->value()));
35441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        value = Pop();
35451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
35461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Bind(var, value);
35471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ast_context()->ReturnValue(value);
35481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else if (var->IsContextSlot() && var->mode() != Variable::CONST) {
35508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(expr->value()));
35511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      HValue* context = BuildContextChainWalk(var);
35521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      int index = var->AsSlot()->index();
35538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HStoreContextSlot* instr =
35548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          new(zone()) HStoreContextSlot(context, index, Top());
35551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      AddInstruction(instr);
35561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
35571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ast_context()->ReturnValue(Pop());
35581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else if (var->is_global()) {
35608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(expr->value()));
3561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandleGlobalVariableAssignment(var,
3562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     Top(),
3563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     expr->position(),
3564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     expr->AssignmentId());
35651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ast_context()->ReturnValue(Pop());
35661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3567b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    } else {
35688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return Bailout("assignment to LOOKUP or const CONTEXT variable");
3569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (prop != NULL) {
3572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HandlePropertyAssignment(expr);
3573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
35748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return Bailout("invalid left-hand side in assignment");
3575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThrow(Throw* expr) {
35808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
35818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
35828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We don't optimize functions with invalid left-hand sides in
3584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // assignments, count operations, or for-in.  Consequently throw can
3585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // currently only occur in an effect context.
3586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(ast_context()->IsEffect());
35878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->exception()));
3588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = environment()->Pop();
35908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HThrow* instr = new(zone()) HThrow(value);
3591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(expr->position());
35921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(instr);
35931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddSimulate(expr->id());
35948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  current_block()->FinishExit(new(zone()) HAbnormalExit);
3595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(NULL);
3596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
3600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    Property* expr,
3601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    Handle<Map> type,
3602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    LookupResult* lookup,
3603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    bool smi_and_map_check) {
3604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (smi_and_map_check) {
36058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(object));
36068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckMap(object, type));
3607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = lookup->GetLocalFieldIndexFromMap(*type);
3610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (index < 0) {
3611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Negative property indices are in-object properties, indexed
3612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // from the end of the fixed part of the object.
3613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int offset = (index * kPointerSize) + type->instance_size();
36148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return new(zone()) HLoadNamedField(object, true, offset);
3615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Non-negative property indices are in the properties array.
3617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
36188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return new(zone()) HLoadNamedField(object, false, offset);
3619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj,
3624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   Property* expr) {
3625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(expr->key()->IsPropertyName());
3626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Object> name = expr->key()->AsLiteral()->handle();
36278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
36281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
36298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HLoadNamedGeneric(context, obj, name);
3630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj,
3634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            Property* expr,
3635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            Handle<Map> map,
3636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            Handle<String> name) {
3637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LookupResult lookup;
3638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  map->LookupInDescriptors(NULL, *name, &lookup);
3639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup.IsProperty() && lookup.type() == FIELD) {
3640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return BuildLoadNamedField(obj,
3641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               expr,
3642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               map,
3643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               &lookup,
3644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               true);
3645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
36468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(obj));
36478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckMap(obj, map));
3648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map));
36498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return new(zone()) HConstant(function, Representation::Tagged());
3650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return BuildLoadNamedGeneric(obj, expr);
3652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
3657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   HValue* key) {
36588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
36591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
36608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HLoadKeyedGeneric(context, object, key);
3661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object,
3665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                       HValue* key,
3666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                       Property* expr) {
3667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic());
36688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckNonSmi(object));
3669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Map> map = expr->GetMonomorphicReceiverType();
3670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(map->has_fast_elements());
36718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckMap(object, map));
36729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
36738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HLoadElements* elements = new(zone()) HLoadElements(object);
36749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  HInstruction* length = NULL;
36759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (is_array) {
36768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    length = AddInstruction(new(zone()) HJSArrayLength(object));
36778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HBoundsCheck(key, length));
36789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    AddInstruction(elements);
36799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
36809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    AddInstruction(elements);
36818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    length = AddInstruction(new(zone()) HFixedArrayLength(elements));
36828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HBoundsCheck(key, length));
36839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
36848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HLoadKeyedFastElement(elements, key);
3685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
368844f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHInstruction* HGraphBuilder::BuildLoadKeyedSpecializedArrayElement(
368944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* object,
369044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* key,
369144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Property* expr) {
36921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic());
36938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckNonSmi(object));
36941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Handle<Map> map = expr->GetMonomorphicReceiverType();
36951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(!map->has_fast_elements());
369644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(map->has_external_array_elements());
36978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckMap(object, map));
36988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HLoadElements* elements = new(zone()) HLoadElements(object);
36991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(elements);
37008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* length = new(zone()) HExternalArrayLength(elements);
3701e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  AddInstruction(length);
37028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HBoundsCheck(key, length));
370344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HLoadExternalArrayPointer* external_elements =
37048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HLoadExternalArrayPointer(elements);
37051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(external_elements);
370644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HLoadKeyedSpecializedArrayElement* pixel_array_value =
37078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HLoadKeyedSpecializedArrayElement(
37088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          external_elements, key, expr->external_array_type());
37091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return pixel_array_value;
37101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
37111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37138b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochHInstruction* HGraphBuilder::BuildLoadKeyed(HValue* obj,
37148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                            HValue* key,
37158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                            Property* prop) {
37168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (prop->IsMonomorphic()) {
37178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Handle<Map> receiver_type(prop->GetMonomorphicReceiverType());
37188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // An object has either fast elements or pixel array elements, but never
37198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // both. Pixel array maps that are assigned to pixel array elements are
37208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // always created with the fast elements flag cleared.
37218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (receiver_type->has_external_array_elements()) {
37228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return BuildLoadKeyedSpecializedArrayElement(obj, key, prop);
37238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else if (receiver_type->has_fast_elements()) {
37248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return BuildLoadKeyedFastElement(obj, key, prop);
37258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
37268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
37278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return BuildLoadKeyedGeneric(obj, key);
37288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
37298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
37308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
3731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
3732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    HValue* key,
3733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    HValue* value) {
37348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
37351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
37368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HStoreKeyedGeneric(
37378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         context,
37388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         object,
37398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         key,
37408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         value,
37418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         function_strict_mode());
3742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object,
3746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                        HValue* key,
3747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                        HValue* val,
3748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                        Expression* expr) {
3749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(expr->IsMonomorphic());
37508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckNonSmi(object));
3751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Map> map = expr->GetMonomorphicReceiverType();
3752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(map->has_fast_elements());
37538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckMap(object, map));
37548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
37558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckMap(
37568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      elements, isolate()->factory()->fixed_array_map()));
3757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
3758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* length = NULL;
3759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (is_array) {
37608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    length = AddInstruction(new(zone()) HJSArrayLength(object));
3761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
37628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    length = AddInstruction(new(zone()) HFixedArrayLength(elements));
3763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
37648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HBoundsCheck(key, length));
37658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HStoreKeyedFastElement(elements, key, val);
3766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
376944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHInstruction* HGraphBuilder::BuildStoreKeyedSpecializedArrayElement(
3770e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HValue* object,
3771e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HValue* key,
3772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HValue* val,
37738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Expression* expr) {
3774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(expr->IsMonomorphic());
37758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckNonSmi(object));
3776e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<Map> map = expr->GetMonomorphicReceiverType();
3777e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!map->has_fast_elements());
377844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(map->has_external_array_elements());
37798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckMap(object, map));
37808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HLoadElements* elements = new(zone()) HLoadElements(object);
3781e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  AddInstruction(elements);
37828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* length = AddInstruction(
37838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HExternalArrayLength(elements));
37848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HBoundsCheck(key, length));
378544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HLoadExternalArrayPointer* external_elements =
37868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HLoadExternalArrayPointer(elements);
3787e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  AddInstruction(external_elements);
37888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HStoreKeyedSpecializedArrayElement(
378944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      external_elements,
379044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      key,
379144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      val,
37928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      expr->external_array_type());
37938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
37948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
37958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
37968b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochHInstruction* HGraphBuilder::BuildStoreKeyed(HValue* object,
37978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                             HValue* key,
37988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                             HValue* value,
37998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                             Expression* expr) {
38008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (expr->IsMonomorphic()) {
38018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Handle<Map> receiver_type(expr->GetMonomorphicReceiverType());
38028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // An object has either fast elements or external array elements, but
38038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // never both. Pixel array maps that are assigned to pixel array elements
38048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // are always created with the fast elements flag cleared.
38058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (receiver_type->has_external_array_elements()) {
38068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return BuildStoreKeyedSpecializedArrayElement(object,
38078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                    key,
38088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                    value,
38098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                    expr);
38108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else if (receiver_type->has_fast_elements()) {
38118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return BuildStoreKeyedFastElement(object, key, value, expr);
38128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
38138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
38148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return BuildStoreKeyedGeneric(object, key, value);
3815e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
3816e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3817e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryArgumentsAccess(Property* expr) {
3819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = expr->obj()->AsVariableProxy();
3820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (proxy == NULL) return false;
3821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!proxy->var()->IsStackAllocated()) return false;
3822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
3823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
3824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* result = NULL;
3827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->key()->IsPropertyName()) {
3828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
3829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!name->IsEqualTo(CStrVector("length"))) return false;
38308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
38318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    result = new(zone()) HArgumentsLength(elements);
3832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3833e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Push(graph()->GetArgumentsObject());
3834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitForValue(expr->key());
38358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (HasStackOverflow() || current_block() == NULL) return true;
3836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* key = Pop();
3837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Drop(1);  // Arguments object.
38388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
38398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* length = AddInstruction(
38408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        new(zone()) HArgumentsLength(elements));
38418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HBoundsCheck(key, length));
38428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    result = new(zone()) HAccessArgumentsAt(elements, length, key);
3843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, expr->id());
3845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
3846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitProperty(Property* expr) {
38508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
38518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
38528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->RecordTypeFeedback(oracle());
3854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (TryArgumentsAccess(expr)) return;
3856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
38578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->obj()));
3858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = NULL;
3860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->IsArrayLength()) {
3861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* array = Pop();
38628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(array));
38638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckInstanceType(array,
38648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                  JS_ARRAY_TYPE,
38658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                  JS_ARRAY_TYPE));
38668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr = new(zone()) HJSArrayLength(array);
38679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
38681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else if (expr->IsStringLength()) {
38691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    HValue* string = Pop();
38708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(string));
38718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckInstanceType(string,
38728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                  FIRST_STRING_TYPE,
38738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                  LAST_STRING_TYPE));
38748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr = new(zone()) HStringLength(string);
387544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (expr->IsStringAccess()) {
38768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->key()));
387744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* index = Pop();
387844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* string = Pop();
387944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
388044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AddInstruction(char_code);
38818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr = new(zone()) HStringCharFromCode(char_code);
38821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
38839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else if (expr->IsFunctionPrototype()) {
38849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    HValue* function = Pop();
38858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(function));
38868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr = new(zone()) HLoadFunctionPrototype(function);
3887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (expr->key()->IsPropertyName()) {
3889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
3890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ZoneMapList* types = expr->GetReceiverTypes();
3891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* obj = Pop();
3893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (expr->IsMonomorphic()) {
3894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = BuildLoadNamed(obj, expr, types->first(), name);
3895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (types != NULL && types->length() > 1) {
38968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      AddInstruction(new(zone()) HCheckNonSmi(obj));
38978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      instr = new(zone()) HLoadNamedFieldPolymorphic(obj, types, name);
3898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
3899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = BuildLoadNamedGeneric(obj, expr);
3900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
39038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->key()));
3904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* key = Pop();
3906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* obj = Pop();
39078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr = BuildLoadKeyed(obj, key, expr);
3908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(expr->position());
3910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(instr, expr->id());
3911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddCheckConstantFunction(Call* expr,
3915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             HValue* receiver,
3916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             Handle<Map> receiver_map,
3917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             bool smi_and_map_check) {
3918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Constant functions have the nice property that the map will change if they
3919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // are overwritten.  Therefore it is enough to check the map of the holder and
3920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // its prototypes.
3921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (smi_and_map_check) {
39228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(receiver));
39238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckMap(receiver, receiver_map));
3924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!expr->holder().is_null()) {
39268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckPrototypeMaps(
3927b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        Handle<JSObject>(JSObject::cast(receiver_map->prototype())),
3928b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        expr->holder()));
3929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
3934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                               HValue* receiver,
3935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                               ZoneMapList* types,
3936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                               Handle<String> name) {
3937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(ager): We should recognize when the prototype chains for different
3938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // maps are identical. In that case we can avoid repeatedly generating the
3939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // same prototype map checks.
394044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int argument_count = expr->arguments()->length() + 1;  // Includes receiver.
394144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int count = 0;
394244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* join = NULL;
394344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < types->length() && count < kMaxCallPolymorphism; ++i) {
3944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Map> map = types->at(i);
3945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (expr->ComputeTarget(map, name)) {
394644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (count == 0) {
39478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        // Only needed once.
39488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckNonSmi(receiver));
394944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        join = graph()->CreateBasicBlock();
395044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
395144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ++count;
395244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HBasicBlock* if_true = graph()->CreateBasicBlock();
395344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HBasicBlock* if_false = graph()->CreateBasicBlock();
39548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HCompareMap* compare =
39558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          new(zone()) HCompareMap(receiver, map, if_true, if_false);
395644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      current_block()->Finish(compare);
395744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
395844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      set_current_block(if_true);
3959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddCheckConstantFunction(expr, receiver, map, false);
3960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
3961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF("Trying to inline the polymorphic call to %s\n",
3962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               *name->ToCString());
3963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
39648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (FLAG_polymorphic_inlining && TryInline(expr)) {
39658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        // Trying to inline will signal that we should bailout from the
39668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        // entire compilation by setting stack overflow on the visitor.
39678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        if (HasStackOverflow()) return;
39688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      } else {
3969e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        HCallConstantFunction* call =
39708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) HCallConstantFunction(expr->target(), argument_count);
3971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        call->set_position(expr->position());
39721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        PreProcessCall(call);
397344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        AddInstruction(call);
397444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (!ast_context()->IsEffect()) Push(call);
3975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
397644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
397744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (current_block() != NULL) current_block()->Goto(join);
397844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      set_current_block(if_false);
3979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
398244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Finish up.  Unconditionally deoptimize if we've handled all the maps we
398344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // know about and do not want to handle ones we've never seen.  Otherwise
398444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // use a generic IC.
398544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
398644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    current_block()->FinishExitWithDeoptimization();
398744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
39888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HContext* context = new(zone()) HContext;
39891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    AddInstruction(context);
39908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count);
3991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    call->set_position(expr->position());
39921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    PreProcessCall(call);
3993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
399444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (join != NULL) {
399544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      AddInstruction(call);
399644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (!ast_context()->IsEffect()) Push(call);
399744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      current_block()->Goto(join);
399844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
399944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ast_context()->ReturnInstruction(call, expr->id());
400044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return;
40019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
4002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
400344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
400444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // We assume that control flow is always live after an expression.  So
400544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // even without predecessors to the join block, we set it as the exit
400644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // block and continue by adding instructions there.
400744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(join != NULL);
400844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (join->HasPredecessor()) {
40098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    set_current_block(join);
401044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    join->SetJoinId(expr->id());
401144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
40128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
40138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    set_current_block(NULL);
401444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
4015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4018e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::TraceInline(Handle<JSFunction> target, const char* reason) {
4019e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (FLAG_trace_inlining) {
4020e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (reason == NULL) {
40218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // We are currently in the context of inlined function thus we have
40228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // to go to an outer FunctionState to get caller.
40238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      SmartPointer<char> callee = target->shared()->DebugName()->ToCString();
40248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      SmartPointer<char> caller =
40258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          function_state()->outer()->compilation_info()->function()->
40268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch              debug_name()->ToCString();
4027e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      PrintF("Inlined %s called from %s.\n", *callee, *caller);
4028e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
40298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      SmartPointer<char> callee = target->shared()->DebugName()->ToCString();
40308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      SmartPointer<char> caller =
40318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          info()->function()->debug_name()->ToCString();
4032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      PrintF("Did not inline %s called from %s (%s).\n",
4033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch             *callee, *caller, reason);
4034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
4035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryInline(Call* expr) {
4040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!FLAG_use_inlining) return false;
4041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Precondition: call is monomorphic and we have found a target with the
4043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // appropriate arity.
4044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<JSFunction> target = expr->target();
4045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Do a quick check on source code length to avoid parsing large
4047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // inlining candidates.
4048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) {
4049e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    TraceInline(target, "target text too big");
4050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
4051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Target must be inlineable.
4054e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!target->IsInlineable()) {
4055e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    TraceInline(target, "target not inlineable");
4056e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return false;
4057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
4058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // No context change required.
4060e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompilationInfo* outer_info = info();
4061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (target->context() != outer_info->closure()->context() ||
4062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_info->scope()->contains_with() ||
4063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_info->scope()->num_heap_slots() > 0) {
4064e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    TraceInline(target, "target requires context change");
4065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
4066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
40688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Don't inline deeper than kMaxInliningLevels calls.
4069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* env = environment();
40708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int current_level = 1;
40718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  while (env->outer() != NULL) {
40728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (current_level == Compiler::kMaxInliningLevels) {
40738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      TraceInline(target, "inline depth limit reached");
40748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return false;
40758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
40768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    current_level++;
40778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    env = env->outer();
4078e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
4079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Don't inline recursive functions.
4081e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (target->shared() == outer_info->closure()->shared()) {
4082e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    TraceInline(target, "target is recursive");
4083e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return false;
4084e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
4085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We don't want to add more than a certain number of nodes from inlining.
4087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) {
4088e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    TraceInline(target, "cumulative AST node limit reached");
4089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
4090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int count_before = AstNode::Count();
4093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Parse and allocate variables.
4095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompilationInfo target_info(target);
4096e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!ParserApi::Parse(&target_info) ||
4097e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      !Scope::Analyze(&target_info)) {
409844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (target_info.isolate()->has_pending_exception()) {
4099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Parse or scope error, never optimize this function.
41001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      SetStackOverflow();
4101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      target->shared()->set_optimization_disabled(true);
41021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
4103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    TraceInline(target, "parse failure");
4104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return false;
4105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
4106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (target_info.scope()->num_heap_slots() > 0) {
4108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    TraceInline(target, "target has context-allocated variables");
4109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
4110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  FunctionLiteral* function = target_info.function();
4112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Count the number of AST nodes added by inlining this call.
4114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int nodes_added = AstNode::Count() - count_before;
4115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) {
4116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    TraceInline(target, "target AST is too large");
4117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
4118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check if we can handle all declarations in the inlined functions.
4121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  VisitDeclarations(target_info.scope()->declarations());
4122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (HasStackOverflow()) {
4123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    TraceInline(target, "target has non-trivial declaration");
4124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ClearStackOverflow();
4125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
4126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Don't inline functions that uses the arguments object or that
4129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // have a mismatching number of parameters.
4130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<SharedFunctionInfo> target_shared(target->shared());
4131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int arity = expr->arguments()->length();
4132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (function->scope()->arguments() != NULL ||
4133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      arity != target_shared->formal_parameter_count()) {
4134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    TraceInline(target, "target requires special argument handling");
4135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
4136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // All statements in the body must be inlineable.
4139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0, count = function->body()->length(); i < count; ++i) {
4140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (!function->body()->at(i)->IsInlineable()) {
4141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      TraceInline(target, "target contains unsupported syntax");
4142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      return false;
4143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
4144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Generate the deoptimization data for the unoptimized version of
4147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the target function if we don't already have it.
4148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!target_shared->has_deoptimization_support()) {
4149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Note that we compile here using the same AST that we will use for
4150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // generating the optimized inline code.
4151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    target_info.EnableDeoptimizationSupport();
4152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (!FullCodeGenerator::MakeCode(&target_info)) {
4153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      TraceInline(target, "could not generate deoptimization info");
4154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      return false;
4155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
4156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    target_shared->EnableDeoptimizationSupport(*target_info.code());
4157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG,
4158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                        &target_info,
4159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                        target_shared);
4160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // ----------------------------------------------------------------
4163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Save the pending call context and type feedback oracle. Set up new ones
4164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // for the inlined function.
4165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(target_shared->has_deoptimization_support());
4166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  TypeFeedbackOracle target_oracle(
4167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Handle<Code>(target_shared->code()),
4168b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      Handle<Context>(target->context()->global_context()));
4169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  FunctionState target_state(this, &target_info, &target_oracle);
4170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
417144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HConstant* undefined = graph()->GetConstantUndefined();
417244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEnvironment* inner_env =
417344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      environment()->CopyForInlining(target, function, true, undefined);
417444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* body_entry = CreateBasicBlock(inner_env);
417544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  current_block()->Goto(body_entry);
417644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
417744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  body_entry->SetJoinId(expr->ReturnId());
417844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  set_current_block(body_entry);
41798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HEnterInlined(target, function));
418044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  VisitStatements(function->body());
4181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (HasStackOverflow()) {
4182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Bail out if the inline function did, as we cannot residualize a call
4183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // instead.
4184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    TraceInline(target, "inline graph construction failed");
41858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return true;
4186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Update inlined nodes count.
4189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  inlined_count_ += nodes_added;
4190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  TraceInline(target, NULL);
4192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
419344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (current_block() != NULL) {
4194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Add a return of undefined if control can fall off the body.  In a
4195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // test context, undefined is false.
4196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (inlined_test_context() == NULL) {
4197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(function_return() != NULL);
419844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(call_context()->IsEffect() || call_context()->IsValue());
419944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (call_context()->IsEffect()) {
420044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        current_block()->Goto(function_return(), false);
420144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else {
420244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        current_block()->AddLeaveInlined(undefined, function_return());
420344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
4204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
4205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // The graph builder assumes control can reach both branches of a
4206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // test, so we materialize the undefined value and test it rather than
4207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // simply jumping to the false target.
4208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      //
4209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // TODO(3168478): refactor to avoid this.
4210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* empty_true = graph()->CreateBasicBlock();
4211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* empty_false = graph()->CreateBasicBlock();
42128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HTest* test = new(zone()) HTest(undefined, empty_true, empty_false);
421344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      current_block()->Finish(test);
421444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
421544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      empty_true->Goto(inlined_test_context()->if_true(), false);
421644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      empty_false->Goto(inlined_test_context()->if_false(), false);
4217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Fix up the function exits.
4221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (inlined_test_context() != NULL) {
4222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* if_true = inlined_test_context()->if_true();
4223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* if_false = inlined_test_context()->if_false();
4224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if_true->SetJoinId(expr->id());
4225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if_false->SetJoinId(expr->id());
4226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(ast_context() == inlined_test_context());
4227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Pop the return test context from the expression context stack.
4228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ClearInlinedTestContext();
4229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Forward to the real test context.
4231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
423344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if_true->Goto(true_target, false);
423444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if_false->Goto(false_target, false);
4235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // TODO(kmillikin): Come up with a better way to handle this. It is too
4237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // subtle. NULL here indicates that the enclosing context has no control
4238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // flow to handle.
4239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(NULL);
4240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
42418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else if (function_return()->HasPredecessor()) {
4242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    function_return()->SetJoinId(expr->id());
4243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(function_return());
42448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
42458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    set_current_block(NULL);
4246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
4249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
42521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockbool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
42531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                             HValue* receiver,
42541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                             Handle<Map> receiver_map,
42551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                             CheckType check_type) {
42561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null());
4257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Try to inline calls like Math.* as operations in the calling function.
42581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
4259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
4260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
4261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (id) {
42621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case kStringCharCodeAt:
426344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    case kStringCharAt:
42641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (argument_count == 2 && check_type == STRING_CHECK) {
42651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        HValue* index = Pop();
42661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        HValue* string = Pop();
42671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ASSERT(!expr->holder().is_null());
42688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckPrototypeMaps(
42691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK),
42701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            expr->holder()));
427144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
427244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (id == kStringCharCodeAt) {
427344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ast_context()->ReturnInstruction(char_code, expr->id());
427444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          return true;
427544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
427644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        AddInstruction(char_code);
42778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        HStringCharFromCode* result =
42788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) HStringCharFromCode(char_code);
42791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ast_context()->ReturnInstruction(result, expr->id());
42801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        return true;
42811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
42821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
4283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathRound:
4284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathFloor:
4285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathAbs:
4286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathSqrt:
4287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathLog:
4288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathSin:
4289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathCos:
42901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
42911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AddCheckConstantFunction(expr, receiver, receiver_map, true);
4292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* argument = Pop();
4293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Drop(1);  // Receiver.
42948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        HUnaryMathOperation* op = new(zone()) HUnaryMathOperation(argument, id);
4295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        op->set_position(expr->position());
4296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ast_context()->ReturnInstruction(op, expr->id());
4297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return true;
4298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
4299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathPow:
43011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
43021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AddCheckConstantFunction(expr, receiver, receiver_map, true);
4303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* right = Pop();
4304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* left = Pop();
4305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Pop();  // Pop receiver.
4306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HInstruction* result = NULL;
4307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Use sqrt() if exponent is 0.5 or -0.5.
4308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
4309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          double exponent = HConstant::cast(right)->DoubleValue();
4310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (exponent == 0.5) {
43118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            result = new(zone()) HUnaryMathOperation(left, kMathPowHalf);
4312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (exponent == -0.5) {
4313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HConstant* double_one =
43148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                new(zone()) HConstant(Handle<Object>(Smi::FromInt(1)),
43158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                      Representation::Double());
4316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AddInstruction(double_one);
4317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HUnaryMathOperation* square_root =
43188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                new(zone()) HUnaryMathOperation(left, kMathPowHalf);
4319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AddInstruction(square_root);
4320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // MathPowHalf doesn't have side effects so there's no need for
4321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // an environment simulation here.
4322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            ASSERT(!square_root->HasSideEffects());
43238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            result = new(zone()) HDiv(double_one, square_root);
4324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (exponent == 2.0) {
43258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            result = new(zone()) HMul(left, left);
4326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
4327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else if (right->IsConstant() &&
43281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                   HConstant::cast(right)->HasInteger32Value() &&
43291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                   HConstant::cast(right)->Integer32Value() == 2) {
43308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          result = new(zone()) HMul(left, left);
4331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
4332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
43331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if (result == NULL) {
43348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          result = new(zone()) HPower(left, right);
43351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        }
4336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ast_context()->ReturnInstruction(result, expr->id());
4337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return true;
4338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
4339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    default:
4341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Not yet supported for inlining.
4342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return false;
4345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryCallApply(Call* expr) {
4349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Expression* callee = expr->expression();
4350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = callee->AsProperty();
4351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(prop != NULL);
4352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4353e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (info()->scope()->arguments() == NULL) return false;
4354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!name->IsEqualTo(CStrVector("apply"))) return false;
4357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
4359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (args->length() != 2) return false;
4360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* arg_two = args->at(1)->AsVariableProxy();
4362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
4363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* arg_two_value = environment()->Lookup(arg_two->var());
4364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
4365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4366b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (!expr->IsMonomorphic() ||
4367b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      expr->check_type() != RECEIVER_MAP_CHECK) return false;
4368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Found pattern f.apply(receiver, arguments).
4370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForValue(prop->obj());
43718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (HasStackOverflow() || current_block() == NULL) return true;
4372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* function = Pop();
4373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForValue(args->at(0));
43748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (HasStackOverflow() || current_block() == NULL) return true;
4375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* receiver = Pop();
43768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
43778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements));
4378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddCheckConstantFunction(expr,
4379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           function,
4380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           expr->GetReceiverTypes()->first(),
4381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           true);
4382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* result =
43838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HApplyArguments(function, receiver, length, elements);
4384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->set_position(expr->position());
4385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, expr->id());
4386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
4387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCall(Call* expr) {
43918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
43928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
43938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
4394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Expression* callee = expr->expression();
4395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
4396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HInstruction* call = NULL;
4397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = callee->AsProperty();
4399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (prop != NULL) {
4400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!prop->key()->IsPropertyName()) {
4401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Keyed function call.
44028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->obj()));
4403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
44048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->key()));
4405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Push receiver and key like the non-optimized code generator expects it.
4406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* key = Pop();
4407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* receiver = Pop();
4408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(key);
4409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(receiver);
4410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
44118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitExpressions(expr->arguments()));
4412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
44138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HContext* context = new(zone()) HContext;
44141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      AddInstruction(context);
44158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      call = PreProcessCall(
44168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          new(zone()) HCallKeyed(context, key, argument_count));
4417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      call->set_position(expr->position());
4418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(1);  // Key.
4419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnInstruction(call, expr->id());
4420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
4421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Named function call.
4424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    expr->RecordTypeFeedback(oracle());
4425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (TryCallApply(expr)) return;
4427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
44288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(prop->obj()));
44298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitExpressions(expr->arguments()));
4430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    expr->RecordTypeFeedback(oracle());
4434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ZoneMapList* types = expr->GetReceiverTypes();
4435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
44361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    HValue* receiver =
44371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        environment()->ExpressionStackAt(expr->arguments()->length());
44381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (expr->IsMonomorphic()) {
44391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Handle<Map> receiver_map =
44401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          (types == NULL) ? Handle<Map>::null() : types->first();
44411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (TryInlineBuiltinFunction(expr,
44421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                   receiver,
44431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                   receiver_map,
44441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                   expr->check_type())) {
4445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return;
4446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
4447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
444844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) ||
44491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          expr->check_type() != RECEIVER_MAP_CHECK) {
44501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // When the target has a custom call IC generator, use the IC,
445144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // because it is likely to generate better code.  Also use the IC
445244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // when a primitive receiver check is required.
44538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        HContext* context = new(zone()) HContext;
44541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AddInstruction(context);
44558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        call = PreProcessCall(
44568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) HCallNamed(context, name, argument_count));
44571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
44581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AddCheckConstantFunction(expr, receiver, receiver_map, true);
44591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
44608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        if (TryInline(expr)) return;
44618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        call = PreProcessCall(
44628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) HCallConstantFunction(expr->target(),
44638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                              argument_count));
44641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
4465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (types != NULL && types->length() > 1) {
4466b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
4467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandlePolymorphicCallNamed(expr, receiver, types, name);
4468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
4469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
44718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HContext* context = new(zone()) HContext;
44721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      AddInstruction(context);
44738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      call = PreProcessCall(
44748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          new(zone()) HCallNamed(context, name, argument_count));
4475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool global_call = (var != NULL) && var->is_global() && !var->is_this();
4480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!global_call) {
4482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ++argument_count;
44838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(expr->expression()));
4484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (global_call) {
4487e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      bool known_global_function = false;
4488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // If there is a global property cell for the name at compile time and
4489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // access check is not enabled we assume that the function will not change
4490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // and generate optimized code for calling the function.
44918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      LookupResult lookup;
44928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
44938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (type == kUseCell &&
4494e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          !info()->global_object()->IsAccessCheckNeeded()) {
4495e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        Handle<GlobalObject> global(info()->global_object());
44968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        known_global_function = expr->ComputeGlobalTarget(global, &lookup);
4497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
4498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (known_global_function) {
4499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Push the global object instead of the global receiver because
4500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // code generated by the full code generator expects it.
45018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        HContext* context = new(zone()) HContext;
45028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        HGlobalObject* global_object = new(zone()) HGlobalObject(context);
45031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AddInstruction(context);
45041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        PushAndAdd(global_object);
45058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        CHECK_ALIVE(VisitExpressions(expr->arguments()));
4506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
45078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        CHECK_ALIVE(VisitForValue(expr->expression()));
4508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* function = Pop();
45098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckFunction(function, expr->target()));
4510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Replace the global object with the global receiver.
45128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        HGlobalReceiver* global_receiver =
45138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) HGlobalReceiver(global_object);
4514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Index of the receiver from the top of the expression stack.
4515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        const int receiver_index = argument_count - 1;
4516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        AddInstruction(global_receiver);
4517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(environment()->ExpressionStackAt(receiver_index)->
4518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               IsGlobalObject());
4519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        environment()->SetExpressionStackAt(receiver_index, global_receiver);
4520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
45218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        if (TryInline(expr)) return;
45228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
45238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                           argument_count));
4524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
45258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        HContext* context = new(zone()) HContext;
45261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AddInstruction(context);
45278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        PushAndAdd(new(zone()) HGlobalObject(context));
45288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        CHECK_ALIVE(VisitExpressions(expr->arguments()));
4529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
45308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        call = PreProcessCall(new(zone()) HCallGlobal(context,
4531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              var->name(),
4532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              argument_count));
4533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
4534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
45368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HContext* context = new(zone()) HContext;
45378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HGlobalObject* global_object = new(zone()) HGlobalObject(context);
45381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      AddInstruction(context);
45391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      AddInstruction(global_object);
45408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      PushAndAdd(new(zone()) HGlobalReceiver(global_object));
45418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitExpressions(expr->arguments()));
4542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
45438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      call = PreProcessCall(new(zone()) HCallFunction(context, argument_count));
4544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  call->set_position(expr->position());
4548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(call, expr->id());
4549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallNew(CallNew* expr) {
45538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
45548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
45558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
4556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The constructor function is also used as the receiver argument to the
4557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // JS construct call builtin.
45588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->expression()));
45598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitExpressions(expr->arguments()));
4560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
45618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
45621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
45631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
45641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The constructor is both an operand to the instruction and an argument
45651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // to the construct call.
45661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int arg_count = expr->arguments()->length() + 1;  // Plus constructor.
45671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  HValue* constructor = environment()->ExpressionStackAt(arg_count - 1);
45688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count);
4569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  call->set_position(expr->position());
45701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  PreProcessCall(call);
4571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(call, expr->id());
4572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for generating inlined runtime functions.
4576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Lookup table for generators for runtime calls that are  generated inline.
4578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Elements of the table are member pointers to functions of HGraphBuilder.
4579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize)  \
4580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    &HGraphBuilder::Generate##Name,
4581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst HGraphBuilder::InlineFunctionGenerator
4583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HGraphBuilder::kInlineFunctionGenerators[] = {
4584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
4585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
4586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
4587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef INLINE_FUNCTION_GENERATOR_ADDRESS
4588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
45918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
45928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
45938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
4594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->is_jsruntime()) {
45958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return Bailout("call to a JavaScript runtime function");
4596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
459844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Runtime::Function* function = expr->function();
4599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(function != NULL);
4600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (function->intrinsic_type == Runtime::INLINE) {
4601e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(expr->name()->length() > 0);
4602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(expr->name()->Get(0) == '_');
4603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Call to an inline function.
4604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int lookup_index = static_cast<int>(function->function_id) -
4605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        static_cast<int>(Runtime::kFirstInlineFunction);
4606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(lookup_index >= 0);
4607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(static_cast<size_t>(lookup_index) <
4608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           ARRAY_SIZE(kInlineFunctionGenerators));
4609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
4610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Call the inline code generator using the pointer-to-member.
4612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    (this->*generator)(expr);
4613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(function->intrinsic_type == Runtime::RUNTIME);
46158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitArgumentList(expr->arguments()));
4616e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Handle<String> name = expr->name();
4618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int argument_count = expr->arguments()->length();
46198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HCallRuntime* call =
46208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        new(zone()) HCallRuntime(name, function, argument_count);
4621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    call->set_position(RelocInfo::kNoPosition);
4622e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Drop(argument_count);
4623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnInstruction(call, expr->id());
4624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
46298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
46308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
46318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
4632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Token::Value op = expr->op();
4633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (op == Token::VOID) {
46348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForEffect(expr->expression()));
4635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnValue(graph()->GetConstantUndefined());
4636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::DELETE) {
4637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Property* prop = expr->expression()->AsProperty();
4638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (prop == NULL && var == NULL) {
4640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Result of deleting non-property, non-variable reference is true.
4641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Evaluate the subexpression for side effects.
46428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForEffect(expr->expression()));
4643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(graph()->GetConstantTrue());
4644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (var != NULL &&
4645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               !var->is_global() &&
4646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               var->AsSlot() != NULL &&
4647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               var->AsSlot()->type() != Slot::LOOKUP) {
4648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Result of deleting non-global, non-dynamic variables is false.
4649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // The subexpression does not have side effects.
4650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(graph()->GetConstantFalse());
4651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (prop != NULL) {
46521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (prop->is_synthetic()) {
46531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // Result of deleting parameters is false, even when they rewrite
46541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // to accesses on the arguments object.
46551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ast_context()->ReturnValue(graph()->GetConstantFalse());
46561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
46578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        CHECK_ALIVE(VisitForValue(prop->obj()));
46588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        CHECK_ALIVE(VisitForValue(prop->key()));
46591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        HValue* key = Pop();
46601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        HValue* obj = Pop();
46618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key);
46621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ast_context()->ReturnInstruction(instr, expr->id());
46631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
4664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (var->is_global()) {
46658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return Bailout("delete with global variable");
4666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
46678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return Bailout("delete with non-global variable");
4668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::NOT) {
4670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (ast_context()->IsTest()) {
4671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TestContext* context = TestContext::cast(ast_context());
4672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VisitForControl(expr->expression(),
4673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      context->if_false(),
4674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      context->if_true());
4675e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else if (ast_context()->IsValue()) {
4676e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* materialize_false = graph()->CreateBasicBlock();
4677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* materialize_true = graph()->CreateBasicBlock();
46788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_BAILOUT(VisitForControl(expr->expression(),
46798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                    materialize_false,
46808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                    materialize_true));
46818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
46828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (materialize_false->HasPredecessor()) {
46838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        materialize_false->SetJoinId(expr->expression()->id());
46848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        set_current_block(materialize_false);
46858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        Push(graph()->GetConstantFalse());
46868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      } else {
46878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        materialize_false = NULL;
46888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
4689e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
46908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (materialize_true->HasPredecessor()) {
46918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        materialize_true->SetJoinId(expr->expression()->id());
46928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        set_current_block(materialize_true);
46938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        Push(graph()->GetConstantTrue());
46948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      } else {
46958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        materialize_true = NULL;
46968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
4697e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4698e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* join =
4699e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          CreateJoin(materialize_false, materialize_true, expr->id());
4700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(join);
47018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (join != NULL) ast_context()->ReturnValue(Pop());
4702e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
4703e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(ast_context()->IsEffect());
4704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      VisitForEffect(expr->expression());
4705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4706e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
470744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (op == Token::TYPEOF) {
47088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForTypeOf(expr->expression()));
470944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* value = Pop();
47108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ast_context()->ReturnInstruction(new(zone()) HTypeof(value), expr->id());
471144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
471244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
47138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->expression()));
4714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = Pop();
4715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* instr = NULL;
4716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    switch (op) {
4717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case Token::BIT_NOT:
47188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        instr = new(zone()) HBitNot(value);
4719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        break;
4720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case Token::SUB:
47218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        instr = new(zone()) HMul(value, graph_->GetConstantMinus1());
472244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        break;
472344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      case Token::ADD:
47248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        instr = new(zone()) HMul(value, graph_->GetConstant1());
4725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        break;
4726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      default:
47278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        return Bailout("Value: unsupported unary operation");
4728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        break;
4729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnInstruction(instr, expr->id());
4731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildIncrement(HValue* value, bool increment) {
4736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HConstant* delta = increment
4737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ? graph_->GetConstant1()
4738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : graph_->GetConstantMinus1();
47398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* instr = new(zone()) HAdd(value, delta);
4740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AssumeRepresentation(instr,  Representation::Integer32());
4741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
4742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCountOperation(CountOperation* expr) {
47468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
47478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
47488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
47498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Expression* target = expr->expression();
4750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = target->AsVariableProxy();
4751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Variable* var = proxy->AsVariable();
4752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = target->AsProperty();
4753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(var == NULL || prop == NULL);
4754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool inc = expr->op() == Token::INC;
4755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (var != NULL) {
47578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(target));
4758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Match the full code generator stack by simulating an extra stack
4760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // element for postfix operations in a non-effect context.
4761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* before = has_extra ? Top() : Pop();
4763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* after = BuildIncrement(before, inc);
4764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(after);
4765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Push(after);
4766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (var->is_global()) {
4768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandleGlobalVariableAssignment(var,
4769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     after,
4770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     expr->position(),
4771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     expr->AssignmentId());
4772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else if (var->IsStackAllocated()) {
4773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Bind(var, after);
4774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else if (var->IsContextSlot()) {
4775e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HValue* context = BuildContextChainWalk(var);
4776e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      int index = var->AsSlot()->index();
47778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HStoreContextSlot* instr =
47788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          new(zone()) HStoreContextSlot(context, index, after);
4779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      AddInstruction(instr);
4780e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
4781e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
47828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return Bailout("lookup variable in count operation");
4783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Drop(has_extra ? 2 : 1);
4785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (prop != NULL) {
4788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    prop->RecordTypeFeedback(oracle());
4789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (prop->key()->IsPropertyName()) {
4791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Named property.
4792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Match the full code generator stack by simulating an extra stack
4794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // element for postfix operations in a non-effect context.
4795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (has_extra) Push(graph_->GetConstantUndefined());
4797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
47988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->obj()));
4799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = Top();
4800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* load = NULL;
4802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (prop->IsMonomorphic()) {
4803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<Map> map = prop->GetReceiverTypes()->first();
4805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamed(obj, prop, map, name);
4806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
4807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamedGeneric(obj, prop);
4808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
4809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(load);
48108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (load->HasSideEffects()) AddSimulate(expr->CountId());
4811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* before = Pop();
4813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // There is no deoptimization to after the increment, so we don't need
4814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // to simulate the expression stack after this instruction.
4815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* after = BuildIncrement(before, inc);
4816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(after);
4817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* store = BuildStoreNamed(obj, after, prop);
4819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(store);
4820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Overwrite the receiver in the bailout environment with the result
4822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // of the operation, and the placeholder with the original value if
4823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // necessary.
4824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      environment()->SetExpressionStackAt(0, after);
4825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (has_extra) environment()->SetExpressionStackAt(1, before);
4826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(has_extra ? 2 : 1);
4828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
4832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Keyed property.
4833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Match the full code generator stack by simulate an extra stack element
4835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // for postfix operations in a non-effect context.
4836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (has_extra) Push(graph_->GetConstantUndefined());
4838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
48398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->obj()));
48408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->key()));
4841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = environment()->ExpressionStackAt(1);
4842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* key = environment()->ExpressionStackAt(0);
4843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
48448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HInstruction* load = BuildLoadKeyed(obj, key, prop);
4845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(load);
48468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (load->HasSideEffects()) AddSimulate(expr->CountId());
4847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* before = Pop();
4849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // There is no deoptimization to after the increment, so we don't need
4850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // to simulate the expression stack after this instruction.
4851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* after = BuildIncrement(before, inc);
4852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(after);
4853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
48548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      expr->RecordTypeFeedback(oracle());
48558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HInstruction* store = BuildStoreKeyed(obj, key, after, expr);
4856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(store);
4857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Drop the key from the bailout environment.  Overwrite the receiver
4859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // with the result of the operation, and the placeholder with the
4860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // original value if necessary.
4861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(1);
4862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      environment()->SetExpressionStackAt(0, after);
4863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (has_extra) environment()->SetExpressionStackAt(1, before);
4864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(has_extra ? 2 : 1);
4866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
48718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return Bailout("invalid lhs in count operation");
4872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
48761e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockHStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string,
48771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                                        HValue* index) {
48788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckNonSmi(string));
48798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckInstanceType(
48801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      string, FIRST_STRING_TYPE, LAST_STRING_TYPE));
48818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HStringLength* length = new(zone()) HStringLength(string);
48821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(length);
48838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HBoundsCheck(index, length));
48848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HStringCharCodeAt(string, index);
48851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
48861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
48871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
4889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  HValue* left,
4890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  HValue* right) {
48918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  TypeInfo info = oracle()->BinaryType(expr);
4892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = NULL;
4893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (expr->op()) {
4894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::ADD:
48958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (info.IsString()) {
48968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckNonSmi(left));
48978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckInstanceType(
48988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            left, FIRST_STRING_TYPE, LAST_STRING_TYPE));
48998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckNonSmi(right));
49008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckInstanceType(
49018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            right, FIRST_STRING_TYPE, LAST_STRING_TYPE));
49028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        instr = new(zone()) HStringAdd(left, right);
49038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      } else {
49048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        instr = new(zone()) HAdd(left, right);
49058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
4906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::SUB:
49088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      instr = new(zone()) HSub(left, right);
4909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::MUL:
49118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      instr = new(zone()) HMul(left, right);
4912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::MOD:
49148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      instr = new(zone()) HMod(left, right);
4915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::DIV:
49178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      instr = new(zone()) HDiv(left, right);
4918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::BIT_XOR:
49208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      instr = new(zone()) HBitXor(left, right);
4921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::BIT_AND:
49238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      instr = new(zone()) HBitAnd(left, right);
4924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::BIT_OR:
49268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      instr = new(zone()) HBitOr(left, right);
4927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::SAR:
49298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      instr = new(zone()) HSar(left, right);
4930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::SHR:
49328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      instr = new(zone()) HShr(left, right);
4933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::SHL:
49358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      instr = new(zone()) HShl(left, right);
4936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    default:
4938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNREACHABLE();
4939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If we hit an uninitialized binary op stub we will get type info
4941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // for a smi operation. If one of the operands is a constant string
4942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // do not generate code assuming it is a smi operation.
4943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsSmi() &&
4944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) ||
4945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch       (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) {
4946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return instr;
4947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_representation) {
4949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("Info: %s/%s\n", info.ToString(), ToRepresentation(info).Mnemonic());
4950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
49511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Representation rep = ToRepresentation(info);
49521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We only generate either int32 or generic tagged bitwise operations.
49531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) {
49541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    rep = Representation::Integer32();
49551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
49561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AssumeRepresentation(instr, rep);
4957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
4958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check for the form (%_ClassOf(foo) === 'BarClass').
4962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool IsClassOfTest(CompareOperation* expr) {
4963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->op() != Token::EQ_STRICT) return false;
4964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CallRuntime* call = expr->left()->AsCallRuntime();
4965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (call == NULL) return false;
4966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Literal* literal = expr->right()->AsLiteral();
4967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (literal == NULL) return false;
4968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!literal->handle()->IsString()) return false;
4969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false;
4970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(call->arguments()->length() == 1);
4971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
4972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
49768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
49778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
49788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
4979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->op() == Token::COMMA) {
49808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForEffect(expr->left()));
4981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Visit the right subexpression in the same AST context as the entire
4982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // expression.
4983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Visit(expr->right());
4984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (expr->op() == Token::AND || expr->op() == Token::OR) {
4986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool is_logical_and = (expr->op() == Token::AND);
4987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (ast_context()->IsTest()) {
4988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TestContext* context = TestContext::cast(ast_context());
4989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Translate left subexpression.
4990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* eval_right = graph()->CreateBasicBlock();
4991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (is_logical_and) {
49928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        CHECK_BAILOUT(VisitForControl(expr->left(),
49938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                      eval_right,
49948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                      context->if_false()));
4995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
49968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        CHECK_BAILOUT(VisitForControl(expr->left(),
49978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                      context->if_true(),
49988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                      eval_right));
4999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Translate right subexpression by visiting it in the same AST
5002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // context as the entire expression.
50038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (eval_right->HasPredecessor()) {
50048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        eval_right->SetJoinId(expr->RightId());
50058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        set_current_block(eval_right);
50068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        Visit(expr->right());
50078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
5008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5009e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else if (ast_context()->IsValue()) {
50108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_ALIVE(VisitForValue(expr->left()));
5011e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(current_block() != NULL);
5012e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
5013e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // We need an extra block to maintain edge-split form.
5014e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* empty_block = graph()->CreateBasicBlock();
5015e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* eval_right = graph()->CreateBasicBlock();
5016e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HTest* test = is_logical_and
50178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          ? new(zone()) HTest(Top(), eval_right, empty_block)
50188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          : new(zone()) HTest(Top(), empty_block, eval_right);
5019e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      current_block()->Finish(test);
5020e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
5021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(eval_right);
5022e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Drop(1);  // Value of the left subexpression.
50238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CHECK_BAILOUT(VisitForValue(expr->right()));
5024e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
5025e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* join_block =
5026e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          CreateJoin(empty_block, current_block(), expr->id());
5027e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(join_block);
5028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(Pop());
5029e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
5030e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
5031e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(ast_context()->IsEffect());
5032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // In an effect context, we don't need the value of the left
5033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // subexpression, only its control flow and side effects.  We need an
5034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // extra block to maintain edge-split form.
5035e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* empty_block = graph()->CreateBasicBlock();
5036e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* right_block = graph()->CreateBasicBlock();
5037e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (is_logical_and) {
50388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
5039e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
50408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
5041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
50428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
5043e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // TODO(kmillikin): Find a way to fix this.  It's ugly that there are
5044e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // actually two empty blocks (one here and one inserted by
5045e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // TestContext::BuildBranch, and that they both have an HSimulate
5046e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // though the second one is not a merge node, and that we really have
5047e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // no good AST ID to put on that first HSimulate.
50488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (empty_block->HasPredecessor()) {
50498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        empty_block->SetJoinId(expr->id());
50508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      } else {
50518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        empty_block = NULL;
50528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
50538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
50548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (right_block->HasPredecessor()) {
50558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        right_block->SetJoinId(expr->RightId());
50568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        set_current_block(right_block);
50578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        CHECK_BAILOUT(VisitForEffect(expr->right()));
50588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        right_block = current_block();
50598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      } else {
50608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        right_block = NULL;
50618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
50628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
50638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HBasicBlock* join_block =
50648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          CreateJoin(empty_block, right_block, expr->id());
5065e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(join_block);
5066e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // We did not materialize any value in the predecessor environments,
5067e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // so there is no need to handle it here.
5068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
50718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->left()));
50728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->right()));
5073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* right = Pop();
5075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* left = Pop();
5076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* instr = BuildBinaryOperation(expr, left, right);
5077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_position(expr->position());
5078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnInstruction(instr, expr->id());
5079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) {
5084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (value->CheckFlag(HValue::kFlexibleRepresentation)) {
5085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (FLAG_trace_representation) {
5086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintF("Assume representation for %s to be %s (%d)\n",
5087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             value->Mnemonic(),
5088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             r.Mnemonic(),
5089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             graph_->GetMaximumValueID());
5090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    value->ChangeRepresentation(r);
50921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // The representation of the value is dictated by type feedback and
50931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // will not be changed later.
5094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    value->ClearFlag(HValue::kFlexibleRepresentation);
5095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (FLAG_trace_representation) {
5096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("No representation assumed\n");
5097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochRepresentation HGraphBuilder::ToRepresentation(TypeInfo info) {
5102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsSmi()) return Representation::Integer32();
5103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsInteger32()) return Representation::Integer32();
5104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsDouble()) return Representation::Double();
5105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsNumber()) return Representation::Double();
5106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Representation::Tagged();
5107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
51118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
51128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
51138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
5114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (IsClassOfTest(expr)) {
5115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CallRuntime* call = expr->left()->AsCallRuntime();
51168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = Pop();
5118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Literal* literal = expr->right()->AsLiteral();
5119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> rhs = Handle<String>::cast(literal->handle());
51208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* instr = new(zone()) HClassOfTest(value, rhs);
5121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_position(expr->position());
5122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnInstruction(instr, expr->id());
5123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
5124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check for the pattern: typeof <expression> == <string literal>.
5127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UnaryOperation* left_unary = expr->left()->AsUnaryOperation();
5128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Literal* right_literal = expr->right()->AsLiteral();
5129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) &&
5130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      left_unary != NULL && left_unary->op() == Token::TYPEOF &&
5131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      right_literal != NULL && right_literal->handle()->IsString()) {
51328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitForTypeOf(left_unary->expression()));
5133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* left = Pop();
51348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* instr = new(zone()) HTypeofIs(left,
5135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<String>::cast(right_literal->handle()));
5136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_position(expr->position());
5137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnInstruction(instr, expr->id());
5138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
5139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
51418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->left()));
51428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->right()));
5143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* right = Pop();
5145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* left = Pop();
5146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Token::Value op = expr->op();
5147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  TypeInfo type_info = oracle()->CompareType(expr);
5149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = NULL;
5150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (op == Token::INSTANCEOF) {
5151086aeeaae12517475c22695a200be45495516549Ben Murdoch    // Check to see if the rhs of the instanceof is a global function not
5152086aeeaae12517475c22695a200be45495516549Ben Murdoch    // residing in new space. If it is we assume that the function will stay the
5153086aeeaae12517475c22695a200be45495516549Ben Murdoch    // same.
5154086aeeaae12517475c22695a200be45495516549Ben Murdoch    Handle<JSFunction> target = Handle<JSFunction>::null();
5155086aeeaae12517475c22695a200be45495516549Ben Murdoch    Variable* var = expr->right()->AsVariableProxy()->AsVariable();
5156086aeeaae12517475c22695a200be45495516549Ben Murdoch    bool global_function = (var != NULL) && var->is_global() && !var->is_this();
5157086aeeaae12517475c22695a200be45495516549Ben Murdoch    if (global_function &&
5158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        info()->has_global_object() &&
5159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        !info()->global_object()->IsAccessCheckNeeded()) {
5160086aeeaae12517475c22695a200be45495516549Ben Murdoch      Handle<String> name = var->name();
5161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Handle<GlobalObject> global(info()->global_object());
5162086aeeaae12517475c22695a200be45495516549Ben Murdoch      LookupResult lookup;
5163086aeeaae12517475c22695a200be45495516549Ben Murdoch      global->Lookup(*name, &lookup);
5164086aeeaae12517475c22695a200be45495516549Ben Murdoch      if (lookup.IsProperty() &&
5165086aeeaae12517475c22695a200be45495516549Ben Murdoch          lookup.type() == NORMAL &&
5166086aeeaae12517475c22695a200be45495516549Ben Murdoch          lookup.GetValue()->IsJSFunction()) {
5167086aeeaae12517475c22695a200be45495516549Ben Murdoch        Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
5168086aeeaae12517475c22695a200be45495516549Ben Murdoch        // If the function is in new space we assume it's more likely to
5169086aeeaae12517475c22695a200be45495516549Ben Murdoch        // change and thus prefer the general IC code.
517044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (!isolate()->heap()->InNewSpace(*candidate)) {
5171086aeeaae12517475c22695a200be45495516549Ben Murdoch          target = candidate;
5172086aeeaae12517475c22695a200be45495516549Ben Murdoch        }
5173086aeeaae12517475c22695a200be45495516549Ben Murdoch      }
5174086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
5175086aeeaae12517475c22695a200be45495516549Ben Murdoch
5176086aeeaae12517475c22695a200be45495516549Ben Murdoch    // If the target is not null we have found a known global function that is
5177086aeeaae12517475c22695a200be45495516549Ben Murdoch    // assumed to stay the same for this instanceof.
5178086aeeaae12517475c22695a200be45495516549Ben Murdoch    if (target.is_null()) {
51798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HContext* context = new(zone()) HContext;
51801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      AddInstruction(context);
51818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      instr = new(zone()) HInstanceOf(context, left, right);
5182086aeeaae12517475c22695a200be45495516549Ben Murdoch    } else {
51838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      AddInstruction(new(zone()) HCheckFunction(right, target));
51848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      instr = new(zone()) HInstanceOfKnownGlobal(left, target);
5185086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
5186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::IN) {
51878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return Bailout("Unsupported comparison: in");
5188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (type_info.IsNonPrimitive()) {
5189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    switch (op) {
5190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case Token::EQ:
5191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case Token::EQ_STRICT: {
51928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckNonSmi(left));
5193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left));
51948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckNonSmi(right));
5195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right));
51968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        instr = new(zone()) HCompareJSObjectEq(left, right);
5197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        break;
5198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      default:
52008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        return Bailout("Unsupported non-primitive compare");
5201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        break;
5202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
52048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HCompare* compare = new(zone()) HCompare(left, right, op);
5205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Representation r = ToRepresentation(type_info);
5206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    compare->SetInputRepresentation(r);
5207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = compare;
5208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(expr->position());
5210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(instr, expr->id());
5211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCompareToNull(CompareToNull* expr) {
52158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
52168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
52178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
52188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->expression()));
5219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
52218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HIsNull* compare = new(zone()) HIsNull(value, expr->is_strict());
5222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(compare, expr->id());
5223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
52278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!HasStackOverflow());
52288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block() != NULL);
52298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(current_block()->HasPredecessor());
52308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("ThisFunction");
5231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDeclaration(Declaration* decl) {
5235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We allow only declarations that do not require code generation.
5236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The following all require code generation: global variables and
5237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // functions, variables with slot type LOOKUP, declarations with
5238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // mode CONST, and functions.
5239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Variable* var = decl->proxy()->var();
5240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Slot* slot = var->AsSlot();
5241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (var->is_global() ||
5242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      (slot != NULL && slot->type() == Slot::LOOKUP) ||
5243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      decl->mode() == Variable::CONST ||
5244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      decl->fun() != NULL) {
52458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return Bailout("unsupported declaration");
5246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Generators for inline runtime functions.
5251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for types.
5252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsSmi(CallRuntime* call) {
5253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
52548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
52568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HIsSmi* result = new(zone()) HIsSmi(value);
5257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
5262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
52638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
5265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HHasInstanceType* result =
52668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE);
5267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsFunction(CallRuntime* call) {
5272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
52738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
52758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HHasInstanceType* result =
52768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HHasInstanceType(value, JS_FUNCTION_TYPE);
5277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
5282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
52838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
52858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HHasCachedArrayIndex* result = new(zone()) HHasCachedArrayIndex(value);
5286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsArray(CallRuntime* call) {
5291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
52928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
52948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HHasInstanceType* result = new(zone()) HHasInstanceType(value, JS_ARRAY_TYPE);
5295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
5300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
53018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
53038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HHasInstanceType* result =
53048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HHasInstanceType(value, JS_REGEXP_TYPE);
5305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsObject(CallRuntime* call) {
5310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
53118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
53138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HIsObject* test = new(zone()) HIsObject(value);
5314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(test, call->id());
5315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
53198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("inlined runtime function: IsNonNegativeSmi");
5320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
53248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("inlined runtime function: IsUndetectableObject");
5325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
5329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    CallRuntime* call) {
53308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout(
53318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
5332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
53351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Support for construct call checks.
5336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
5337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 0);
53388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (function_state()->outer() != NULL) {
53398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // We are generating graph for inlined function. Currently
53408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // constructor inlining is not supported and we can just return
53418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // false from %_IsConstructCall().
53428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ast_context()->ReturnValue(graph()->GetConstantFalse());
53438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
53448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ast_context()->ReturnInstruction(new(zone()) HIsConstructCall, call->id());
53458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
5346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for arguments.length and arguments[?].
5350e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
5351e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 0);
53528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
53538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HArgumentsLength* result = new(zone()) HArgumentsLength(elements);
5354e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5358e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateArguments(CallRuntime* call) {
5359e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
53608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* index = Pop();
53628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
53638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements));
53648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HAccessArgumentsAt* result =
53658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HAccessArgumentsAt(elements, length, index);
5366e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for accessing the class and value fields of an object.
5371e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateClassOf(CallRuntime* call) {
5372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The special form detected by IsClassOfTest is detected before we get here
5373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // and does not cause a bailout.
53748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("inlined runtime function: ClassOf");
5375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5378e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateValueOf(CallRuntime* call) {
5379e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
53808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
53828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HValueOf* result = new(zone()) HValueOf(value);
5383e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5387e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
53888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("inlined runtime function: SetValueOf");
5389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for charCodeAt(n).
5393e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
5394e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 2);
53958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
53968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
53971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  HValue* index = Pop();
53981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  HValue* string = Pop();
53991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  HStringCharCodeAt* result = BuildStringCharCodeAt(string, index);
5400e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n].
5405e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
540644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(call->arguments()->length() == 1);
54078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
540844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HValue* char_code = Pop();
54098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code);
541044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ast_context()->ReturnInstruction(result, call->id());
5411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n].
5415e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
541644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(call->arguments()->length() == 2);
54178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
54188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
541944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HValue* index = Pop();
542044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HValue* string = Pop();
542144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
542244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  AddInstruction(char_code);
54238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code);
5424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for object equality testing.
5429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
5430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 2);
54318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
54328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
5433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* right = Pop();
5434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* left = Pop();
54358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCompareJSObjectEq* result = new(zone()) HCompareJSObjectEq(left, right);
5436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateLog(CallRuntime* call) {
5441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // %_Log is ignored in optimized code.
5442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnValue(graph()->GetConstantUndefined());
5443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for Math.random().
5447e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
54488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("inlined runtime function: RandomHeapNumber");
5449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringAdd.
5453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringAdd(CallRuntime* call) {
5454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(2, call->arguments()->length());
54558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
54568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
54571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
54588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2);
5459e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(2);
5460e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for SubString.
5465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSubString(CallRuntime* call) {
5466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(3, call->arguments()->length());
54678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
54688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
54691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
54708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3);
5471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(3);
5472e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringCompare.
5477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCompare(CallRuntime* call) {
5478e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(2, call->arguments()->length());
54798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
54808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
54811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
54828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
54838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::StringCompare, 2);
5484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(2);
5485e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for direct calls from JavaScript to native RegExp code.
5490e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
5491e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(4, call->arguments()->length());
54928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
54938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
54941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
54958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4);
5496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(4);
5497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Construct a RegExp exec result with two in-object properties.
5502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
5503e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(3, call->arguments()->length());
55048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
55058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
55061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
5507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCallStub* result =
55088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3);
5509e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(3);
5510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for fast native caches.
5515e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
55168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("inlined runtime function: GetFromCache");
5517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for number to string.
5521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateNumberToString(CallRuntime* call) {
5522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(1, call->arguments()->length());
55238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
55248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
55251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
55268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
55278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::NumberToString, 1);
5528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(1);
5529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast swapping of elements. Takes three expressions, the object and two
5534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// indices. This should only be used if the indices are known to be
5535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// non-negative and within bounds of the elements array at the call site.
5536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSwapElements(CallRuntime* call) {
55378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("inlined runtime function: SwapElements");
5538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call for custom callbacks.
5542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateCallFunction(CallRuntime* call) {
55438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // 1 ~ The function to call is not itself an argument to the call.
55448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int arg_count = call->arguments()->length() - 1;
55458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(arg_count >= 1);  // There's always at least a receiver.
55468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
55478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  for (int i = 0; i < arg_count; ++i) {
55488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CHECK_ALIVE(VisitArgument(call->arguments()->at(i)));
55498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
55508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->last()));
55518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HValue* function = Pop();
55528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new HContext;
55538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(context);
55548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInvokeFunction* result =
55558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HInvokeFunction(context, function, arg_count);
55568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Drop(arg_count);
55578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ast_context()->ReturnInstruction(result, call->id());
5558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call to math functions.
5562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathPow(CallRuntime* call) {
5563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(2, call->arguments()->length());
55648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
55658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
5566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* right = Pop();
5567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* left = Pop();
55688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HPower* result = new(zone()) HPower(left, right);
5569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathSin(CallRuntime* call) {
5574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(1, call->arguments()->length());
55758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
55768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
55771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
55788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
55798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
5580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->set_transcendental_type(TranscendentalCache::SIN);
5581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(1);
5582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathCos(CallRuntime* call) {
5587e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(1, call->arguments()->length());
55888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
55898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
55901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
55918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
55928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
5593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->set_transcendental_type(TranscendentalCache::COS);
5594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(1);
5595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathLog(CallRuntime* call) {
5600e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(1, call->arguments()->length());
56018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
56028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HContext* context = new(zone()) HContext;
56031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(context);
56048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
56058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
5606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->set_transcendental_type(TranscendentalCache::LOG);
5607e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(1);
5608e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
56138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("inlined runtime function: MathSqrt");
5614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check whether two RegExps are equivalent
5618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
56198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("inlined runtime function: IsRegExpEquivalent");
5620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
5624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
56258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HValue* value = Pop();
56278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value);
5628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ast_context()->ReturnInstruction(result, call->id());
5629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
56338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Bailout("inlined runtime function: FastAsciiArrayJoin");
5634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef CHECK_BAILOUT
56388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#undef CHECK_ALIVE
5639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(HEnvironment* outer,
5642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           Scope* scope,
5643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           Handle<JSFunction> closure)
5644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : closure_(closure),
5645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      values_(0),
5646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      assigned_variables_(4),
5647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parameter_count_(0),
5648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      local_count_(0),
5649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_(outer),
5650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      pop_count_(0),
5651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      push_count_(0),
5652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_id_(AstNode::kNoNumber) {
5653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0);
5654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(const HEnvironment* other)
5658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : values_(0),
5659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      assigned_variables_(0),
5660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parameter_count_(0),
5661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      local_count_(0),
5662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_(NULL),
5663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      pop_count_(0),
5664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      push_count_(0),
5665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_id_(other->ast_id()) {
5666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Initialize(other);
5667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::Initialize(int parameter_count,
5671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              int local_count,
5672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              int stack_height) {
5673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  parameter_count_ = parameter_count;
5674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  local_count_ = local_count;
5675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Avoid reallocating the temporaries' backing store on the first Push.
5677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int total = parameter_count + local_count + stack_height;
5678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  values_.Initialize(total + 4);
5679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < total; ++i) values_.Add(NULL);
5680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
56839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Initialize(const HEnvironment* other) {
56849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  closure_ = other->closure();
56859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  values_.AddAll(other->values_);
56869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  assigned_variables_.AddAll(other->assigned_variables_);
56879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  parameter_count_ = other->parameter_count_;
56889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  local_count_ = other->local_count_;
56899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (other->outer_ != NULL) outer_ = other->outer_->Copy();  // Deep copy.
56909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  pop_count_ = other->pop_count_;
56919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  push_count_ = other->push_count_;
56929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ast_id_ = other->ast_id_;
56939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
56949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
56959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
5696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
5697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!block->IsLoopHeader());
5698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(values_.length() == other->values_.length());
5699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = values_.length();
5701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; ++i) {
5702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = values_[i];
5703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (value != NULL && value->IsPhi() && value->block() == block) {
5704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // There is already a phi for the i'th value.
5705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = HPhi::cast(value);
5706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Assert index is correct and that we haven't missed an incoming edge.
5707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(phi->merged_index() == i);
5708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(phi->OperandCount() == block->predecessors()->length());
5709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->AddInput(other->values_[i]);
5710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (values_[i] != other->values_[i]) {
5711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // There is a fresh value on the incoming edge, a phi is needed.
5712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(values_[i] != NULL && other->values_[i] != NULL);
57138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HPhi* phi = new(block->zone()) HPhi(i);
5714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* old_value = values_[i];
5715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < block->predecessors()->length(); j++) {
5716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->AddInput(old_value);
5717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->AddInput(other->values_[i]);
5719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      this->values_[i] = phi;
5720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->AddPhi(phi);
5721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
57269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Bind(int index, HValue* value) {
57279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(value != NULL);
57289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (!assigned_variables_.Contains(index)) {
57299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    assigned_variables_.Add(index);
57309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
57319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  values_[index] = value;
5732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
57359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::HasExpressionAt(int index) const {
57369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return index >= parameter_count_ + local_count_;
57379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
57389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
57399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
57409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::ExpressionStackIsEmpty() const {
57419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  int first_expression = parameter_count() + local_count();
57429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(length() >= first_expression);
57439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return length() == first_expression;
57449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
57459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
57469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
57479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
57489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  int count = index_from_top + 1;
57499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  int index = values_.length() - count;
57509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(HasExpressionAt(index));
57519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // The push count must include at least the element in question or else
57529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // the new value will not be included in this environment's history.
57539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (push_count_ < count) {
57549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // This is the same effect as popping then re-pushing 'count' elements.
57559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    pop_count_ += (count - push_count_);
57569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    push_count_ = count;
57579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
57589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  values_[index] = value;
57599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
57609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
57619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
57629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Drop(int count) {
57639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  for (int i = 0; i < count; ++i) {
57649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Pop();
5765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::Copy() const {
57708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(closure()->GetIsolate()->zone()) HEnvironment(this);
5771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyWithoutHistory() const {
5775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* result = Copy();
5776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->ClearHistory();
5777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
5778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
5782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* new_env = Copy();
5783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < values_.length(); ++i) {
57848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HPhi* phi = new(loop_header->zone()) HPhi(i);
5785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    phi->AddInput(values_[i]);
5786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_env->values_[i] = phi;
5787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    loop_header->AddPhi(phi);
5788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  new_env->ClearHistory();
5790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return new_env;
5791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyForInlining(Handle<JSFunction> target,
5795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            FunctionLiteral* function,
5796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            bool is_speculative,
5797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            HConstant* undefined) const {
5798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Outer environment is a copy of this one without the arguments.
5799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int arity = function->scope()->num_parameters();
5800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* outer = Copy();
5801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  outer->Drop(arity + 1);  // Including receiver.
5802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  outer->ClearHistory();
58038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Zone* zone = closure()->GetIsolate()->zone();
58048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HEnvironment* inner =
58058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone) HEnvironment(outer, function->scope(), target);
5806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Get the argument values from the original environment.
5807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (is_speculative) {
5808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i <= arity; ++i) {  // Include receiver.
5809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* push = ExpressionStackAt(arity - i);
5810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      inner->SetValueAt(i, push);
5811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
5813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i <= arity; ++i) {  // Include receiver.
5814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      inner->SetValueAt(i, ExpressionStackAt(arity - i));
5815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Initialize the stack-allocated locals to undefined.
5819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int local_base = arity + 1;
5820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int local_count = function->scope()->num_stack_slots();
5821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < local_count; ++i) {
5822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    inner->SetValueAt(local_base + i, undefined);
5823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
58258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  inner->set_ast_id(AstNode::kFunctionEntryId);
5826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return inner;
5827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintTo(StringStream* stream) {
58319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  for (int i = 0; i < length(); i++) {
5832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (i == 0) stream->Add("parameters\n");
5833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (i == parameter_count()) stream->Add("locals\n");
5834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (i == parameter_count() + local_count()) stream->Add("expressions");
5835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* val = values_.at(i);
5836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    stream->Add("%d: ", i);
5837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (val != NULL) {
5838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      val->PrintNameTo(stream);
5839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
5840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      stream->Add("NULL");
5841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    stream->Add("\n");
5843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintToStd() {
5848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HeapStringAllocator string_allocator;
5849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StringStream trace(&string_allocator);
5850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintTo(&trace);
5851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("%s", *trace.ToCString());
5852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceCompilation(FunctionLiteral* function) {
5856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Tag tag(this, "compilation");
5857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<String> name = function->debug_name();
5858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("name", *name->ToCString());
5859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("method", *name->ToCString());
5860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis()));
5861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLithium(const char* name, LChunk* chunk) {
5865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Trace(name, chunk->graph(), chunk);
5866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceHydrogen(const char* name, HGraph* graph) {
5870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Trace(name, graph, NULL);
5871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
5875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Tag tag(this, "cfg");
5876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("name", name);
5877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<HBasicBlock*>* blocks = graph->blocks();
5878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks->length(); i++) {
5879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* current = blocks->at(i);
5880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Tag block_tag(this, "block");
5881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintBlockProperty("name", current->block_id());
5882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintIntProperty("from_bci", -1);
5883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintIntProperty("to_bci", -1);
5884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!current->predecessors()->is_empty()) {
5886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintIndent();
5887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add("predecessors");
5888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < current->predecessors()->length(); ++j) {
5889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
5890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add("\n");
5892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
5893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintEmptyProperty("predecessors");
5894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->end() == NULL || current->end()->FirstSuccessor() == NULL) {
5897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintEmptyProperty("successors");
5898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (current->end()->SecondSuccessor() == NULL) {
5899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintBlockProperty("successors",
5900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             current->end()->FirstSuccessor()->block_id());
5901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
5902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintBlockProperty("successors",
5903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             current->end()->FirstSuccessor()->block_id(),
5904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             current->end()->SecondSuccessor()->block_id());
5905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintEmptyProperty("xhandlers");
5908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintEmptyProperty("flags");
5909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->dominator() != NULL) {
5911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintBlockProperty("dominator", current->dominator()->block_id());
5912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (chunk != NULL) {
5915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int first_index = current->first_instruction_index();
5916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int last_index = current->last_instruction_index();
5917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintIntProperty(
5918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          "first_lir_id",
5919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          LifetimePosition::FromInstructionIndex(first_index).Value());
5920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintIntProperty(
5921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          "last_lir_id",
5922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          LifetimePosition::FromInstructionIndex(last_index).Value());
5923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    {
5926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag states_tag(this, "states");
5927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag locals_tag(this, "locals");
5928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int total = current->phis()->length();
5929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add("size %d\n", total);
5930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add("method \"None\"");
5931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < total; ++j) {
5932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HPhi* phi = current->phis()->at(j);
5933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add("%d ", phi->merged_index());
5934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->PrintNameTo(&trace_);
5935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" ");
5936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->PrintTo(&trace_);
5937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add("\n");
5938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    {
5942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag HIR_tag(this, "HIR");
5943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instruction = current->first();
5944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      while (instruction != NULL) {
5945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int bci = 0;
5946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int uses = instruction->uses()->length();
5947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add("%d %d ", bci, uses);
5948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instruction->PrintNameTo(&trace_);
5949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" ");
5950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instruction->PrintTo(&trace_);
5951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" <|@\n");
5952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instruction = instruction->next();
5953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (chunk != NULL) {
5958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag LIR_tag(this, "LIR");
5959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int first_index = current->first_instruction_index();
5960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int last_index = current->last_instruction_index();
5961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (first_index != -1 && last_index != -1) {
5962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        const ZoneList<LInstruction*>* instructions = chunk->instructions();
5963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        for (int i = first_index; i <= last_index; ++i) {
5964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          LInstruction* linstr = instructions->at(i);
5965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (linstr != NULL) {
5966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            trace_.Add("%d ",
5967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       LifetimePosition::FromInstructionIndex(i).Value());
5968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            linstr->PrintTo(&trace_);
5969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            trace_.Add(" <|@\n");
5970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
5971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
5972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
5979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Tag tag(this, "intervals");
5980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("name", name);
5981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
598244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
5983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < fixed_d->length(); ++i) {
5984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceLiveRange(fixed_d->at(i), "fixed");
5985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
598744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
5988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < fixed->length(); ++i) {
5989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceLiveRange(fixed->at(i), "fixed");
5990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
5993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < live_ranges->length(); ++i) {
5994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceLiveRange(live_ranges->at(i), "object");
5995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRange(LiveRange* range, const char* type) {
6000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (range != NULL && !range->IsEmpty()) {
6001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    trace_.Add("%d %s", range->id(), type);
6002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (range->HasRegisterAssigned()) {
6003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      LOperand* op = range->CreateAssignedOperand();
6004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int assigned_reg = op->index();
6005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (op->IsDoubleRegister()) {
6006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"%s\"",
6007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   DoubleRegister::AllocationIndexToString(assigned_reg));
6008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
6009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(op->IsRegister());
6010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg));
6011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
6012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (range->IsSpilled()) {
6013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      LOperand* op = range->TopLevel()->GetSpillOperand();
6014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (op->IsDoubleStackSlot()) {
6015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"double_stack:%d\"", op->index());
6016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
6017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(op->IsStackSlot());
6018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"stack:%d\"", op->index());
6019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
6020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
6021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int parent_index = -1;
6022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (range->IsChild()) {
6023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parent_index = range->parent()->id();
6024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
6025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parent_index = range->id();
6026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
6027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LOperand* op = range->FirstHint();
6028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int hint_index = -1;
6029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (op != NULL && op->IsUnallocated()) hint_index = op->VirtualRegister();
6030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    trace_.Add(" %d %d", parent_index, hint_index);
6031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    UseInterval* cur_interval = range->first_interval();
6032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    while (cur_interval != NULL && range->Covers(cur_interval->start())) {
6033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add(" [%d, %d[",
6034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 cur_interval->start().Value(),
6035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 cur_interval->end().Value());
6036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      cur_interval = cur_interval->next();
6037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
6038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    UsePosition* current_pos = range->first_pos();
6040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current_pos != NULL) {
6041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
6042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" %d M", current_pos->pos().Value());
6043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
6044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current_pos = current_pos->next();
6045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
6046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    trace_.Add(" \"\"\n");
6048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::FlushToFile() {
6053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AppendChars(filename_, *trace_.ToCString(), trace_.length(), false);
6054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  trace_.Reset();
6055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
605844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HStatistics::Initialize(CompilationInfo* info) {
605944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  source_size_ += info->shared_info()->SourceSize();
606044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
606144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
606244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStatistics::Print() {
6064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("Timing results:\n");
6065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int64_t sum = 0;
6066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < timing_.length(); ++i) {
6067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    sum += timing_[i];
6068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < names_.length(); ++i) {
6071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("%30s", names_[i]);
6072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    double ms = static_cast<double>(timing_[i]) / 1000;
6073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    double percent = static_cast<double>(timing_[i]) * 100 / sum;
6074b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    PrintF(" - %7.3f ms / %4.1f %% ", ms, percent);
6075b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
6076b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    unsigned size = sizes_[i];
6077b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    double size_percent = static_cast<double>(size) * 100 / total_size_;
6078b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    PrintF(" %8u bytes / %4.1f %%\n", size, size_percent);
6079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
608044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  double source_size_in_kb = static_cast<double>(source_size_) / 1024;
608144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  double normalized_time =  source_size_in_kb > 0
608244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? (static_cast<double>(sum) / 1000) / source_size_in_kb
608344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : 0;
608444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  double normalized_bytes = source_size_in_kb > 0
608544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? total_size_ / source_size_in_kb
608644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : 0;
608744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  PrintF("%30s - %7.3f ms           %7.3f bytes\n", "Sum",
608844f0eee88ff00398ff7f715fab053374d808c90dSteve Block         normalized_time, normalized_bytes);
6089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("---------------------------------------------------------------\n");
6090b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  PrintF("%30s - %7.3f ms (%.1f times slower than full code gen)\n",
6091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         "Total",
6092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         static_cast<double>(total_) / 1000,
6093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         static_cast<double>(total_) / full_code_gen_);
6094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6097b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid HStatistics::SaveTiming(const char* name, int64_t ticks, unsigned size) {
6098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (name == HPhase::kFullCodeGen) {
6099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    full_code_gen_ += ticks;
6100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (name == HPhase::kTotal) {
6101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    total_ += ticks;
6102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
6103b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    total_size_ += size;
6104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < names_.length(); ++i) {
6105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (names_[i] == name) {
6106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        timing_[i] += ticks;
6107b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        sizes_[i] += size;
6108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return;
6109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
6110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
6111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    names_.Add(name);
6112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    timing_.Add(ticks);
6113b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    sizes_.Add(size);
6114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kFullCodeGen = "Full code generator";
6119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kTotal = "Total";
6120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::Begin(const char* name,
6123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   HGraph* graph,
6124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   LChunk* chunk,
6125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   LAllocator* allocator) {
6126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  name_ = name;
6127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_ = graph;
6128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  chunk_ = chunk;
6129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  allocator_ = allocator;
6130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (allocator != NULL && chunk_ == NULL) {
6131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    chunk_ = allocator->chunk();
6132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
613344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_hydrogen_stats) start_ = OS::Ticks();
6134b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  start_allocation_size_ = Zone::allocation_size_;
6135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::End() const {
613944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_hydrogen_stats) {
6140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int64_t end = OS::Ticks();
6141b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    unsigned size = Zone::allocation_size_ - start_allocation_size_;
6142b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    HStatistics::Instance()->SaveTiming(name_, end - start_, size);
6143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_hydrogen) {
6146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_);
6147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_);
6148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (allocator_ != NULL) {
6149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HTracer::Instance()->TraceLiveRanges(name_, allocator_);
6150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
6151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
6154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (graph_ != NULL) graph_->Verify();
6155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (allocator_ != NULL) allocator_->Verify();
6156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
6157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} }  // namespace v8::internal
6160