13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Redistribution and use in source and binary forms, with or without
3b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// modification, are permitted provided that the following conditions are
4b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// met:
5b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//
6b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Redistributions of source code must retain the above copyright
7b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       notice, this list of conditions and the following disclaimer.
8b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Redistributions in binary form must reproduce the above
9b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       copyright notice, this list of conditions and the following
10b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       disclaimer in the documentation and/or other materials provided
11b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       with the distribution.
12b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Neither the name of Google Inc. nor the names of its
13b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       contributors may be used to endorse or promote products derived
14b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       from this software without specific prior written permission.
15b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//
16b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "v8.h"
29b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "hydrogen.h"
30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "codegen.h"
32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h"
33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "hashmap.h"
34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "lithium-allocator.h"
35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "parser.h"
363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "scopeinfo.h"
37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "scopes.h"
381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "stub-cache.h"
39b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#if V8_TARGET_ARCH_IA32
41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "ia32/lithium-codegen-ia32.h"
42b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#elif V8_TARGET_ARCH_X64
43b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "x64/lithium-codegen-x64.h"
44b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#elif V8_TARGET_ARCH_ARM
45b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "arm/lithium-codegen-arm.h"
4644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#elif V8_TARGET_ARCH_MIPS
4744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "mips/lithium-codegen-mips.h"
48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#else
49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#error Unsupported target architecture.
50b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
51b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
52b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 {
53b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal {
54b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
55b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock::HBasicBlock(HGraph* graph)
56b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : block_id_(graph->GetNextBlockID()),
57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      graph_(graph),
58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phis_(4),
59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      first_(NULL),
60b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      last_(NULL),
61b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      end_(NULL),
62b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      loop_information_(NULL),
63b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      predecessors_(2),
64b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      dominator_(NULL),
65b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      dominated_blocks_(4),
66b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      last_environment_(NULL),
67b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      argument_count_(-1),
68b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      first_instruction_index_(-1),
69b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      last_instruction_index_(-1),
70b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      deleted_phis_(4),
711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      parent_loop_header_(NULL),
723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      is_inline_return_target_(false),
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      is_deoptimizing_(false),
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      dominates_loop_successors_(false) { }
75b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AttachLoopInformation() {
78b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsLoopHeader());
798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  loop_information_ = new(zone()) HLoopInformation(this);
80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::DetachLoopInformation() {
84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(IsLoopHeader());
85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  loop_information_ = NULL;
86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddPhi(HPhi* phi) {
90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsStartBlock());
91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phis_.Add(phi);
92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phi->SetBlock(this);
93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::RemovePhi(HPhi* phi) {
97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(phi->block() == this);
98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(phis_.Contains(phi));
9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(phi->HasNoUses() || !phi->is_live());
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  phi->Kill();
101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phis_.RemoveElement(phi);
102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phi->SetBlock(NULL);
103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddInstruction(HInstruction* instr) {
107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsStartBlock() || !IsFinished());
108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!instr->IsLinked());
109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsFinished());
110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (first_ == NULL) {
1118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HBlockEntry* entry = new(zone()) HBlockEntry();
112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    entry->InitializeAsFirst(this);
113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    first_ = last_ = entry;
114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  instr->InsertAfter(last_);
116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  last_ = instr;
117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHDeoptimize* HBasicBlock::CreateDeoptimize(
121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HDeoptimize::UseEnvironment has_uses) {
12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(HasEnvironment());
123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (has_uses == HDeoptimize::kNoUses) return new(zone()) HDeoptimize(0);
12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HEnvironment* environment = last_environment();
1268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HDeoptimize* instr = new(zone()) HDeoptimize(environment->length());
12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < environment->length(); i++) {
12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* val = environment->values()->at(i);
12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    instr->AddEnvironmentValue(val);
13044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
13144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return instr;
13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1363fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHSimulate* HBasicBlock::CreateSimulate(int ast_id) {
137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(HasEnvironment());
138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* environment = last_environment();
1393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(ast_id == AstNode::kNoNumber ||
1403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         environment->closure()->shared()->VerifyBailoutId(ast_id));
141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int push_count = environment->push_count();
143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int pop_count = environment->pop_count();
144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HSimulate* instr = new(zone()) HSimulate(ast_id, pop_count);
146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = push_count - 1; i >= 0; --i) {
147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->AddPushedValue(environment->ExpressionStackAt(i));
148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < environment->assigned_variables()->length(); ++i) {
150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int index = environment->assigned_variables()->at(i);
151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->AddAssignedValue(index, environment->Lookup(index));
152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  environment->ClearHistory();
154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Finish(HControlInstruction* end) {
159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsFinished());
160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(end);
161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  end_ = end;
1623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
1633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    it.Current()->RegisterPredecessor(this);
164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HBasicBlock::Goto(HBasicBlock* block, bool drop_extra) {
16944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (block->IsInlineReturnTarget()) {
1708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HLeaveInlined);
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    last_environment_ = last_environment()->DiscardInlined(drop_extra);
17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddSimulate(AstNode::kNoNumber);
1748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HGoto* instr = new(zone()) HGoto(block);
175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Finish(instr);
176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HBasicBlock::AddLeaveInlined(HValue* return_value,
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  HBasicBlock* target,
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  bool drop_extra) {
18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(target->IsInlineReturnTarget());
18344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(return_value != NULL);
1848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HLeaveInlined);
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  last_environment_ = last_environment()->DiscardInlined(drop_extra);
18644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  last_environment()->Push(return_value);
18744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  AddSimulate(AstNode::kNoNumber);
1888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HGoto* instr = new(zone()) HGoto(target);
18944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Finish(instr);
19044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
19144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!HasEnvironment());
195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(first() == NULL);
196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UpdateEnvironment(env);
197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HBasicBlock::SetJoinId(int ast_id) {
201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = predecessors_.length();
202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(length > 0);
203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; i++) {
204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* predecessor = predecessors_[i];
205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(predecessor->end()->IsGoto());
206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // We only need to verify the ID once.
208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(i != 0 ||
209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           predecessor->last_environment()->closure()->shared()
2103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               ->VerifyBailoutId(ast_id));
2113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    simulate->set_ast_id(ast_id);
212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HBasicBlock::Dominates(HBasicBlock* other) const {
217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* current = other->dominator();
218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (current != NULL) {
219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current == this) return true;
220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current = current->dominator();
221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return false;
223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
226589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochint HBasicBlock::LoopNestingDepth() const {
227589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  const HBasicBlock* current = this;
228589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int result  = (current->IsLoopHeader()) ? 1 : 0;
229589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  while (current->parent_loop_header() != NULL) {
230589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    current = current->parent_loop_header();
231589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    result++;
232589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
233589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return result;
234589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
235589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(IsLoopHeader());
239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetJoinId(stmt->EntryId());
241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (predecessors()->length() == 1) {
242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // This is a degenerated loop.
243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    DetachLoopInformation();
244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Only the first entry into the loop is from outside the loop. All other
248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // entries must be back edges.
249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 1; i < predecessors()->length(); ++i) {
250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    loop_information()->RegisterBackEdge(predecessors()->at(i));
251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (HasPredecessor()) {
257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Only loop header blocks can have a predecessor added after
258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // instructions have been added to the block (they have phis for all
259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // values in the environment, these phis may be eliminated later).
260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(IsLoopHeader() || first_ == NULL);
261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HEnvironment* incoming_env = pred->last_environment();
262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (IsLoopHeader()) {
2639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ASSERT(phis()->length() == incoming_env->length());
264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int i = 0; i < phis_.length(); ++i) {
265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phis_[i]->AddInput(incoming_env->values()->at(i));
266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      last_environment()->AddIncomingEdge(this, pred->last_environment());
269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (!HasEnvironment() && !IsFinished()) {
271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!IsLoopHeader());
272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetInitialEnvironment(pred->last_environment()->Copy());
273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  predecessors_.Add(pred);
276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!dominated_blocks_.Contains(block));
281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Keep the list of dominated blocks sorted such that if there is two
282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // succeeding block in this list, the predecessor is before the successor.
283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = 0;
284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (index < dominated_blocks_.length() &&
285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         dominated_blocks_[index]->block_id() < block->block_id()) {
286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ++index;
287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  dominated_blocks_.InsertAt(index, block);
289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (dominator_ == NULL) {
294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    dominator_ = other;
295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    other->AddDominatedBlock(this);
296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (other->dominator() != NULL) {
297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* first = dominator_;
298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* second = other;
299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (first != second) {
301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (first->block_id() > second->block_id()) {
302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        first = first->dominator();
303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        second = second->dominator();
305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(first != NULL && second != NULL);
307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (dominator_ != first) {
310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(dominator_->dominated_blocks_.Contains(this));
311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      dominator_->dominated_blocks_.RemoveElement(this);
312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      dominator_ = first;
313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      first->AddDominatedBlock(this);
314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HBasicBlock::AssignLoopSuccessorDominators() {
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Mark blocks that dominate all subsequent reachable blocks inside their
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // loop. Exploit the fact that blocks are sorted in reverse post order. When
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the loop is visited in increasing block id order, if the number of
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // non-loop-exiting successor edges at the dominator_candidate block doesn't
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // exceed the number of previously encountered predecessor edges, there is no
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // path from the loop header to any block with higher id that doesn't go
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // through the dominator_candidate block. In this case, the
3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // dominator_candidate block is guaranteed to dominate all blocks reachable
3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // from it with higher ids.
3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* last = loop_information()->GetLastBackEdge();
3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int outstanding_successors = 1;  // one edge from the pre-header
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Header always dominates everything.
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MarkAsLoopSuccessorDominator();
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int j = block_id(); j <= last->block_id(); ++j) {
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HBasicBlock* dominator_candidate = graph_->blocks()->at(j);
3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (HPredecessorIterator it(dominator_candidate); !it.Done();
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         it.Advance()) {
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HBasicBlock* predecessor = it.Current();
3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Don't count back edges.
3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (predecessor->block_id() < dominator_candidate->block_id()) {
3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        outstanding_successors--;
3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If more successors than predecessors have been seen in the loop up to
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // now, it's not possible to guarantee that the current block dominates
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // all of the blocks with higher IDs. In this case, assume conservatively
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // that those paths through loop that don't go through the current block
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // contain all of the loop's dependencies. Also be careful to record
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // dominator information about the current loop that's being processed,
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // and not nested loops, which will be processed when
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // AssignLoopSuccessorDominators gets called on their header.
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(outstanding_successors >= 0);
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header();
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (outstanding_successors == 0 &&
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) {
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      dominator_candidate->MarkAsLoopSuccessorDominator();
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HControlInstruction* end = dominator_candidate->end();
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HBasicBlock* successor = it.Current();
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Only count successors that remain inside the loop and don't loop back
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // to a loop header.
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (successor->block_id() > dominator_candidate->block_id() &&
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          successor->block_id() <= last->block_id()) {
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Backwards edges must land on loop headers.
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(successor->block_id() > dominator_candidate->block_id() ||
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               successor->IsLoopHeader());
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        outstanding_successors++;
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const {
376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < predecessors_.length(); ++i) {
377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (predecessors_[i] == predecessor) return i;
378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UNREACHABLE();
380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return -1;
381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Verify() {
386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check that every block is finished.
387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(IsFinished());
388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(block_id() >= 0);
38944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
39044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the incoming edges are in edge split form.
39144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (predecessors_.length() > 1) {
39244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 0; i < predecessors_.length(); ++i) {
39344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(predecessors_[i]->end()->SecondSuccessor() == NULL);
39444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
39544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  this->back_edges_.Add(block);
402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddBlock(block);
403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HLoopInformation::GetLastBackEdge() const {
407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int max_id = -1;
408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* result = NULL;
409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < back_edges_.length(); ++i) {
410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* cur = back_edges_[i];
411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (cur->block_id() > max_id) {
412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      max_id = cur->block_id();
413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      result = cur;
414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HLoopInformation::AddBlock(HBasicBlock* block) {
421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block == loop_header()) return;
422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->parent_loop_header() == loop_header()) return;
423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->parent_loop_header() != NULL) {
424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddBlock(block->parent_loop_header());
425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    block->set_parent_loop_header(loop_header());
427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    blocks_.Add(block);
428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < block->predecessors()->length(); ++i) {
429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddBlock(block->predecessors()->at(i));
430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Checks reachability of the blocks in this graph and stores a bit in
438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the BitVector "reachable()" for every block that can be reached
439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// from the start block of the graph. If "dont_visit" is non-null, the given
440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// block is treated as if it would not be part of the graph. "visited_count()"
441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// returns the number of reachable blocks.
442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass ReachabilityAnalyzer BASE_EMBEDDED {
443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ReachabilityAnalyzer(HBasicBlock* entry_block,
445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       int block_count,
446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       HBasicBlock* dont_visit)
447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : visited_count_(0),
448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        stack_(16),
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        reachable_(block_count, ZONE),
450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        dont_visit_(dont_visit) {
451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PushBlock(entry_block);
452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Analyze();
453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int visited_count() const { return visited_count_; }
456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const BitVector* reachable() const { return &reachable_; }
457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void PushBlock(HBasicBlock* block) {
460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block != NULL && block != dont_visit_ &&
461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        !reachable_.Contains(block->block_id())) {
462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      reachable_.Add(block->block_id());
463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      stack_.Add(block);
464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      visited_count_++;
465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze() {
469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (!stack_.is_empty()) {
470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HControlInstruction* end = stack_.RemoveLast()->end();
4713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
4723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        PushBlock(it.Current());
4733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int visited_count_;
478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HBasicBlock*> stack_;
479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BitVector reachable_;
480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* dont_visit_;
481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraph::Verify(bool do_full_verify) const {
485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); i++) {
486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = blocks_.at(i);
487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    block->Verify();
489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that every block contains at least one node and that only the last
491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // node is a control instruction.
492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = block->first();
493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(current != NULL && current->IsBlockEntry());
494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT((current->next() == NULL) == current->IsControlInstruction());
496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(current->block() == block);
497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current->Verify();
498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that successors are correctly set.
502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* first = block->end()->FirstSuccessor();
503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* second = block->end()->SecondSuccessor();
504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(second == NULL || first != NULL);
505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that the predecessor array is correct.
507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (first != NULL) {
508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(first->predecessors()->Contains(block));
509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (second != NULL) {
510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(second->predecessors()->Contains(block));
511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that phis have correct arguments.
515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < block->phis()->length(); j++) {
516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = block->phis()->at(j);
517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->Verify();
518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that all join blocks have predecessors that end with an
521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // unconditional goto and agree on their environment node id.
522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->predecessors()->length() >= 2) {
523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int id = block->predecessors()->first()->last_environment()->ast_id();
524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int k = 0; k < block->predecessors()->length(); k++) {
525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HBasicBlock* predecessor = block->predecessors()->at(k);
526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(predecessor->end()->IsGoto());
527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(predecessor->last_environment()->ast_id() == id);
528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check special property of first block to have no predecessors.
533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(blocks_.at(0)->predecessors()->is_empty());
534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (do_full_verify) {
5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check that the graph is fully connected.
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(analyzer.visited_count() == blocks_.length());
539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check that entry block dominator is NULL.
5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(entry_block_->dominator() == NULL);
542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check dominators.
5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < blocks_.length(); ++i) {
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HBasicBlock* block = blocks_.at(i);
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (block->dominator() == NULL) {
5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Only start block may have no dominator assigned to.
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(i == 0);
5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Assert that block is unreachable if dominator must not be visited.
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ReachabilityAnalyzer dominator_analyzer(entry_block_,
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                blocks_.length(),
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                block->dominator());
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(!dominator_analyzer.reachable()->Contains(block->block_id()));
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               Object* value) {
565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!pointer->is_set()) {
5668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HConstant* constant = new(zone()) HConstant(Handle<Object>(value),
5678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                Representation::Tagged());
568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    constant->InsertAfter(GetConstantUndefined());
569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    pointer->set(constant);
570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return pointer->get();
572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstant1() {
576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return GetConstant(&constant_1_, Smi::FromInt(1));
577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantMinus1() {
581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return GetConstant(&constant_minus1_, Smi::FromInt(-1));
582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantTrue() {
58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return GetConstant(&constant_true_, isolate()->heap()->true_value());
587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantFalse() {
59144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return GetConstant(&constant_false_, isolate()->heap()->false_value());
592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5953fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHConstant* HGraph::GetConstantHole() {
5963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return GetConstant(&constant_hole_, isolate()->heap()->the_hole_value());
5973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
5983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHGraphBuilder::HGraphBuilder(CompilationInfo* info,
601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                             TypeFeedbackOracle* oracle)
602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    : function_state_(NULL),
6033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      initial_function_state_(this, info, oracle, NORMAL_RETURN),
604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ast_context_(NULL),
605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break_scope_(NULL),
606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      graph_(NULL),
607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      current_block_(NULL),
608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      inlined_count_(0),
609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      zone_(info->isolate()->zone()),
610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      inline_bailout_(false) {
611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This is not initialized in the initializer list because the
612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // constructor for the initial state relies on function_state_ == NULL
613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // to know it's the initial state.
614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  function_state_= &initial_function_state_;
615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateJoin(HBasicBlock* first,
618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* second,
619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       int join_id) {
620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (first == NULL) {
621e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return second;
622e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (second == NULL) {
623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return first;
624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* join_block = graph_->CreateBasicBlock();
626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    first->Goto(join_block);
627e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    second->Goto(join_block);
628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    join_block->SetJoinId(join_id);
629e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return join_block;
630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::JoinContinue(IterationStatement* statement,
635e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         HBasicBlock* exit_block,
636e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         HBasicBlock* continue_block) {
637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (continue_block != NULL) {
638e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (exit_block != NULL) exit_block->Goto(continue_block);
639e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    continue_block->SetJoinId(statement->ContinueId());
640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return continue_block;
641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
642e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return exit_block;
643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
646e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement,
647e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* loop_entry,
648e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* body_exit,
649e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* loop_successor,
650e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       HBasicBlock* break_block) {
6513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (body_exit != NULL) body_exit->Goto(loop_entry);
652e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  loop_entry->PostProcessLoopHeader(statement);
653e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (break_block != NULL) {
654e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (loop_successor != NULL) loop_successor->Goto(break_block);
655e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    break_block->SetJoinId(statement->ExitId());
656e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return break_block;
657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
658e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return loop_successor;
659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
662e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HBasicBlock::FinishExit(HControlInstruction* instruction) {
663e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Finish(instruction);
664e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ClearEnvironment();
665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHGraph::HGraph(CompilationInfo* info)
66944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : isolate_(info->isolate()),
670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      next_block_id_(0),
67144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      entry_block_(NULL),
672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      blocks_(8),
673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      values_(16),
674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi_list_(NULL) {
6758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  start_environment_ =
6768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HEnvironment(NULL, info->scope(), info->closure());
6778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  start_environment_->set_ast_id(AstNode::kFunctionEntryId);
67844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  entry_block_ = CreateBasicBlock();
67944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  entry_block_->SetInitialEnvironment(start_environment_);
680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHandle<Code> HGraph::Compile(CompilationInfo* info) {
684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int values = GetMaximumValueID();
6853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (values > LUnallocated::kMaxVirtualRegisters) {
6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_trace_bailout) {
6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrintF("Not enough virtual registers for (values).\n");
6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return Handle<Code>::null();
690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LAllocator allocator(values, this);
692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LChunkBuilder builder(info, this, &allocator);
693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LChunk* chunk = builder.Build();
694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (chunk == NULL) return Handle<Code>::null();
695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!allocator.Allocate(chunk)) {
6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_trace_bailout) {
6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrintF("Not enough virtual registers (regalloc).\n");
6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler assembler(info->isolate(), NULL, 0);
704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LCodeGen generator(chunk, &assembler, info);
705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  chunk->MarkEmptyBlocks();
707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (generator.GenerateCode()) {
709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (FLAG_trace_codegen) {
710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintF("Crankshaft Compiler - ");
711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    CodeGenerator::MakeCodePrologue(info);
713589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Code::Flags flags = Code::ComputeFlags(Code::OPTIMIZED_FUNCTION);
714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Code> code =
715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        CodeGenerator::MakeCodeEpilogue(&assembler, flags, info);
716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    generator.FinishCode(code);
717e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    CodeGenerator::PrintCode(code, info);
718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return code;
719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Handle<Code>::null();
721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraph::CreateBasicBlock() {
7258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HBasicBlock* result = new(zone()) HBasicBlock(this);
726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  blocks_.Add(result);
727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Canonicalize() {
732e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!FLAG_use_canonicalizing) return;
7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HPhase phase("H_Canonicalize", this);
734e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < blocks()->length(); ++i) {
735e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HInstruction* instr = blocks()->at(i)->first();
736e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    while (instr != NULL) {
737e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HValue* value = instr->Canonicalize();
738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (value != instr) instr->DeleteAndReplaceWith(value);
739e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      instr = instr->next();
740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::OrderBlocks() {
7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HPhase phase("H_Block ordering");
7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BitVector visited(blocks_.length(), zone());
748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HBasicBlock*> reverse_result(8);
750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* start = blocks_[0];
751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Postorder(start, &visited, &reverse_result, NULL);
752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  blocks_.Rewind(0);
754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = 0;
755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = reverse_result.length() - 1; i >= 0; --i) {
756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* b = reverse_result[i];
757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    blocks_.Add(b);
758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    b->set_block_id(index++);
759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::PostorderLoopBlocks(HLoopInformation* loop,
764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 BitVector* visited,
765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 ZoneList<HBasicBlock*>* order,
766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 HBasicBlock* loop_header) {
767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < loop->blocks()->length(); ++i) {
768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* b = loop->blocks()->at(i);
7693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    for (HSuccessorIterator it(b->end()); !it.Done(); it.Advance()) {
7703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Postorder(it.Current(), visited, order, loop_header);
7713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (b->IsLoopHeader() && b != loop->loop_header()) {
773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PostorderLoopBlocks(b->loop_information(), visited, order, loop_header);
774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Postorder(HBasicBlock* block,
780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       BitVector* visited,
781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       ZoneList<HBasicBlock*>* order,
782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       HBasicBlock* loop_header) {
783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block == NULL || visited->Contains(block->block_id())) return;
784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->parent_loop_header() != loop_header) return;
785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  visited->Add(block->block_id());
786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->IsLoopHeader()) {
787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PostorderLoopBlocks(block->loop_information(), visited, order, loop_header);
7883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) {
7893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Postorder(it.Current(), visited, order, block);
7903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(block->IsFinished());
7933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) {
7943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Postorder(it.Current(), visited, order, loop_header);
7953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(block->end()->FirstSuccessor() == NULL ||
798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         order->Contains(block->end()->FirstSuccessor()) ||
799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         block->end()->FirstSuccessor()->IsLoopHeader());
800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(block->end()->SecondSuccessor() == NULL ||
801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         order->Contains(block->end()->SecondSuccessor()) ||
802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         block->end()->SecondSuccessor()->IsLoopHeader());
803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  order->Add(block);
804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::AssignDominators() {
8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HPhase phase("H_Assign dominators", this);
809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); ++i) {
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HBasicBlock* block = blocks_[i];
8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (block->IsLoopHeader()) {
81269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // Only the first predecessor of a loop header is from outside the loop.
81369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // All others are back edges, and thus cannot dominate the loop header.
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      block->AssignCommonDominator(block->predecessors()->first());
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      block->AssignLoopSuccessorDominators();
816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
82269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
8233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
82469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Mark all blocks that are dominated by an unconditional soft deoptimize to
82569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// prevent code motion across those blocks.
82669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid HGraph::PropagateDeoptimizingMark() {
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HPhase phase("H_Propagate deoptimizing mark", this);
8283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  MarkAsDeoptimizingRecursively(entry_block());
829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) {
8323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
8333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HBasicBlock* dominated = block->dominated_blocks()->at(i);
8343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing();
8353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MarkAsDeoptimizingRecursively(dominated);
8363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
8373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
8383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::EliminateRedundantPhis() {
8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HPhase phase("H_Redundant phi elimination", this);
841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Worklist of phis that can potentially be eliminated. Initialized with
843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // all phi nodes. When elimination of a phi node modifies another phi node
844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the modified phi node is added to the worklist.
845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HPhi*> worklist(blocks_.length());
846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); ++i) {
847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    worklist.AddAll(*blocks_[i]->phis());
848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (!worklist.is_empty()) {
851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = worklist.RemoveLast();
852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = phi->block();
853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Skip phi node if it was already replaced.
855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block == NULL) continue;
856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Get replacement value if phi is redundant.
858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HValue* replacement = phi->GetRedundantReplacement();
859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (replacement != NULL) {
861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Iterate through the uses and replace them all.
862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        HValue* value = it.value();
864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        value->SetOperandAt(it.index(), replacement);
865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (value->IsPhi()) worklist.Add(HPhi::cast(value));
866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->RemovePhi(phi);
86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
86944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
87044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
87144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
87244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
87344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HGraph::EliminateUnreachablePhis() {
8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HPhase phase("H_Unreachable phi elimination", this);
87544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
87644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Initialize worklist.
87744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ZoneList<HPhi*> phi_list(blocks_.length());
87844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ZoneList<HPhi*> worklist(blocks_.length());
87944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < blocks_.length(); ++i) {
88044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int j = 0; j < blocks_[i]->phis()->length(); j++) {
88144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HPhi* phi = blocks_[i]->phis()->at(j);
88244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      phi_list.Add(phi);
8831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // We can't eliminate phis in the receiver position in the environment
8841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // because in case of throwing an error we need this value to
8851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // construct a stack trace.
88644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (phi->HasRealUses() || phi->IsReceiver())  {
88744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        phi->set_is_live(true);
88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        worklist.Add(phi);
88944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
89044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
89144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
89244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
89344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Iteratively mark live phis.
89444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  while (!worklist.is_empty()) {
89544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HPhi* phi = worklist.RemoveLast();
89644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 0; i < phi->OperandCount(); i++) {
89744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HValue* operand = phi->OperandAt(i);
89844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (operand->IsPhi() && !HPhi::cast(operand)->is_live()) {
89944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        HPhi::cast(operand)->set_is_live(true);
90044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        worklist.Add(HPhi::cast(operand));
90144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
90244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
90344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
90444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
90544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Remove unreachable phis.
90644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < phi_list.length(); i++) {
90744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HPhi* phi = phi_list[i];
90844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!phi->is_live()) {
90944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HBasicBlock* block = phi->block();
910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->RemovePhi(phi);
911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->RecordDeletedPhi(phi->merged_index());
912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraph::CheckArgumentsPhiUses() {
918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int block_count = blocks_.length();
919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < block_count; ++i) {
920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      HPhi* phi = blocks_[i]->phis()->at(j);
922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // We don't support phi uses of arguments for now.
923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (phi->CheckFlag(HValue::kIsArguments)) return false;
924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return true;
927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraph::CheckConstPhiUses() {
9313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int block_count = blocks_.length();
9323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < block_count; ++i) {
9333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
9343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HPhi* phi = blocks_[i]->phis()->at(j);
9353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Check for the hole value (from an uninitialized const).
9363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (int k = 0; k < phi->OperandCount(); k++) {
9373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (phi->OperandAt(k) == GetConstantHole()) return false;
9383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
9393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
9403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
9413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return true;
9423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
9433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraph::CollectPhis() {
9463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int block_count = blocks_.length();
9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  phi_list_ = new ZoneList<HPhi*>(block_count);
9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < block_count; ++i) {
9493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HPhi* phi = blocks_[i]->phis()->at(j);
9513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      phi_list_->Add(phi);
9523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
9553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InferTypes(ZoneList<HValue*>* worklist) {
9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BitVector in_worklist(GetMaximumValueID(), zone());
959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < worklist->length(); ++i) {
960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!in_worklist.Contains(worklist->at(i)->id()));
961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    in_worklist.Add(worklist->at(i)->id());
962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (!worklist->is_empty()) {
965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* current = worklist->RemoveLast();
966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    in_worklist.Remove(current->id());
967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->UpdateInferredType()) {
968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      for (HUseIterator it(current->uses()); !it.Done(); it.Advance()) {
969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        HValue* use = it.value();
970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (!in_worklist.Contains(use->id())) {
971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          in_worklist.Add(use->id());
972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          worklist->Add(use);
973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HRangeAnalysis BASE_EMBEDDED {
981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit HRangeAnalysis(HGraph* graph) :
9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      graph_(graph), zone_(graph->isolate()->zone()), changed_ranges_(16) { }
984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze();
986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void TraceRange(const char* msg, ...);
989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze(HBasicBlock* block);
9903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void InferControlFlowRange(HCompareIDAndBranch* test, HBasicBlock* dest);
9913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other);
992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferRange(HValue* value);
993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void RollBackTo(int index);
994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AddRange(HValue* value, Range* range);
995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Zone* zone_;
998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HValue*> changed_ranges_;
999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::TraceRange(const char* msg, ...) {
1003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_range) {
1004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_list arguments;
1005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_start(arguments, msg);
1006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    OS::VPrint(msg, arguments);
1007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_end(arguments);
1008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::Analyze() {
10133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HPhase phase("H_Range analysis", graph_);
10143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Analyze(graph_->entry_block());
1015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::Analyze(HBasicBlock* block) {
1019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("Analyzing block B%d\n", block->block_id());
1020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int last_changed_range = changed_ranges_.length() - 1;
1022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Infer range based on control flow.
1024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->predecessors()->length() == 1) {
1025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* pred = block->predecessors()->first();
10263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (pred->end()->IsCompareIDAndBranch()) {
10273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      InferControlFlowRange(HCompareIDAndBranch::cast(pred->end()), block);
1028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Process phi instructions.
1032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < block->phis()->length(); ++i) {
1033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = block->phis()->at(i);
10343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    InferRange(phi);
1035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Go through all instructions of the current block.
1038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = block->first();
1039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (instr != block->end()) {
1040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferRange(instr);
1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = instr->next();
1042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Continue analysis in all dominated blocks.
1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
1046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Analyze(block->dominated_blocks()->at(i));
1047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RollBackTo(last_changed_range);
1050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
10533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test,
10543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                           HBasicBlock* dest) {
10551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
10563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (test->GetInputRepresentation().IsInteger32()) {
10573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Token::Value op = test->token();
10583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (test->SecondSuccessor() == dest) {
10593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      op = Token::NegateCompareOp(op);
1060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
10613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Token::Value inverted_op = Token::InvertCompareOp(op);
10623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    UpdateControlFlowRange(op, test->left(), test->right());
10633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    UpdateControlFlowRange(inverted_op, test->right(), test->left());
1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// We know that value [op] other. Use this information to update the range on
1069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// value.
10703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HRangeAnalysis::UpdateControlFlowRange(Token::Value op,
10713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                            HValue* value,
10723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                            HValue* other) {
1073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Range temp_range;
1074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Range* range = other->range() != NULL ? other->range() : &temp_range;
1075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Range* new_range = NULL;
1076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("Control flow range infer %d %s %d\n",
1078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             value->id(),
1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             Token::Name(op),
1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             other->id());
1081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (op == Token::EQ || op == Token::EQ_STRICT) {
1083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // The same range has to apply for value.
10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    new_range = range->Copy(zone_);
1085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::LT || op == Token::LTE) {
10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    new_range = range->CopyClearLower(zone_);
1087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (op == Token::LT) {
1088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new_range->AddConstant(-1);
1089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::GT || op == Token::GTE) {
10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    new_range = range->CopyClearUpper(zone_);
1092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (op == Token::GT) {
1093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new_range->AddConstant(1);
1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (new_range != NULL && !new_range->IsMostGeneric()) {
1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddRange(value, new_range);
1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferRange(HValue* value) {
1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!value->HasRange());
1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!value->representation().IsNone()) {
11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    value->ComputeInitialRange(zone_);
1107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Range* range = value->range();
1108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n",
1109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               value->id(),
1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               value->Mnemonic(),
1111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               range->lower(),
1112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               range->upper());
1113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::RollBackTo(int index) {
1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = index + 1; i < changed_ranges_.length(); ++i) {
1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    changed_ranges_[i]->RemoveLastAddedRange();
1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  changed_ranges_.Rewind(index + 1);
1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::AddRange(HValue* value, Range* range) {
1126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Range* original_range = value->range();
11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  value->AddNewRange(range, zone_);
1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  changed_ranges_.Add(value);
1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Range* new_range = value->range();
1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("Updated range of %d set to [%d,%d]\n",
1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             value->id(),
1132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             new_range->lower(),
1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             new_range->upper());
1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (original_range != NULL) {
1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceRange("Original range was [%d,%d]\n",
1136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               original_range->lower(),
1137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               original_range->upper());
1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("New information was [%d,%d]\n",
1140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             range->lower(),
1141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             range->upper());
1142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TraceGVN(const char* msg, ...) {
1146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_gvn) {
1147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_list arguments;
1148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_start(arguments, msg);
1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    OS::VPrint(msg, arguments);
1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_end(arguments);
1151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHValueMap::HValueMap(Zone* zone, const HValueMap* other)
1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : array_size_(other->array_size_),
1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      lists_size_(other->lists_size_),
1158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      count_(other->count_),
1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      present_flags_(other->present_flags_),
1160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      array_(zone->NewArray<HValueMapListElement>(other->array_size_)),
1161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      lists_(zone->NewArray<HValueMapListElement>(other->lists_size_)),
1162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      free_list_head_(other->free_list_head_) {
1163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memcpy(array_, other->array_, array_size_ * sizeof(HValueMapListElement));
1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memcpy(lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement));
1165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HValueMap::Kill(GVNFlagSet flags) {
11693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(flags);
11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!present_flags_.ContainsAnyOf(depends_flags)) return;
11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  present_flags_.RemoveAll();
1172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < array_size_; ++i) {
1173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = array_[i].value;
1174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (value != NULL) {
1175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Clear list of collisions first, so we know if it becomes empty.
1176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int kept = kNil;  // List of kept elements.
1177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int next;
1178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int current = array_[i].next; current != kNil; current = next) {
1179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        next = lists_[current].next;
11803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HValue* value = lists_[current].value;
11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (value->gvn_flags().ContainsAnyOf(depends_flags)) {
1182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          // Drop it.
1183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          count_--;
1184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[current].next = free_list_head_;
1185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          free_list_head_ = current;
1186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else {
1187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          // Keep it.
1188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[current].next = kept;
1189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          kept = current;
11903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          present_flags_.Add(value->gvn_flags());
1191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      array_[i].next = kept;
1194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Now possibly drop directly indexed element.
11963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      value = array_[i].value;
11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (value->gvn_flags().ContainsAnyOf(depends_flags)) {  // Drop it.
1198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        count_--;
1199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int head = array_[i].next;
1200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (head == kNil) {
1201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          array_[i].value = NULL;
1202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else {
1203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          array_[i].value = lists_[head].value;
1204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          array_[i].next = lists_[head].next;
1205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[head].next = free_list_head_;
1206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          free_list_head_ = head;
1207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        present_flags_.Add(value->gvn_flags());  // Keep it.
1210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHValue* HValueMap::Lookup(HValue* value) const {
1217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint32_t hash = static_cast<uint32_t>(value->Hashcode());
1218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint32_t pos = Bound(hash);
1219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (array_[pos].value != NULL) {
1220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (array_[pos].value->Equals(value)) return array_[pos].value;
1221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int next = array_[pos].next;
1222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (next != kNil) {
1223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (lists_[next].value->Equals(value)) return lists_[next].value;
1224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      next = lists_[next].next;
1225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return NULL;
1228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Resize(int new_size) {
1232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(new_size > count_);
1233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Hashing the values into the new array has no more collisions than in the
1234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // old hash map, so we can use the existing lists_ array, if we are careful.
1235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Make sure we have at least one free element.
1237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (free_list_head_ == kNil) {
1238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ResizeLists(lists_size_ << 1);
1239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* new_array =
124244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ZONE->NewArray<HValueMapListElement>(new_size);
1243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(new_array, 0, sizeof(HValueMapListElement) * new_size);
1244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* old_array = array_;
1246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int old_size = array_size_;
1247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int old_count = count_;
1249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  count_ = 0;
1250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Do not modify present_flags_.  It is currently correct.
1251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  array_size_ = new_size;
1252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  array_ = new_array;
1253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (old_array != NULL) {
1255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Iterate over all the elements in lists, rehashing them.
1256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < old_size; ++i) {
1257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (old_array[i].value != NULL) {
1258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int current = old_array[i].next;
1259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        while (current != kNil) {
1260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          Insert(lists_[current].value);
1261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          int next = lists_[current].next;
1262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[current].next = free_list_head_;
1263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          free_list_head_ = current;
1264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          current = next;
1265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Rehash the directly stored value.
1267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Insert(old_array[i].value);
1268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  USE(old_count);
1272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(count_ == old_count);
1273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::ResizeLists(int new_size) {
1277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(new_size > lists_size_);
1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* new_lists =
128044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ZONE->NewArray<HValueMapListElement>(new_size);
1281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(new_lists, 0, sizeof(HValueMapListElement) * new_size);
1282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* old_lists = lists_;
1284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int old_size = lists_size_;
1285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  lists_size_ = new_size;
1287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  lists_ = new_lists;
1288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (old_lists != NULL) {
1290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    memcpy(lists_, old_lists, old_size * sizeof(HValueMapListElement));
1291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = old_size; i < lists_size_; ++i) {
1293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    lists_[i].next = free_list_head_;
1294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    free_list_head_ = i;
1295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Insert(HValue* value) {
1300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(value != NULL);
1301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Resizing when half of the hashtable is filled up.
1302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (count_ >= array_size_ >> 1) Resize(array_size_ << 1);
1303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(count_ < array_size_);
1304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  count_++;
1305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint32_t pos = Bound(static_cast<uint32_t>(value->Hashcode()));
1306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (array_[pos].value == NULL) {
1307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    array_[pos].value = value;
1308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    array_[pos].next = kNil;
1309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
1310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (free_list_head_ == kNil) {
1311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ResizeLists(lists_size_ << 1);
1312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int new_element_pos = free_list_head_;
1314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(new_element_pos != kNil);
1315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    free_list_head_ = lists_[free_list_head_].next;
1316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    lists_[new_element_pos].value = value;
1317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    lists_[new_element_pos].next = array_[pos].next;
1318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value != NULL);
1319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    array_[pos].next = new_element_pos;
1320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HStackCheckEliminator BASE_EMBEDDED {
1325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
1326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { }
1327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Process();
1329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
1331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
1332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStackCheckEliminator::Process() {
1336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // For each loop block walk the dominator tree from the backwards branch to
1337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the loop header. If a call instruction is encountered the backwards branch
1338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // is dominated by a call and the stack check in the backwards branch can be
1339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // removed.
1340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < graph_->blocks()->length(); i++) {
1341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
1343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge();
1344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* dominator = back_edge;
13453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      while (true) {
1346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HInstruction* instr = dominator->first();
13473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        while (instr != NULL) {
1348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (instr->IsCall()) {
13493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            block->loop_information()->stack_check()->Eliminate();
13503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            break;
1351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
1352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          instr = instr->next();
1353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
13553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        // Done when the loop header is processed.
13563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (dominator == block) break;
1357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
13583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        // Move up the dominator tree.
13593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        dominator = dominator->dominator();
13603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
1361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Simple sparse set with O(1) add, contains, and clear.
1367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass SparseSet {
1368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
1369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SparseSet(Zone* zone, int capacity)
1370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : capacity_(capacity),
1371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        length_(0),
1372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        dense_(zone->NewArray<int>(capacity)),
13733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        sparse_(zone->NewArray<int>(capacity)) {
13743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#ifndef NVALGRIND
13753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Initialize the sparse array to make valgrind happy.
13763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    memset(sparse_, 0, sizeof(sparse_[0]) * capacity);
13773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
13783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool Contains(int n) const {
1381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(0 <= n && n < capacity_);
1382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int d = sparse_[n];
1383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return 0 <= d && d < length_ && dense_[d] == n;
1384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool Add(int n) {
1387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (Contains(n)) return false;
1388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    dense_[length_] = n;
1389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    sparse_[n] = length_;
1390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ++length_;
1391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return true;
1392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Clear() { length_ = 0; }
1395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
1397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int capacity_;
1398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int length_;
1399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int* dense_;
1400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int* sparse_;
1401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(SparseSet);
1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
1404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HGlobalValueNumberer BASE_EMBEDDED {
1407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
1408e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info)
1409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : graph_(graph),
1410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        info_(info),
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        removed_side_effects_(false),
1412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        block_side_effects_(graph->blocks()->length()),
1413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        loop_side_effects_(graph->blocks()->length()),
1414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        visited_on_paths_(graph->zone(), graph->blocks()->length()) {
141544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(info->isolate()->heap()->allow_allocation(false));
14163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    block_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length());
14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    loop_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length());
1418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ~HGlobalValueNumberer() {
142044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(!info_->isolate()->heap()->allow_allocation(true));
1421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns true if values with side effects are removed.
14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool Analyze();
1425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock(
14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HBasicBlock* dominator,
14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HBasicBlock* dominated);
1430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
1431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void ComputeBlockSideEffects();
1432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void LoopInvariantCodeMotion();
1433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void ProcessLoopBlock(HBasicBlock* block,
1434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        HBasicBlock* before_loop,
14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        GVNFlagSet loop_kills,
14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        GVNFlagSet* accumulated_first_time_depends,
14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        GVNFlagSet* accumulated_first_time_changes);
1438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool AllowCodeMotion();
1439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
1440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HGraph* graph() { return graph_; }
1442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompilationInfo* info() { return info_; }
14438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Zone* zone() { return graph_->zone(); }
1444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
1446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompilationInfo* info_;
14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool removed_side_effects_;
1448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // A map of block IDs to their side effects.
14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<GVNFlagSet> block_side_effects_;
1451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // A map of loop header block IDs to their loop's side effects.
14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<GVNFlagSet> loop_side_effects_;
1454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Used when collecting side effects on paths from dominator to
1456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // dominated.
1457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SparseSet visited_on_paths_;
1458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGlobalValueNumberer::Analyze() {
14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  removed_side_effects_ = false;
1463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ComputeBlockSideEffects();
1464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_loop_invariant_code_motion) {
1465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LoopInvariantCodeMotion();
1466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
14678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HValueMap* map = new(zone()) HValueMap();
14683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AnalyzeBlock(graph_->entry_block(), map);
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return removed_side_effects_;
1470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::ComputeBlockSideEffects() {
14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The Analyze phase of GVN can be called multiple times. Clear loop side
14753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // effects before computing them to erase the contents from previous Analyze
14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // passes.
14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < loop_side_effects_.length(); ++i) {
14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    loop_side_effects_[i].RemoveAll();
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Compute side effects for the block.
1482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* instr = block->first();
1484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int id = block->block_id();
14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GVNFlagSet side_effects;
1486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (instr != NULL) {
14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      side_effects.Add(instr->ChangesFlags());
14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (instr->IsSoftDeoptimize()) {
14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        block_side_effects_[id].RemoveAll();
14903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        side_effects.RemoveAll();
14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
14923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
1493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = instr->next();
1494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    block_side_effects_[id].Add(side_effects);
1496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Loop headers are part of their loop.
1498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      loop_side_effects_[id].Add(side_effects);
1500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Propagate loop side effects upwards.
1503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->HasParentLoopHeader()) {
1504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int header_id = block->parent_loop_header()->block_id();
15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      loop_side_effects_[header_id].Add(block->IsLoopHeader()
15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        ? loop_side_effects_[id]
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        : side_effects);
1508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::LoopInvariantCodeMotion() {
1514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GVNFlagSet side_effects = loop_side_effects_[block->block_id()];
1518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n",
1519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               block->block_id(),
15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               side_effects.ToIntegral());
1521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GVNFlagSet accumulated_first_time_depends;
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GVNFlagSet accumulated_first_time_changes;
1524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* last = block->loop_information()->GetLastBackEdge();
1525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = block->block_id(); j <= last->block_id(); ++j) {
15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects,
15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         &accumulated_first_time_depends,
15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         &accumulated_first_time_changes);
1529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGlobalValueNumberer::ProcessLoopBlock(
15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HBasicBlock* block,
15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HBasicBlock* loop_header,
15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GVNFlagSet loop_kills,
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GVNFlagSet* first_time_depends,
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GVNFlagSet* first_time_changes) {
1541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* pre_header = loop_header->predecessors()->at(0);
15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
1543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n",
1544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           block->block_id(),
15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           depends_flags.ToIntegral());
1546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = block->first();
1547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (instr != NULL) {
1548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* next = instr->next();
15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool hoisted = false;
15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->CheckFlag(HValue::kUseGVN)) {
15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      TraceGVN("Checking instruction %d (%s) instruction GVN flags 0x%X, "
15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               "loop kills 0x%X\n",
1553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               instr->id(),
15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               instr->Mnemonic(),
15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               instr->gvn_flags().ToIntegral(),
15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               depends_flags.ToIntegral());
15573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags);
15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (instr->IsTransitionElementsKind()) {
15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // It's possible to hoist transitions out of a loop as long as the
15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // hoisting wouldn't move the transition past a DependsOn of one of it's
15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // changes or any instructions that might change an objects map or
15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // elements contents.
15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        GVNFlagSet changes = instr->ChangesFlags();
15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        GVNFlagSet hoist_depends_blockers =
15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            HValue::ConvertChangesToDependsFlags(changes);
15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // In addition to not hoisting transitions above other instructions that
15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // change dependencies that the transition changes, it must not be
15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // hoisted above map changes and stores to an elements backing store
15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // that the transition might change.
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        GVNFlagSet hoist_change_blockers = changes;
15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        hoist_change_blockers.Add(kChangesMaps);
15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HTransitionElementsKind* trans = HTransitionElementsKind::cast(instr);
15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (trans->original_map()->has_fast_double_elements()) {
15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          hoist_change_blockers.Add(kChangesDoubleArrayElements);
15755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        }
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (trans->transitioned_map()->has_fast_double_elements()) {
15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          hoist_change_blockers.Add(kChangesArrayElements);
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        TraceGVN("Checking dependencies on HTransitionElementsKind %d (%s) "
15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 "hoist depends blockers 0x%X, hoist change blockers 0x%X, "
15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 "accumulated depends 0x%X, accumulated changes 0x%X\n",
15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 instr->id(),
15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 instr->Mnemonic(),
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 hoist_depends_blockers.ToIntegral(),
15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 hoist_change_blockers.ToIntegral(),
15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 first_time_depends->ToIntegral(),
15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 first_time_changes->ToIntegral());
15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // It's possible to hoist transition from the current loop loop only if
15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // they dominate all of the successor blocks in the same loop and there
15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // are not any instructions that have Changes/DependsOn that intervene
15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // between it and the beginning of the loop header.
15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bool in_nested_loop = block != loop_header &&
15933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ((block->parent_loop_header() != loop_header) ||
15943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             block->IsLoopHeader());
15953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        can_hoist = !in_nested_loop &&
15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            block->IsLoopSuccessorDominator() &&
15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            !first_time_depends->ContainsAnyOf(hoist_depends_blockers) &&
15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            !first_time_changes->ContainsAnyOf(hoist_change_blockers);
1599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
16013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (can_hoist) {
16023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bool inputs_loop_invariant = true;
16033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for (int i = 0; i < instr->OperandCount(); ++i) {
16043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) {
16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            inputs_loop_invariant = false;
16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
16073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (inputs_loop_invariant && ShouldMove(instr, loop_header)) {
16103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          TraceGVN("Hoisting loop invariant instruction %d\n", instr->id());
16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Move the instruction out of the loop.
16123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          instr->Unlink();
16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          instr->InsertBefore(pre_header->end());
16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (instr->HasSideEffects()) removed_side_effects_ = true;
16153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          hoisted = true;
16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
1617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!hoisted) {
16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // If an instruction is not hoisted, we have to account for its side
16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // effects when hoisting later HTransitionElementsKind instructions.
16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      first_time_depends->Add(instr->DependsOnFlags());
16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      first_time_changes->Add(instr->ChangesFlags());
16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = next;
1626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
16291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1630e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool HGlobalValueNumberer::AllowCodeMotion() {
1631e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
1632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
1636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                      HBasicBlock* loop_header) {
16373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // If we've disabled code motion or we're in a block that unconditionally
16383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // deoptimizes, don't move any instructions.
16393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return AllowCodeMotion() && !instr->block()->IsDeoptimizing();
1640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
16433ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochGVNFlagSet HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
1644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* dominator, HBasicBlock* dominated) {
16453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GVNFlagSet side_effects;
1646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < dominated->predecessors()->length(); ++i) {
1647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* block = dominated->predecessors()->at(i);
1648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (dominator->block_id() < block->block_id() &&
1649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        block->block_id() < dominated->block_id() &&
1650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        visited_on_paths_.Add(block->block_id())) {
16513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      side_effects.Add(block_side_effects_[block->block_id()]);
1652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (block->IsLoopHeader()) {
16533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        side_effects.Add(loop_side_effects_[block->block_id()]);
1654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
16553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock(
16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          dominator, block));
1657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return side_effects;
1660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
1664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TraceGVN("Analyzing block B%d%s\n",
1665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           block->block_id(),
1666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           block->IsLoopHeader() ? " (loop header)" : "");
1667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If this is a loop header kill everything killed by the loop.
1669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->IsLoopHeader()) {
1670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    map->Kill(loop_side_effects_[block->block_id()]);
1671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Go through all instructions of the current block.
1674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = block->first();
1675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (instr != NULL) {
1676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* next = instr->next();
16773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GVNFlagSet flags = instr->ChangesFlags();
16783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!flags.IsEmpty()) {
1679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Clear all instructions in the map that are affected by side effects.
1680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      map->Kill(flags);
1681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TraceGVN("Instruction %d kills\n", instr->id());
16823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
16833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->CheckFlag(HValue::kUseGVN)) {
16843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(!instr->HasObservableSideEffects());
1685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* other = map->Lookup(instr);
1686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (other != NULL) {
1687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(instr->Equals(other) && other->Equals(instr));
1688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        TraceGVN("Replacing value %d (%s) with value %d (%s)\n",
1689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 instr->id(),
1690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 instr->Mnemonic(),
1691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 other->id(),
1692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 other->Mnemonic());
16933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (instr->HasSideEffects()) removed_side_effects_ = true;
1694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        instr->DeleteAndReplaceWith(other);
1695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
1696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        map->Add(instr);
1697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = next;
1700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Recursively continue analysis for all immediately dominated blocks.
1703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = block->dominated_blocks()->length();
1704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; ++i) {
1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* dominated = block->dominated_blocks()->at(i);
1706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // No need to copy the map for the last child in the dominator tree.
17078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone());
1708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Kill everything killed on any path between this block and the
1710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // dominated block.
1711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // We don't have to traverse these paths if the value map is
1712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // already empty.
1713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // If the range of block ids (block_id, dominated_id) is empty
1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // there are no such paths.
1715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!successor_map->IsEmpty() &&
1716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        block->block_id() + 1 < dominated->block_id()) {
1717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      visited_on_paths_.Clear();
1718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      successor_map->Kill(CollectSideEffectsOnPathsToDominatedBlock(block,
1719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                                    dominated));
1720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AnalyzeBlock(dominated, successor_map);
1722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HInferRepresentation BASE_EMBEDDED {
1727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
1728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit HInferRepresentation(HGraph* graph)
17293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : graph_(graph),
17303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        worklist_(8),
17313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        in_worklist_(graph->GetMaximumValueID(), graph->zone()) { }
1732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze();
1734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
1736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation TryChange(HValue* current);
1737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AddToWorklist(HValue* current);
1738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferBasedOnInputs(HValue* current);
1739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AddDependantsToWorklist(HValue* current);
1740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferBasedOnUses(HValue* current);
1741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
17428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Zone* zone() { return graph_->zone(); }
17438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
1745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HValue*> worklist_;
1746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BitVector in_worklist_;
1747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::AddToWorklist(HValue* current) {
1751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (current->representation().IsSpecialization()) return;
1752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return;
1753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (in_worklist_.Contains(current->id())) return;
1754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  worklist_.Add(current);
1755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  in_worklist_.Add(current->id());
1756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This method tries to specialize the representation type of the value
1760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// given as a parameter. The value is asked to infer its representation type
1761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// based on its inputs. If the inferred type is more specialized, then this
1762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// becomes the new representation type of the node.
1763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::InferBasedOnInputs(HValue* current) {
1764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation r = current->representation();
1765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (r.IsSpecialization()) return;
1766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation));
1767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation inferred = current->InferredRepresentation();
1768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (inferred.IsSpecialization()) {
17693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_trace_representation) {
17703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrintF("Changing #%d representation %s -> %s based on inputs\n",
17713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             current->id(),
17723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             r.Mnemonic(),
17733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             inferred.Mnemonic());
17743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current->ChangeRepresentation(inferred);
1776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddDependantsToWorklist(current);
1777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HInferRepresentation::AddDependantsToWorklist(HValue* value) {
1782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
1783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AddToWorklist(it.value());
1784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < value->OperandCount(); ++i) {
1786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AddToWorklist(value->OperandAt(i));
1787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This method calculates whether specializing the representation of the value
1792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// given as the parameter has a benefit in terms of less necessary type
1793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// conversions. If there is a benefit, then the representation of the value is
1794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// specialized.
1795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HInferRepresentation::InferBasedOnUses(HValue* value) {
1796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Representation r = value->representation();
1797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (r.IsSpecialization() || value->HasNoUses()) return;
1798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(value->CheckFlag(HValue::kFlexibleRepresentation));
1799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Representation new_rep = TryChange(value);
1800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!new_rep.IsNone()) {
1801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!value->representation().Equals(new_rep)) {
18023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (FLAG_trace_representation) {
18033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrintF("Changing #%d representation %s -> %s based on uses\n",
18043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               value->id(),
18053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               r.Mnemonic(),
18063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               new_rep.Mnemonic());
18073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
1808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      value->ChangeRepresentation(new_rep);
1809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      AddDependantsToWorklist(value);
1810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochRepresentation HInferRepresentation::TryChange(HValue* value) {
1816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Array of use counts for each representation.
1817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int use_count[Representation::kNumRepresentations] = { 0 };
1818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
1820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HValue* use = it.value();
1821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Representation rep = use->RequiredInputRepresentation(it.index());
1822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (rep.IsNone()) continue;
1823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (use->IsPhi()) HPhi::cast(use)->AddIndirectUsesTo(&use_count[0]);
18243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    use_count[rep.kind()] += use->LoopWeight();
1825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int tagged_count = use_count[Representation::kTagged];
1827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int double_count = use_count[Representation::kDouble];
1828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int int32_count = use_count[Representation::kInteger32];
1829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int non_tagged_count = double_count + int32_count;
1830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If a non-loop phi has tagged uses, don't convert it to untagged.
1832589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (value->IsPhi() && !value->block()->IsLoopHeader() && tagged_count > 0) {
1833589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return Representation::None();
1834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1836589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Prefer unboxing over boxing, the latter is more expensive.
18373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (tagged_count > non_tagged_count) return Representation::None();
1838589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1839589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Prefer Integer32 over Double, if possible.
1840589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (int32_count > 0 && value->IsConvertibleToInteger()) {
1841589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return Representation::Integer32();
1842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1843589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1844589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (double_count > 0) return Representation::Double();
1845589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Representation::None();
1847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::Analyze() {
18513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HPhase phase("H_Infer representations", graph_);
1852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // (1) Initialize bit vectors and count real uses. Each phi gets a
1854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // bit-vector of length <number of phis>.
1855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<HPhi*>* phi_list = graph_->phi_list();
1856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int phi_count = phi_list->length();
1857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneList<BitVector*> connected_phis(phi_count);
1858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < phi_count; ++i) {
1859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    phi_list->at(i)->InitRealUses(i);
18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    BitVector* connected_set = new(zone()) BitVector(phi_count, graph_->zone());
1861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    connected_set->Add(i);
1862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    connected_phis.Add(connected_set);
1863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // (2) Do a fixed point iteration to find the set of connected phis.  A
1866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // phi is connected to another phi if its value is used either directly or
1867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // indirectly through a transitive closure of the def-use relation.
1868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool change = true;
1869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (change) {
1870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    change = false;
1871589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // We normally have far more "forward edges" than "backward edges",
1872589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // so we terminate faster when we walk backwards.
1873589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    for (int i = phi_count - 1; i >= 0; --i) {
1874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = phi_list->at(i);
1875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
1876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        HValue* use = it.value();
1877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (use->IsPhi()) {
1878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          int id = HPhi::cast(use)->phi_id();
18793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          if (connected_phis[i]->UnionIsChanged(*connected_phis[id]))
18803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            change = true;
1881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1886589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // (3) Use the phi reachability information from step 2 to
1887589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  //     (a) sum up the non-phi use counts of all connected phis.
1888589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  //     (b) push information about values which can't be converted to integer
1889589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  //         without deoptimization through the phi use-def chains, avoiding
1890589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  //         unnecessary deoptimizations later.
1891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < phi_count; ++i) {
1892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = phi_list->at(i);
1893589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    bool cti = phi->AllOperandsConvertibleToInteger();
1894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (BitVector::Iterator it(connected_phis.at(i));
1895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         !it.Done();
1896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         it.Advance()) {
1897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int index = it.Current();
1898589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      HPhi* it_use = phi_list->at(it.Current());
1899589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (index != i) phi->AddNonPhiUsesFrom(it_use);  // Don't count twice!
1900589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (!cti) it_use->set_is_convertible_to_integer(false);
1901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1904589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Initialize work list
1905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < graph_->blocks()->length(); ++i) {
1906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const ZoneList<HPhi*>* phis = block->phis();
1908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < phis->length(); ++j) {
1909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddToWorklist(phis->at(j));
1910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = block->first();
1913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
1914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddToWorklist(current);
1915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
1916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1919589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Do a fixed point iteration, trying to improve representations
1920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (!worklist_.is_empty()) {
1921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* current = worklist_.RemoveLast();
1922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    in_worklist_.Remove(current->id());
1923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferBasedOnInputs(current);
1924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferBasedOnUses(current);
1925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InitializeInferredTypes() {
19303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HPhase phase("H_Inferring types", this);
1931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  InitializeInferredTypes(0, this->blocks_.length() - 1);
1932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InitializeInferredTypes(int from_inclusive, int to_inclusive) {
1936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = from_inclusive; i <= to_inclusive; ++i) {
1937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = blocks_[i];
1938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const ZoneList<HPhi*>* phis = block->phis();
1940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < phis->length(); j++) {
1941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phis->at(j)->UpdateInferredType();
1942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = block->first();
1945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
1946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current->UpdateInferredType();
1947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
1948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
1951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* last_back_edge =
1952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          block->loop_information()->GetLastBackEdge();
1953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InitializeInferredTypes(i + 1, last_back_edge->block_id());
1954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Skip all blocks already processed by the recursive call.
1955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      i = last_back_edge->block_id();
1956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Update phis of the loop header now after the whole loop body is
1957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // guaranteed to be processed.
1958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ZoneList<HValue*> worklist(block->phis()->length());
1959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < block->phis()->length(); ++j) {
1960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        worklist.Add(block->phis()->at(j));
1961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InferTypes(&worklist);
1963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) {
1969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* current = value;
1970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (current != NULL) {
1971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (visited->Contains(current->id())) return;
1972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // For phis, we must propagate the check to all of its inputs.
1974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->IsPhi()) {
1975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      visited->Add(current->id());
1976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = HPhi::cast(current);
1977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int i = 0; i < phi->OperandCount(); ++i) {
1978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PropagateMinusZeroChecks(phi->OperandAt(i), visited);
1979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
1981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // For multiplication and division, we must propagate to the left and
1984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // the right side.
1985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->IsMul()) {
1986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HMul* mul = HMul::cast(current);
1987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      mul->EnsureAndPropagateNotMinusZero(visited);
1988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(mul->left(), visited);
1989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(mul->right(), visited);
1990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (current->IsDiv()) {
1991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HDiv* div = HDiv::cast(current);
1992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      div->EnsureAndPropagateNotMinusZero(visited);
1993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(div->left(), visited);
1994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(div->right(), visited);
1995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current = current->EnsureAndPropagateNotMinusZero(visited);
1998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChangeForUse(HValue* value,
2003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              HValue* use_value,
2004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              int use_index,
2005e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              Representation to) {
2006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Insert the representation change right before its use. For phi-uses we
2007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // insert at the end of the corresponding predecessor.
20081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  HInstruction* next = NULL;
2009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (use_value->IsPhi()) {
2010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    next = use_value->block()->predecessors()->at(use_index)->end();
20111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
2012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    next = HInstruction::cast(use_value);
2013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // For constants we try to make the representation change at compile
2016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // time. When a representation change is not possible without loss of
2017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // information we treat constants like normal instructions and insert the
2018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // change instructions for them.
2019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* new_value = NULL;
2020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32);
2021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool deoptimize_on_undefined =
2022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      use_value->CheckFlag(HValue::kDeoptimizeOnUndefined);
2023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (value->IsConstant()) {
2024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HConstant* constant = HConstant::cast(value);
2025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Try to create a new copy of the constant with the new representation.
2026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_value = is_truncating
2027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ? constant->CopyToTruncatedInt32()
2028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        : constant->CopyToRepresentation(to);
2029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (new_value == NULL) {
20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    new_value = new(zone()) HChange(value, to,
20337d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch                                    is_truncating, deoptimize_on_undefined);
2034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  new_value->InsertBefore(next);
2037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  use_value->SetOperandAt(use_index, new_value);
2038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraph::InsertRepresentationChangesForValue(HValue* value) {
2042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Representation r = value->representation();
2043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (r.IsNone()) return;
2044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (value->HasNoUses()) return;
2045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
2047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HValue* use_value = it.value();
2048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int use_index = it.index();
2049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Representation req = use_value->RequiredInputRepresentation(use_index);
2050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (req.IsNone() || req.Equals(r)) continue;
2051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    InsertRepresentationChangeForUse(value, use_value, use_index, req);
2052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (value->HasNoUses()) {
2054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(value->IsConstant());
2055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value->DeleteAndReplaceWith(NULL);
2056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // The only purpose of a HForceRepresentation is to represent the value
2059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // after the (possible) HChange instruction.  We make it disappear.
2060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (value->IsForceRepresentation()) {
2061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value());
2062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChanges() {
20673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HPhase phase("H_Representation changes", this);
2068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Compute truncation flag for phis: Initially assume that all
2070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // int32-phis allow truncation and iteratively remove the ones that
2071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // are used in an operation that does not allow a truncating
2072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // conversion.
2073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(fschneider): Replace this with a worklist-based iteration.
2074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < phi_list()->length(); i++) {
2075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = phi_list()->at(i);
2076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (phi->representation().IsInteger32()) {
2077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->SetFlag(HValue::kTruncatingToInt32);
2078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool change = true;
2081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (change) {
2082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    change = false;
2083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < phi_list()->length(); i++) {
2084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = phi_list()->at(i);
2085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue;
20863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!phi->CheckUsesForFlag(HValue::kTruncatingToInt32)) {
20873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        phi->ClearFlag(HValue::kTruncatingToInt32);
20883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        change = true;
2089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
2090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); ++i) {
2094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Process phi instructions first.
2095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    const ZoneList<HPhi*>* phis = blocks_[i]->phis();
2096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (int j = 0; j < phis->length(); j++) {
2097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      InsertRepresentationChangesForValue(phis->at(j));
2098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Process normal instructions.
2101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = blocks_[i]->first();
2102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
2103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      InsertRepresentationChangesForValue(current);
2104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
2105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
21107d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdochvoid HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) {
21117d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  if (phi->CheckFlag(HValue::kDeoptimizeOnUndefined)) return;
21127d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  phi->SetFlag(HValue::kDeoptimizeOnUndefined);
21137d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  for (int i = 0; i < phi->OperandCount(); ++i) {
21147d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    HValue* input = phi->OperandAt(i);
21157d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    if (input->IsPhi()) {
21167d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch      RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input));
21177d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    }
21187d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  }
21197d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch}
21207d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch
21217d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch
21227d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdochvoid HGraph::MarkDeoptimizeOnUndefined() {
21233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HPhase phase("H_MarkDeoptimizeOnUndefined", this);
21247d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // Compute DeoptimizeOnUndefined flag for phis.
21257d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // Any phi that can reach a use with DeoptimizeOnUndefined set must
21263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have DeoptimizeOnUndefined set.  Currently only HCompareIDAndBranch, with
21277d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // double input representation, has this flag set.
21287d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // The flag is used by HChange tagged->double, which must deoptimize
21297d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // if one of its uses has this flag set.
21307d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  for (int i = 0; i < phi_list()->length(); i++) {
21317d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    HPhi* phi = phi_list()->at(i);
21327d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    if (phi->representation().IsDouble()) {
2133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
2134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (it.value()->CheckFlag(HValue::kDeoptimizeOnUndefined)) {
21357d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch          RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
21367d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch          break;
21377d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch        }
21387d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch      }
21397d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    }
21407d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  }
21417d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch}
21427d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch
21437d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch
21441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid HGraph::ComputeMinusZeroChecks() {
21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BitVector visited(GetMaximumValueID(), zone());
21461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = 0; i < blocks_.length(); ++i) {
21471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    for (HInstruction* current = blocks_[i]->first();
21481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block         current != NULL;
21491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block         current = current->next()) {
21501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (current->IsChange()) {
21511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        HChange* change = HChange::cast(current);
21521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // Propagate flags for negative zero checks upwards from conversions
21531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // int32-to-tagged and int32-to-double.
21541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Representation from = change->value()->representation();
21551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ASSERT(from.Equals(change->from()));
21561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if (from.IsInteger32()) {
21571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          ASSERT(change->to().IsTagged() || change->to().IsDouble());
21581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          ASSERT(visited.IsEmpty());
21591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          PropagateMinusZeroChecks(change->value(), &visited);
21601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          visited.Clear();
21611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        }
21621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
21631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
21641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
21651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
21661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
21671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Implementation of utility class to encapsulate the translation state for
2169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// a (possibly inlined) function.
2170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochFunctionState::FunctionState(HGraphBuilder* owner,
2171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                             CompilationInfo* info,
21723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             TypeFeedbackOracle* oracle,
21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             ReturnHandlingFlag return_handling)
2174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    : owner_(owner),
2175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      compilation_info_(info),
2176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      oracle_(oracle),
2177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      call_context_(NULL),
21783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return_handling_(return_handling),
2179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      function_return_(NULL),
2180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      test_context_(NULL),
2181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      outer_(owner->function_state()) {
2182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (outer_ != NULL) {
2183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // State for an inline function.
2184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (owner->ast_context()->IsTest()) {
2185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
2186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
2187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if_true->MarkAsInlineReturnTarget();
2188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if_false->MarkAsInlineReturnTarget();
21893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Expression* cond = TestContext::cast(owner->ast_context())->condition();
2190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // The AstContext constructor pushed on the context stack.  This newed
2191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // instance is the reason that AstContext can't be BASE_EMBEDDED.
21923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      test_context_ = new TestContext(owner, cond, if_true, if_false);
2193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
2194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      function_return_ = owner->graph()->CreateBasicBlock();
2195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      function_return()->MarkAsInlineReturnTarget();
2196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Set this after possibly allocating a new TestContext above.
2198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    call_context_ = owner->ast_context();
2199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Push on the state stack.
2202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  owner->set_function_state(this);
2203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochFunctionState::~FunctionState() {
2207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  delete test_context_;
2208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  owner_->set_function_state(outer_);
2209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Implementation of utility classes to represent an expression's context in
2213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the AST.
2214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
22158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : owner_(owner),
22168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      kind_(kind),
22178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      outer_(owner->ast_context()),
22188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      for_typeof_(false) {
2219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner->set_ast_context(this);  // Push.
2220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
22213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(owner->environment()->frame_type() == JS_FUNCTION);
22229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  original_length_ = owner->environment()->length();
2223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
2224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAstContext::~AstContext() {
2228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner_->set_ast_context(outer_);  // Pop.
2229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochEffectContext::~EffectContext() {
2233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(owner()->HasStackOverflow() ||
2234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         owner()->current_block() == NULL ||
22353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         (owner()->environment()->length() == original_length_ &&
22363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          owner()->environment()->frame_type() == JS_FUNCTION));
2237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochValueContext::~ValueContext() {
2241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(owner()->HasStackOverflow() ||
2242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         owner()->current_block() == NULL ||
22433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         (owner()->environment()->length() == original_length_ + 1 &&
22443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          owner()->environment()->frame_type() == JS_FUNCTION));
2245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid EffectContext::ReturnValue(HValue* value) {
2249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The value is simply ignored.
2250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid ValueContext::ReturnValue(HValue* value) {
2254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The value is tracked in the bailout environment, and communicated
2255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // through the environment as the result of the expression.
2256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) {
2257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    owner()->Bailout("bad value context for arguments value");
2258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->Push(value);
2260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::ReturnValue(HValue* value) {
2264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BuildBranch(value);
2265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) {
22693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(!instr->IsControlInstruction());
2270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->AddInstruction(instr);
22713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id);
2272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid EffectContext::ReturnControl(HControlInstruction* instr, int ast_id) {
22763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!instr->HasObservableSideEffects());
22773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
22783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
22793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  instr->SetSuccessorAt(0, empty_true);
22803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  instr->SetSuccessorAt(1, empty_false);
22813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->current_block()->Finish(instr);
22823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
22833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->set_current_block(join);
22843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
22853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
22863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) {
22883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(!instr->IsControlInstruction());
2289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
22903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return owner()->Bailout("bad value context for arguments object value");
2291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->AddInstruction(instr);
2293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->Push(instr);
22943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id);
2295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid ValueContext::ReturnControl(HControlInstruction* instr, int ast_id) {
22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!instr->HasObservableSideEffects());
23003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
23013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return owner()->Bailout("bad value context for arguments object value");
23023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
23033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
23043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
23053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  instr->SetSuccessorAt(0, materialize_true);
23063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  instr->SetSuccessorAt(1, materialize_false);
23073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->current_block()->Finish(instr);
23083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->set_current_block(materialize_true);
23093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->Push(owner()->graph()->GetConstantTrue());
23103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->set_current_block(materialize_false);
23113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->Push(owner()->graph()->GetConstantFalse());
23123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* join =
23133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    owner()->CreateJoin(materialize_true, materialize_false, ast_id);
23143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->set_current_block(join);
23153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
23163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
23173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::ReturnInstruction(HInstruction* instr, int ast_id) {
23193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(!instr->IsControlInstruction());
2320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraphBuilder* builder = owner();
2321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  builder->AddInstruction(instr);
2322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We expect a simulate after every expression with side effects, though
2323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // this one isn't actually needed (and wouldn't work if it were targeted).
23243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->HasObservableSideEffects()) {
2325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    builder->Push(instr);
2326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    builder->AddSimulate(ast_id);
2327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    builder->Pop();
2328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BuildBranch(instr);
2330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
23333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid TestContext::ReturnControl(HControlInstruction* instr, int ast_id) {
23343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!instr->HasObservableSideEffects());
23353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
23363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
23373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  instr->SetSuccessorAt(0, empty_true);
23383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  instr->SetSuccessorAt(1, empty_false);
23393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->current_block()->Finish(instr);
23403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  empty_true->Goto(if_true(), owner()->function_state()->drop_extra());
23413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  empty_false->Goto(if_false(), owner()->function_state()->drop_extra());
23423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  owner()->set_current_block(NULL);
23433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
23443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
23453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::BuildBranch(HValue* value) {
2347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We expect the graph to be in edge-split form: there is no edge that
2348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // connects a branch node to a join node.  We conservatively ensure that
2349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // property by always adding an empty block on the outgoing edges of this
2350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // branch.
2351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraphBuilder* builder = owner();
23523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
2353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    builder->Bailout("arguments object value in a test context");
2354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
235769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  unsigned test_id = condition()->test_id();
235869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ToBooleanStub::Types expected(builder->oracle()->ToBooleanTypes(test_id));
235969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected);
2360e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  builder->current_block()->Finish(test);
2361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
23623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  empty_true->Goto(if_true(), owner()->function_state()->drop_extra());
23633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  empty_false->Goto(if_false(), owner()->function_state()->drop_extra());
2364e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  builder->set_current_block(NULL);
2365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// HGraphBuilder infrastructure for bailing out and checking bailouts.
2369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define CHECK_BAILOUT(call)                     \
2370053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  do {                                          \
2371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    call;                                       \
2372053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    if (HasStackOverflow()) return;             \
2373053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  } while (false)
2374053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
2375053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
2376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define CHECK_ALIVE(call)                                       \
2377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  do {                                                          \
2378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    call;                                                       \
2379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (HasStackOverflow() || current_block() == NULL) return;  \
2380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } while (false)
2381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::Bailout(const char* reason) {
2384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_bailout) {
2385589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SmartArrayPointer<char> name(
2386589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        info()->shared_info()->DebugName()->ToCString());
2387e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *name, reason);
2388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetStackOverflow();
2390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForEffect(Expression* expr) {
2394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EffectContext for_effect(this);
2395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Visit(expr);
2396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitForValue(Expression* expr, ArgumentsAllowedFlag flag) {
2400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ValueContext for_value(this, flag);
2401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Visit(expr);
2402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
24058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid HGraphBuilder::VisitForTypeOf(Expression* expr) {
2406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
24078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  for_value.set_for_typeof(true);
24088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Visit(expr);
24098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
24108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
24118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
24128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForControl(Expression* expr,
2414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    HBasicBlock* true_block,
2415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    HBasicBlock* false_block) {
24163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  TestContext for_test(this, expr, true_block, false_block);
2417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Visit(expr);
2418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
24213fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHValue* HGraphBuilder::VisitArgument(Expression* expr) {
24223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  VisitForValue(expr);
24233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (HasStackOverflow() || current_block() == NULL) return NULL;
24243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* value = Pop();
24253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Push(AddInstruction(new(zone()) HPushArgument(value)));
24263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return value;
2427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) {
2431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < arguments->length(); i++) {
2432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitArgument(arguments->at(i)));
2433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) {
2438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < exprs->length(); ++i) {
2439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(exprs->at(i)));
2440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2443e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHGraph* HGraphBuilder::CreateGraph() {
24458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  graph_ = new(zone()) HGraph(info());
244644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info());
2447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
24493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HPhase phase("H_Block building");
245044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    current_block_ = graph()->entry_block();
2451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Scope* scope = info()->scope();
2453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (scope->HasIllegalRedeclaration()) {
2454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Bailout("function with illegal redeclaration");
2455e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      return NULL;
2456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
24573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (scope->calls_eval()) {
24583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Bailout("function calls eval");
24593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return NULL;
24603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
24613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SetUpScope(scope);
2462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Add an edge to the body entry.  This is warty: the graph's start
2464e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // environment will be used by the Lithium translation as the initial
2465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // environment on graph entry, but it has now been mutated by the
2466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Hydrogen translation of the instructions in the start block.  This
2467e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // environment uses values which have not been defined yet.  These
2468e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Hydrogen instructions will then be replayed by the Lithium
2469e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // translation, so they cannot have an environment effect.  The edge to
2470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // the body's entry block (along with some special logic for the start
2471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // block in HInstruction::InsertAfter) seals the start block from
2472e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // getting unwanted instructions inserted.
2473e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    //
2474e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // TODO(kmillikin): Fix this.  Stop mutating the initial environment.
2475e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Make the Hydrogen instructions in the initial block into Hydrogen
2476e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // values (but not instructions), present in the initial environment and
2477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // not replayed by the Lithium translation.
2478e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HEnvironment* initial_env = environment()->CopyWithoutHistory();
2479e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* body_entry = CreateBasicBlock(initial_env);
2480e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    current_block()->Goto(body_entry);
24818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    body_entry->SetJoinId(AstNode::kFunctionEntryId);
2482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(body_entry);
2483589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2484589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Handle implicit declaration of the function name in named function
2485589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // expressions before other declarations.
2486589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (scope->is_function_scope() && scope->function() != NULL) {
24873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HandleDeclaration(scope->function(), CONST, NULL, NULL);
2488589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
2489589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    VisitDeclarations(scope->declarations());
2490589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    AddSimulate(AstNode::kDeclarationsId);
2491589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2492589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    HValue* context = environment()->LookupContext();
2493589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    AddInstruction(
2494589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry));
2495589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    VisitStatements(info()->function()->body());
2497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (HasStackOverflow()) return NULL;
2498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2499e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (current_block() != NULL) {
25008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined());
2501e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      current_block()->FinishExit(instr);
2502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(NULL);
2503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  graph()->OrderBlocks();
2507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  graph()->AssignDominators();
25083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
25103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do a full verify after building the graph and computing dominators.
25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  graph()->Verify(true);
25123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
251469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  graph()->PropagateDeoptimizingMark();
25153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!graph()->CheckConstPhiUses()) {
25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Bailout("Unsupported phi use of const variable");
25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return NULL;
25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2519592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  graph()->EliminateRedundantPhis();
25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!graph()->CheckArgumentsPhiUses()) {
25213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Bailout("Unsupported phi use of arguments");
2522589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return NULL;
2523589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
2524592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis();
25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  graph()->CollectPhis();
25263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (graph()->has_osr_loop_entry()) {
25283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const ZoneList<HPhi*>* phis = graph()->osr_loop_entry()->phis();
25293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int j = 0; j < phis->length(); j++) {
25303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HPhi* phi = phis->at(j);
25313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      graph()->osr_values()->at(phi->merged_index())->set_incoming_value(phi);
25323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
25335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
25345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
2535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HInferRepresentation rep(graph());
2536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  rep.Analyze();
2537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
25387d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  graph()->MarkDeoptimizeOnUndefined();
2539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  graph()->InsertRepresentationChanges();
2540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
254169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  graph()->InitializeInferredTypes();
254269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  graph()->Canonicalize();
2543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Perform common subexpression elimination and loop-invariant code motion.
2545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_use_gvn) {
25463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HPhase phase("H_Global value numbering", graph());
2547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HGlobalValueNumberer gvn(graph(), info());
25483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool removed_side_effects = gvn.Analyze();
25493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Trigger a second analysis pass to further eliminate duplicate values that
25503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // could only be discovered by removing side-effect-generating instructions
25513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // during the first pass.
25523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_smi_only_arrays && removed_side_effects) {
25533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      removed_side_effects = gvn.Analyze();
25543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(!removed_side_effects);
25553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
255869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (FLAG_use_range) {
255969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    HRangeAnalysis rangeAnalysis(graph());
256069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    rangeAnalysis.Analyze();
256169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
256269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  graph()->ComputeMinusZeroChecks();
256369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
256469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Eliminate redundant stack checks on backwards branches.
256569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HStackCheckEliminator sce(graph());
256669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  sce.Process();
256769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
25687d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // Replace the results of check instructions with the original value, if the
25697d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // result is used. This is safe now, since we don't do code motion after this
25707d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // point. It enables better register allocation since the value produced by
25717d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // check instructions is really a copy of the original value.
25727d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  graph()->ReplaceCheckedValues();
25737d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch
2574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return graph();
2575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
25787d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdochvoid HGraph::ReplaceCheckedValues() {
25793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HPhase phase("H_Replace checked values", this);
25807d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  for (int i = 0; i < blocks()->length(); ++i) {
25817d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    HInstruction* instr = blocks()->at(i)->first();
25827d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    while (instr != NULL) {
25837d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch      if (instr->IsBoundsCheck()) {
25847d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch        // Replace all uses of the checked value with the original input.
2585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        ASSERT(instr->UseCount() > 0);
2586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        instr->ReplaceAllUsesWith(HBoundsCheck::cast(instr)->index());
25877d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch      }
25887d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch      instr = instr->next();
25897d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    }
25907d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  }
25917d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch}
25927d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch
25937d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch
2594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
2595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
2596e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->AddInstruction(instr);
2597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
2598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
26013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraphBuilder::AddSimulate(int ast_id) {
2602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
26033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  current_block()->AddSimulate(ast_id);
2604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddPhi(HPhi* instr) {
2608e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
2609e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->AddPhi(instr);
2610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::PushAndAdd(HInstruction* instr) {
2614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Push(instr);
2615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(instr);
2616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
26193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <class Instruction>
26203ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHInstruction* HGraphBuilder::PreProcessCall(Instruction* call) {
26211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int count = call->argument_count();
26221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ZoneList<HValue*> arguments(count);
26231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = 0; i < count; ++i) {
26241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    arguments.Add(Pop());
2625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
26271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  while (!arguments.is_empty()) {
26288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast()));
2629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2630e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return call;
2631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
26343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::SetUpScope(Scope* scope) {
26358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HConstant* undefined_constant = new(zone()) HConstant(
263644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->factory()->undefined_value(), Representation::Tagged());
2637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(undefined_constant);
2638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_->set_undefined_constant(undefined_constant);
2639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
26403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HArgumentsObject* object = new(zone()) HArgumentsObject;
26413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInstruction(object);
26423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  graph()->SetArgumentsObject(object);
26433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Set the initial values of parameters including "this".  "This" has
2645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // parameter index 0.
2646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count());
2647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < environment()->parameter_count(); ++i) {
26498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* parameter = AddInstruction(new(zone()) HParameter(i));
2650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    environment()->Bind(i, parameter);
2651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // First special is HContext.
2654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HInstruction* context = AddInstruction(new(zone()) HContext);
2655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  environment()->BindContext(context);
2656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Initialize specials and locals to undefined.
2658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = environment()->parameter_count() + 1;
2659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       i < environment()->length();
2660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       ++i) {
2661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    environment()->Bind(i, undefined_constant);
2662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Handle the arguments and arguments shadow variables specially (they do
2665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // not have declarations).
2666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (scope->arguments() != NULL) {
26673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!scope->arguments()->IsStackAllocated()) {
2668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return Bailout("context-allocated arguments");
2669e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    environment()->Bind(scope->arguments(),
26723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        graph()->GetArgumentsObject());
26733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
2674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
2678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < statements->length(); i++) {
2679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(Visit(statements->at(i)));
2680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
2685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* b = graph()->CreateBasicBlock();
2686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  b->SetInitialEnvironment(env);
2687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return b;
2688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2691e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
2692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* header = graph()->CreateBasicBlock();
2693e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
2694e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  header->SetInitialEnvironment(entry_env);
2695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  header->AttachLoopInformation();
2696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return header;
2697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBlock(Block* stmt) {
2701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
270469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (stmt->block_scope() != NULL) {
270569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return Bailout("ScopedBlock");
270669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
2707e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueInfo break_info(stmt);
2708e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  { BreakAndContinueScope push(&break_info, this);
2709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(VisitStatements(stmt->statements()));
2710e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2711e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* break_block = break_info.break_block();
2712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (break_block != NULL) {
2713e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (current_block() != NULL) current_block()->Goto(break_block);
2714e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    break_block->SetJoinId(stmt->ExitId());
2715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(break_block);
2716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
2721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForEffect(stmt->expression());
2725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
2729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitIfStatement(IfStatement* stmt) {
2736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (stmt->condition()->ToBooleanIsTrue()) {
2740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddSimulate(stmt->ThenId());
2741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Visit(stmt->then_statement());
2742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (stmt->condition()->ToBooleanIsFalse()) {
2743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddSimulate(stmt->ElseId());
2744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Visit(stmt->else_statement());
2745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2746e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* cond_true = graph()->CreateBasicBlock();
2747e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* cond_false = graph()->CreateBasicBlock();
2748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false));
2749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (cond_true->HasPredecessor()) {
2751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cond_true->SetJoinId(stmt->ThenId());
2752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      set_current_block(cond_true);
2753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(Visit(stmt->then_statement()));
2754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cond_true = current_block();
2755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
2756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cond_true = NULL;
2757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
2758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (cond_false->HasPredecessor()) {
2760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cond_false->SetJoinId(stmt->ElseId());
2761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      set_current_block(cond_false);
2762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(Visit(stmt->else_statement()));
2763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cond_false = current_block();
2764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
2765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      cond_false = NULL;
2766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
2767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
27683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId());
2769e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(join);
2770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::BreakAndContinueScope::Get(
2775e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    BreakableStatement* stmt,
27763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    BreakType type,
27773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int* drop_extra) {
27783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *drop_extra = 0;
2779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueScope* current = this;
2780e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while (current != NULL && current->info()->target() != stmt) {
27813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    *drop_extra += current->info()->drop_extra();
2782e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    current = current->next();
2783e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2784e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current != NULL);  // Always found (unless stack is malformed).
27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (type == BREAK) {
27873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    *drop_extra += current->info()->drop_extra();
27883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
27893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2790e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* block = NULL;
2791e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  switch (type) {
2792e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case BREAK:
2793e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      block = current->info()->break_block();
2794e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (block == NULL) {
2795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        block = current->owner()->graph()->CreateBasicBlock();
2796e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        current->info()->set_break_block(block);
2797e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case CONTINUE:
2801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      block = current->info()->continue_block();
2802e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (block == NULL) {
2803e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        block = current->owner()->graph()->CreateBasicBlock();
2804e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        current->info()->set_continue_block(block);
2805e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2806e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
2807e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2808e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2809e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return block;
2810e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2811e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2812e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
2814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
28173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int drop_extra = 0;
28183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* continue_block = break_scope()->Get(stmt->target(),
28193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   CONTINUE,
28203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   &drop_extra);
28213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Drop(drop_extra);
2822e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Goto(continue_block);
2823e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(NULL);
2824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
2828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
28313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int drop_extra = 0;
28323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* break_block = break_scope()->Get(stmt->target(),
28333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                BREAK,
28343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                &drop_extra);
28353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Drop(drop_extra);
2836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Goto(break_block);
2837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(NULL);
2838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
2842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
2845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AstContext* context = call_context();
2846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (context == NULL) {
2847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Not an inlined return, so an actual one.
2848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(stmt->expression()));
2849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* result = environment()->Pop();
28508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    current_block()->FinishExit(new(zone()) HReturn(result));
28513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (function_state()->is_construct()) {
28523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Return from an inlined construct call.  In a test context the return
28533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // value will always evaluate to true, in a value context the return value
28543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // needs to be a JSObject.
28553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (context->IsTest()) {
28563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      TestContext* test = TestContext::cast(context);
28573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK_ALIVE(VisitForEffect(stmt->expression()));
28583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current_block()->Goto(test->if_true(), function_state()->drop_extra());
28593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (context->IsEffect()) {
28603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK_ALIVE(VisitForEffect(stmt->expression()));
28613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current_block()->Goto(function_return(), function_state()->drop_extra());
28623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
28633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(context->IsValue());
28643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK_ALIVE(VisitForValue(stmt->expression()));
28653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HValue* return_value = Pop();
28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HValue* receiver = environment()->Lookup(0);
28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HHasInstanceTypeAndBranch* typecheck =
28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          new(zone()) HHasInstanceTypeAndBranch(return_value,
28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                FIRST_SPEC_OBJECT_TYPE,
28703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                LAST_SPEC_OBJECT_TYPE);
28713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
28723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
28733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      typecheck->SetSuccessorAt(0, if_spec_object);
28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      typecheck->SetSuccessorAt(1, not_spec_object);
28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current_block()->Finish(typecheck);
28763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if_spec_object->AddLeaveInlined(return_value,
28773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      function_return(),
28783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      function_state()->drop_extra());
28793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      not_spec_object->AddLeaveInlined(receiver,
28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       function_return(),
28813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       function_state()->drop_extra());
28823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Return from an inlined function, visit the subexpression in the
2885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // expression context of the call.
2886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (context->IsTest()) {
2887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TestContext* test = TestContext::cast(context);
2888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VisitForControl(stmt->expression(),
2889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      test->if_true(),
2890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      test->if_false());
289144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else if (context->IsEffect()) {
2892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForEffect(stmt->expression()));
28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current_block()->Goto(function_return(), function_state()->drop_extra());
2894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
289544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(context->IsValue());
2896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(stmt->expression()));
28973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HValue* return_value = Pop();
28983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current_block()->AddLeaveInlined(return_value,
28993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       function_return(),
29003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       function_state()->drop_extra());
2901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
29033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  set_current_block(NULL);
2904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
290769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid HGraphBuilder::VisitWithStatement(WithStatement* stmt) {
2908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
291169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return Bailout("WithStatement");
2912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
2916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
2917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
2918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
291944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // We only optimize switch statements with smi-literal smi comparisons,
292044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // with a bounded number of clauses.
292144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kCaseClauseLimit = 128;
292244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ZoneList<CaseClause*>* clauses = stmt->cases();
292344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int clause_count = clauses->length();
292444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (clause_count > kCaseClauseLimit) {
2925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Bailout("SwitchStatement: too many clauses");
292644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
292744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
29283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HValue* context = environment()->LookupContext();
29293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(stmt->tag()));
2931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddSimulate(stmt->EntryId());
293244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HValue* tag_value = Pop();
293344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* first_test_block = current_block();
2934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
29353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SwitchType switch_type = UNKNOWN_SWITCH;
29363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 1. Extract clause type
293844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < clause_count; ++i) {
2939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CaseClause* clause = clauses->at(i);
2940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (clause->is_default()) continue;
29413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (switch_type == UNKNOWN_SWITCH) {
29433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (clause->label()->IsSmiLiteral()) {
29443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        switch_type = SMI_SWITCH;
29453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (clause->label()->IsStringLiteral()) {
29463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        switch_type = STRING_SWITCH;
29473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
29483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return Bailout("SwitchStatement: non-literal switch label");
29493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
29503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if ((switch_type == STRING_SWITCH &&
29513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                !clause->label()->IsStringLiteral()) ||
29523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               (switch_type == SMI_SWITCH &&
29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                !clause->label()->IsSmiLiteral())) {
29543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return Bailout("SwitchStatemnt: mixed label types are not supported");
2955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
29563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2957592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
29583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HUnaryControlInstruction* string_check = NULL;
29593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* not_string_block = NULL;
29603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Test switch's tag value if all clauses are string literals
29623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (switch_type == STRING_SWITCH) {
29633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    string_check = new(zone()) HIsStringAndBranch(tag_value);
29643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    first_test_block = graph()->CreateBasicBlock();
29653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    not_string_block = graph()->CreateBasicBlock();
29663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    string_check->SetSuccessorAt(0, first_test_block);
29683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    string_check->SetSuccessorAt(1, not_string_block);
29693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    current_block()->Finish(string_check);
29703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    set_current_block(first_test_block);
29723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 2. Build all the tests, with dangling true branches
29753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int default_id = AstNode::kNoNumber;
29763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < clause_count; ++i) {
29773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CaseClause* clause = clauses->at(i);
29783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (clause->is_default()) {
29793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      default_id = clause->EntryId();
29803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      continue;
29813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
29823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (switch_type == SMI_SWITCH) {
29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      clause->RecordTypeFeedback(oracle());
2984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
29863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Generate a compare and branch.
2987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(clause->label()));
298844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* label_value = Pop();
29893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
299085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    HBasicBlock* next_test_block = graph()->CreateBasicBlock();
29913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HBasicBlock* body_block = graph()->CreateBasicBlock();
29923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HControlInstruction* compare;
29943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (switch_type == SMI_SWITCH) {
29963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!clause->IsSmiCompare()) {
29973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Finish with deoptimize and add uses of enviroment values to
29983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // account for invisible uses.
29993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        set_current_block(NULL);
30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
30023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
30033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HCompareIDAndBranch* compare_ =
30053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          new(zone()) HCompareIDAndBranch(tag_value,
30063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          label_value,
30073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Token::EQ_STRICT);
30083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      compare_->SetInputRepresentation(Representation::Integer32());
30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      compare = compare_;
30103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
30113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      compare = new(zone()) HStringCompareAndBranch(context, tag_value,
30123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     label_value,
30133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Token::EQ_STRICT);
30143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
30153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    compare->SetSuccessorAt(0, body_block);
30173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    compare->SetSuccessorAt(1, next_test_block);
30183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    current_block()->Finish(compare);
30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
302044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    set_current_block(next_test_block);
302144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
302244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
302344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Save the current block to use for the default or to join with the
302444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // exit.  This block is NULL if we deoptimized.
302544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* last_block = current_block();
302644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
30273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (not_string_block != NULL) {
30283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int join_id = (default_id != AstNode::kNoNumber)
30293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ? default_id
30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : stmt->ExitId();
30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    last_block = CreateJoin(last_block, not_string_block, join_id);
30323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
30333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 3. Loop over the clauses and the linked list of tests in lockstep,
303544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // translating the clause bodies.
303644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* curr_test_block = first_test_block;
303744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* fall_through_block = NULL;
30383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
303944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BreakAndContinueInfo break_info(stmt);
304044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  { BreakAndContinueScope push(&break_info, this);
304144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 0; i < clause_count; ++i) {
304244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      CaseClause* clause = clauses->at(i);
304344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
304444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Identify the block where normal (non-fall-through) control flow
304544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // goes to.
304644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HBasicBlock* normal_block = NULL;
3047053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block      if (clause->is_default()) {
3048053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block        if (last_block != NULL) {
3049053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block          normal_block = last_block;
3050053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block          last_block = NULL;  // Cleared to indicate we've handled it.
3051053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block        }
305244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else if (!curr_test_block->end()->IsDeoptimize()) {
305344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        normal_block = curr_test_block->end()->FirstSuccessor();
305444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        curr_test_block = curr_test_block->end()->SecondSuccessor();
305544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
3056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
305744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Identify a block to emit the body into.
305844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (normal_block == NULL) {
305944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (fall_through_block == NULL) {
306044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          // (a) Unreachable.
306144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (clause->is_default()) {
306244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            continue;  // Might still be reachable clause bodies.
306344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
306444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
306544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
306644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
306744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          // (b) Reachable only as fall through.
306844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          set_current_block(fall_through_block);
3069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
307044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else if (fall_through_block == NULL) {
307144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // (c) Reachable only normally.
307244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        set_current_block(normal_block);
3073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
307444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // (d) Reachable both ways.
307544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        HBasicBlock* join = CreateJoin(fall_through_block,
307644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       normal_block,
307744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       clause->EntryId());
307844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        set_current_block(join);
3079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
3080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(VisitStatements(clause->statements()));
308244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      fall_through_block = current_block();
3083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
308644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Create an up-to-3-way join.  Use the break block if it exists since
308744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // it's already a join block.
308844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* break_block = break_info.break_block();
308944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (break_block == NULL) {
309044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    set_current_block(CreateJoin(fall_through_block,
309144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 last_block,
309244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 stmt->ExitId()));
3093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
309444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (fall_through_block != NULL) fall_through_block->Goto(break_block);
309544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (last_block != NULL) last_block->Goto(break_block);
309644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    break_block->SetJoinId(stmt->ExitId());
309744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    set_current_block(break_block);
3098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
310144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
3103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return statement->OsrEntryId() == info()->osr_ast_id();
3104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
31073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
31083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!HasOsrEntryAt(statement)) return false;
3109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
3111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* osr_entry = graph()->CreateBasicBlock();
3112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* true_value = graph()->GetConstantTrue();
31133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry);
3114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Finish(test);
3115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
3117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  non_osr_entry->Goto(loop_predecessor);
3118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(osr_entry);
3120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int osr_entry_id = statement->OsrEntryId();
31213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int first_expression_index = environment()->first_expression_index();
31223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int length = environment()->length();
31233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<HUnknownOSRValue*>* osr_values =
31243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new(zone()) ZoneList<HUnknownOSRValue*>(length);
31253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < first_expression_index; ++i) {
3127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue;
3128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AddInstruction(osr_value);
3129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    environment()->Bind(i, osr_value);
31303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    osr_values->Add(osr_value);
31315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
31325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
31333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (first_expression_index != length) {
31343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    environment()->Drop(length - first_expression_index);
31353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = first_expression_index; i < length; ++i) {
31363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue;
31373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      AddInstruction(osr_value);
31383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      environment()->Push(osr_value);
31393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      osr_values->Add(osr_value);
31403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
31413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
31423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  graph()->set_osr_values(osr_values);
31443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  AddSimulate(osr_entry_id);
31468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HOsrEntry(osr_entry_id));
3147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HContext* context = new(zone()) HContext;
3148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AddInstruction(context);
3149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  environment()->BindContext(context);
3150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  current_block()->Goto(loop_predecessor);
3151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  loop_predecessor->SetJoinId(statement->EntryId());
3152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_predecessor);
31533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return true;
3154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
31573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraphBuilder::VisitLoopBody(IterationStatement* stmt,
31583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  HBasicBlock* loop_entry,
31593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  BreakAndContinueInfo* break_info) {
31603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BreakAndContinueScope push(break_info, this);
31613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AddSimulate(stmt->StackCheckId());
31623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
31633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HStackCheck* stack_check =
31643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch);
31653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AddInstruction(stack_check);
31663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(loop_entry->IsLoopHeader());
31673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  loop_entry->loop_information()->set_stack_check(stack_check);
31683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_BAILOUT(Visit(stmt->body()));
31693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
31703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
31713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
3173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
31773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool osr_entry = PreProcessOsrEntry(stmt);
3178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
31793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  current_block()->Goto(loop_entry);
3180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_entry);
31813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
3182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueInfo break_info(stmt);
31843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
3185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* body_exit =
3186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      JoinContinue(stmt, current_block(), break_info.continue_block());
3187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_successor = NULL;
3188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
3189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(body_exit);
3190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // The block for a true condition, the actual predecessor block of the
3191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // back edge.
3192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    body_exit = graph()->CreateBasicBlock();
3193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    loop_successor = graph()->CreateBasicBlock();
3194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
3195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (body_exit->HasPredecessor()) {
3196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      body_exit->SetJoinId(stmt->BackEdgeId());
3197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      body_exit = NULL;
3199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (loop_successor->HasPredecessor()) {
3201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      loop_successor->SetJoinId(stmt->ExitId());
3202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      loop_successor = NULL;
3204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_exit = CreateLoop(stmt,
3207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_entry,
3208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      body_exit,
3209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_successor,
3210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      break_info.break_block());
3211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_exit);
3212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
3216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
32203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool osr_entry = PreProcessOsrEntry(stmt);
3221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
32223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  current_block()->Goto(loop_entry);
3223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_entry);
32243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
32253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // If the condition is constant true, do not generate a branch.
3228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_successor = NULL;
3229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!stmt->cond()->ToBooleanIsTrue()) {
3230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* body_entry = graph()->CreateBasicBlock();
3231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    loop_successor = graph()->CreateBasicBlock();
3232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
3233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (body_entry->HasPredecessor()) {
3234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      body_entry->SetJoinId(stmt->BodyId());
3235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      set_current_block(body_entry);
3236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (loop_successor->HasPredecessor()) {
3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      loop_successor->SetJoinId(stmt->ExitId());
3239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      loop_successor = NULL;
3241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
3243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueInfo break_info(stmt);
3245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (current_block() != NULL) {
32463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
3247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* body_exit =
3249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      JoinContinue(stmt, current_block(), break_info.continue_block());
3250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_exit = CreateLoop(stmt,
3251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_entry,
3252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      body_exit,
3253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_successor,
3254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      break_info.break_block());
3255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_exit);
3256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForStatement(ForStatement* stmt) {
3260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (stmt->init() != NULL) {
3264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(Visit(stmt->init()));
3265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(current_block() != NULL);
32673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool osr_entry = PreProcessOsrEntry(stmt);
3268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
32693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  current_block()->Goto(loop_entry);
3270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_entry);
32713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
3272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_successor = NULL;
3274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (stmt->cond() != NULL) {
3275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* body_entry = graph()->CreateBasicBlock();
3276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    loop_successor = graph()->CreateBasicBlock();
3277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
3278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (body_entry->HasPredecessor()) {
3279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      body_entry->SetJoinId(stmt->BodyId());
3280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      set_current_block(body_entry);
3281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (loop_successor->HasPredecessor()) {
3283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      loop_successor->SetJoinId(stmt->ExitId());
3284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      loop_successor = NULL;
3286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  BreakAndContinueInfo break_info(stmt);
3290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (current_block() != NULL) {
32913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
3292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* body_exit =
3294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      JoinContinue(stmt, current_block(), break_info.continue_block());
3295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (stmt->next() != NULL && body_exit != NULL) {
3297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(body_exit);
3298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(Visit(stmt->next()));
3299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    body_exit = current_block();
3300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* loop_exit = CreateLoop(stmt,
3303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_entry,
3304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      body_exit,
3305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      loop_successor,
3306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      break_info.break_block());
3307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(loop_exit);
3308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
3312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
33153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!FLAG_optimize_for_in) {
33173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Bailout("ForInStatement optimization is disabled");
33183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
33193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!oracle()->IsForInFastCase(stmt)) {
33213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Bailout("ForInStatement is not fast case");
33223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
33233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!stmt->each()->IsVariableProxy() ||
33253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
33263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Bailout("ForInStatement with non-local each variable");
33273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
33283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Variable* each_var = stmt->each()->AsVariableProxy()->var();
33303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_ALIVE(VisitForValue(stmt->enumerable()));
33323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HValue* enumerable = Top();  // Leave enumerable at the top.
33333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HInstruction* map = AddInstruction(new(zone()) HForInPrepareMap(
33353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      environment()->LookupContext(), enumerable));
33363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddSimulate(stmt->PrepareId());
33373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HInstruction* array = AddInstruction(
33393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new(zone()) HForInCacheArray(
33403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          enumerable,
33413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          map,
33423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          DescriptorArray::kEnumCacheBridgeCacheIndex));
33433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HInstruction* array_length = AddInstruction(
33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new(zone()) HFixedArrayBaseLength(array));
33463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HInstruction* start_index = AddInstruction(new(zone()) HConstant(
33483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Object>(Smi::FromInt(0)), Representation::Integer32()));
33493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Push(map);
33513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Push(array);
33523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Push(array_length);
33533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Push(start_index);
33543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HInstruction* index_cache = AddInstruction(
33563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new(zone()) HForInCacheArray(
33573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          enumerable,
33583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          map,
33593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          DescriptorArray::kEnumCacheBridgeIndicesCacheIndex));
33603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HForInCacheArray::cast(array)->set_index_cache(
33613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HForInCacheArray::cast(index_cache));
33623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool osr_entry = PreProcessOsrEntry(stmt);
33643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
33653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  current_block()->Goto(loop_entry);
33663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  set_current_block(loop_entry);
33673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
33683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HValue* index = environment()->ExpressionStackAt(0);
33703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HValue* limit = environment()->ExpressionStackAt(1);
33713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that we still have more keys.
33733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HCompareIDAndBranch* compare_index =
33743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new(zone()) HCompareIDAndBranch(index, limit, Token::LT);
33753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  compare_index->SetInputRepresentation(Representation::Integer32());
33763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* loop_body = graph()->CreateBasicBlock();
33783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* loop_successor = graph()->CreateBasicBlock();
33793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  compare_index->SetSuccessorAt(0, loop_body);
33813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  compare_index->SetSuccessorAt(1, loop_successor);
33823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  current_block()->Finish(compare_index);
33833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  set_current_block(loop_successor);
33853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Drop(5);
33863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  set_current_block(loop_body);
33883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HValue* key = AddInstruction(
33903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new(zone()) HLoadKeyedFastElement(
33913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          environment()->ExpressionStackAt(2),  // Enum cache.
33923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          environment()->ExpressionStackAt(0),  // Iteration index.
33933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          HLoadKeyedFastElement::OMIT_HOLE_CHECK));
33943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the expected map still matches that of the enumerable.
33963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If not just deoptimize.
33973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInstruction(new(zone()) HCheckMapValue(
33983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      environment()->ExpressionStackAt(4),
33993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      environment()->ExpressionStackAt(3)));
34003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Bind(each_var, key);
34023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BreakAndContinueInfo break_info(stmt, 5);
34043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
34053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* body_exit =
34073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      JoinContinue(stmt, current_block(), break_info.continue_block());
34083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (body_exit != NULL) {
34103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    set_current_block(body_exit);
34113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HValue* current_index = Pop();
34133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HInstruction* new_index = new(zone()) HAdd(environment()->LookupContext(),
34143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               current_index,
34153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               graph()->GetConstant1());
34163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    new_index->AssumeRepresentation(Representation::Integer32());
34173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PushAndAdd(new_index);
34183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    body_exit = current_block();
34193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
34203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* loop_exit = CreateLoop(stmt,
34223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      loop_entry,
34233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      body_exit,
34243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      loop_successor,
34253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      break_info.break_block());
34263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  set_current_block(loop_exit);
3428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
3432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("TryCatchStatement");
3436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
3440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("TryFinallyStatement");
3444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("DebuggerStatement");
34528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
34538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
34548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
34558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic Handle<SharedFunctionInfo> SearchSharedFunctionInfo(
34568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Code* unoptimized_code, FunctionLiteral* expr) {
34578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int start_position = expr->start_position();
34588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  RelocIterator it(unoptimized_code);
34598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  for (;!it.done(); it.next()) {
34608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    RelocInfo* rinfo = it.rinfo();
34618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue;
34628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Object* obj = rinfo->target_object();
34638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (obj->IsSharedFunctionInfo()) {
34648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
34658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (shared->start_position() == start_position) {
34668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        return Handle<SharedFunctionInfo>(shared);
34678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
34688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
34698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
34708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
34718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return Handle<SharedFunctionInfo>();
3472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
3476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<SharedFunctionInfo> shared_info =
34808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      SearchSharedFunctionInfo(info()->shared_info()->code(),
34818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                               expr);
34828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (shared_info.is_null()) {
34838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    shared_info = Compiler::BuildFunctionInfo(expr, info()->script());
34848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
3485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We also have a stack overflow if the recursive compilation did.
3486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (HasStackOverflow()) return;
34873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
3488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HFunctionLiteral* instr =
34893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure());
34903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
3491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitSharedFunctionInfoLiteral(
3495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SharedFunctionInfoLiteral* expr) {
3496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("SharedFunctionInfoLiteral");
3500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitConditional(Conditional* expr) {
3504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* cond_true = graph()->CreateBasicBlock();
3508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* cond_false = graph()->CreateBasicBlock();
3509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
3510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
351144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Visit the true and false subexpressions in the same AST context as the
351244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // whole expression.
3513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (cond_true->HasPredecessor()) {
3514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cond_true->SetJoinId(expr->ThenId());
3515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(cond_true);
3516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(Visit(expr->then_expression()));
3517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cond_true = current_block();
3518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cond_true = NULL;
3520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (cond_false->HasPredecessor()) {
3523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cond_false->SetJoinId(expr->ElseId());
3524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(cond_false);
3525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(Visit(expr->else_expression()));
3526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cond_false = current_block();
3527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    cond_false = NULL;
3529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
353144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!ast_context()->IsTest()) {
3532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
353344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    set_current_block(join);
3534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (join != NULL && !ast_context()->IsEffect()) {
35353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnValue(Pop());
3536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
353744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
3538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
35418b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochHGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty(
35428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Variable* var, LookupResult* lookup, bool is_store) {
35438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (var->is_this() || !info()->has_global_object()) {
35448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return kUseGeneric;
3545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3546e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<GlobalObject> global(info()->global_object());
3547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  global->Lookup(*var->name(), lookup);
35483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!lookup->IsFound() ||
35498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      lookup->type() != NORMAL ||
35508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      (is_store && lookup->IsReadOnly()) ||
35518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      lookup->holder() != *global) {
35528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return kUseGeneric;
35531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
35548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
35558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return kUseCell;
35561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
35571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35591e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockHValue* HGraphBuilder::BuildContextChainWalk(Variable* var) {
35601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(var->IsContextSlot());
3561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
3562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int length = info()->scope()->ContextChainLength(var->scope());
35631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  while (length-- > 0) {
3564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HInstruction* context_instruction = new(zone()) HOuterContext(context);
3565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AddInstruction(context_instruction);
3566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    context = context_instruction;
35671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
35681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return context;
3569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
3573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3576589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Variable* variable = expr->var();
3577589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (variable->location()) {
3578589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::UNALLOCATED: {
35793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (variable->mode() == LET || variable->mode() == CONST_HARMONY) {
35803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return Bailout("reference to global harmony declared variable");
35813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
35823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Handle known global constants like 'undefined' specially to avoid a
35833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // load from a global cell for them.
35843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Object> constant_value =
35853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          isolate()->factory()->GlobalConstantFor(variable->name());
35863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!constant_value.is_null()) {
35873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HConstant* instr =
35883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            new(zone()) HConstant(constant_value, Representation::Tagged());
35893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return ast_context()->ReturnInstruction(instr, expr->id());
35903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
35913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LookupResult lookup(isolate());
3593589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      GlobalPropertyAccess type =
3594589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          LookupGlobalProperty(variable, &lookup, false);
3595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3596589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (type == kUseCell &&
3597589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          info()->global_object()->IsAccessCheckNeeded()) {
3598589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        type = kUseGeneric;
3599589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
3600589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3601589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (type == kUseCell) {
3602589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Handle<GlobalObject> global(info()->global_object());
3603589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
36043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HLoadGlobalCell* instr =
36053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
3606589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return ast_context()->ReturnInstruction(instr, expr->id());
3607589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else {
3608589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HValue* context = environment()->LookupContext();
3609589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HGlobalObject* global_object = new(zone()) HGlobalObject(context);
3610589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        AddInstruction(global_object);
3611589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HLoadGlobalGeneric* instr =
3612589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            new(zone()) HLoadGlobalGeneric(context,
3613589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                           global_object,
3614589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                           variable->name(),
3615589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                           ast_context()->is_for_typeof());
3616589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        instr->set_position(expr->position());
3617589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return ast_context()->ReturnInstruction(instr, expr->id());
3618589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
36198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
36208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
3621589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::PARAMETER:
3622589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOCAL: {
3623589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      HValue* value = environment()->Lookup(variable);
36243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (value == graph()->GetConstantHole()) {
36253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(variable->mode() == CONST ||
36263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               variable->mode() == CONST_HARMONY ||
36273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               variable->mode() == LET);
36283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return Bailout("reference to uninitialized variable");
3629589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
3630589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return ast_context()->ReturnValue(value);
3631589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
3632589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3633589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::CONTEXT: {
3634589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      HValue* context = BuildContextChainWalk(variable);
36353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable);
36363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnInstruction(instr, expr->id());
3637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3638589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3639589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOOKUP:
3640589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return Bailout("reference to a variable which requires dynamic lookup");
3641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitLiteral(Literal* expr) {
3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
36498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HConstant* instr =
36508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HConstant(expr->handle(), Representation::Tagged());
36513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
3652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
3656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
36593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
36603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context,
36623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                     expr->pattern(),
36638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                     expr->flags(),
36648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                                     expr->literal_index());
36653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
3666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
36693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Determines whether the given array or object literal boilerplate satisfies
36703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// all limits to be considered for fast deep-copying and computes the total
36713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// size of all objects that are part of the graph.
36723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool IsFastLiteral(Handle<JSObject> boilerplate,
36733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          int max_depth,
36743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          int* max_properties,
36753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          int* total_size) {
36763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(max_depth >= 0 && *max_properties >= 0);
36773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (max_depth == 0) return false;
36783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArrayBase> elements(boilerplate->elements());
36803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements->length() > 0 &&
36813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) {
36823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (boilerplate->HasFastDoubleElements()) {
36833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      *total_size += FixedDoubleArray::SizeFor(elements->length());
36843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (boilerplate->HasFastElements()) {
36853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int length = elements->length();
36863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int i = 0; i < length; i++) {
36873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if ((*max_properties)-- == 0) return false;
36883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Handle<Object> value = JSObject::GetElement(boilerplate, i);
36893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (value->IsJSObject()) {
36903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Handle<JSObject> value_object = Handle<JSObject>::cast(value);
36913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (!IsFastLiteral(value_object,
36923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             max_depth - 1,
36933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             max_properties,
36943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             total_size)) {
36953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            return false;
36963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
36973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
36983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
36993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      *total_size += FixedArray::SizeFor(length);
37003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
37013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return false;
37023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
37033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
37043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> properties(boilerplate->properties());
37063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (properties->length() > 0) {
37073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return false;
37083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
37093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int nof = boilerplate->map()->inobject_properties();
37103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < nof; i++) {
37113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if ((*max_properties)-- == 0) return false;
37123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Object> value(boilerplate->InObjectPropertyAt(i));
37133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (value->IsJSObject()) {
37143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Handle<JSObject> value_object = Handle<JSObject>::cast(value);
37153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!IsFastLiteral(value_object,
37163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           max_depth - 1,
37173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           max_properties,
37183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           total_size)) {
37193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          return false;
37203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
37213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
37223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
37233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
37243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *total_size += boilerplate->map()->instance_size();
37263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return true;
37273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
37283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
3731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
37343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSFunction> closure = function_state()->compilation_info()->closure();
3735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
37363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HInstruction* literal;
37373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check whether to use fast or slow deep-copying for boilerplate.
37393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int total_size = 0;
37403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int max_properties = HFastLiteral::kMaxLiteralProperties;
37413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> boilerplate(closure->literals()->get(expr->literal_index()));
37423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (boilerplate->IsJSObject() &&
37433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      IsFastLiteral(Handle<JSObject>::cast(boilerplate),
37443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    HFastLiteral::kMaxLiteralDepth,
37453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    &max_properties,
37463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    &total_size)) {
37473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate);
37483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    literal = new(zone()) HFastLiteral(context,
37493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       boilerplate_object,
37503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       total_size,
37513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       expr->literal_index(),
37523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       expr->depth());
37533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
37543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    literal = new(zone()) HObjectLiteral(context,
37553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         expr->constant_properties(),
37563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         expr->fast_elements(),
37573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         expr->literal_index(),
37583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         expr->depth(),
37593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         expr->has_function());
37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
37613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The object is expected in the bailout environment during computation
3763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // of the property values and is the value of the entire expression.
3764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushAndAdd(literal);
3765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->CalculateEmitStore();
3767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < expr->properties()->length(); i++) {
3769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ObjectLiteral::Property* property = expr->properties()->at(i);
3770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (property->IsCompileTimeValue()) continue;
3771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Literal* key = property->key();
3773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Expression* value = property->value();
3774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    switch (property->kind()) {
3776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
3777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
3778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Fall through.
3779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::COMPUTED:
3780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (key->handle()->IsSymbol()) {
3781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (property->emit_store()) {
37823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            property->RecordTypeFeedback(oracle());
3783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            CHECK_ALIVE(VisitForValue(value));
3784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HValue* value = Pop();
37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            HInstruction* store = BuildStoreNamed(literal, value, property);
37861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            AddInstruction(store);
37873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            if (store->HasObservableSideEffects()) AddSimulate(key->id());
3788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else {
3789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            CHECK_ALIVE(VisitForEffect(value));
3790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
3791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          break;
3792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
3793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Fall through.
3794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::PROTOTYPE:
3795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::SETTER:
3796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::GETTER:
3797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return Bailout("Object literal with complex property");
3798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      default: UNREACHABLE();
3799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
380144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
380244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (expr->has_function()) {
380344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Return the result of the transformation to fast properties
380444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // instead of the original since this operation changes the map
380544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // of the object. This makes sure that the original object won't
380644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // be used by other optimized code before it is transformed
380744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // (e.g. because of code motion).
38088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HToFastProperties* result = new(zone()) HToFastProperties(Pop());
380944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AddInstruction(result);
38103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnValue(result);
381144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
38123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnValue(Pop());
381344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
3814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
3818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
3819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
3820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
3821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<Expression*>* subexprs = expr->values();
3822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = subexprs->length();
38233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
38243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HInstruction* literal;
38253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> literals(environment()->closure()->literals());
38273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> raw_boilerplate(literals->get(expr->literal_index()));
38283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (raw_boilerplate->IsUndefined()) {
38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate(
38313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate(), literals, expr->constant_elements());
38323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (raw_boilerplate.is_null()) {
38333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return Bailout("array boilerplate creation failed");
38343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    literals->set(expr->literal_index(), *raw_boilerplate);
38363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (JSObject::cast(*raw_boilerplate)->elements()->map() ==
38373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate()->heap()->fixed_cow_array_map()) {
38383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->counters()->cow_arrays_created_runtime()->Increment();
38393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
38403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
38413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> boilerplate = Handle<JSObject>::cast(raw_boilerplate);
38433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsKind boilerplate_elements_kind =
38443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Handle<JSObject>::cast(boilerplate)->GetElementsKind();
38453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check whether to use fast or slow deep-copying for boilerplate.
38473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int total_size = 0;
38483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int max_properties = HFastLiteral::kMaxLiteralProperties;
38493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (IsFastLiteral(boilerplate,
38503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    HFastLiteral::kMaxLiteralDepth,
38513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    &max_properties,
38523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    &total_size)) {
38533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    literal = new(zone()) HFastLiteral(context,
38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       boilerplate,
38553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       total_size,
38563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       expr->literal_index(),
38573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       expr->depth());
38583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
38593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    literal = new(zone()) HArrayLiteral(context,
38603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        boilerplate,
38613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        length,
38623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        expr->literal_index(),
38633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        expr->depth());
38643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3865c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
3866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The array is expected in the bailout environment during computation
3867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // of the property values and is the value of the entire expression.
3868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushAndAdd(literal);
3869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HLoadElements* elements = NULL;
3871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; i++) {
3873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Expression* subexpr = subexprs->at(i);
3874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // If the subexpression is a literal or a simple materialized literal it
3875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // is already set in the cloned array.
3876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
3877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(subexpr));
3879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = Pop();
3880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal");
3881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
38823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    elements = new(zone()) HLoadElements(literal);
38833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AddInstruction(elements);
3884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
38858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HValue* key = AddInstruction(
38868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)),
38878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                              Representation::Integer32()));
38883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (boilerplate_elements_kind) {
38903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_SMI_ONLY_ELEMENTS:
38913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Smi-only arrays need a smi check.
38923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddInstruction(new(zone()) HCheckSmi(value));
38933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Fall through.
38943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_ELEMENTS:
38953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddInstruction(new(zone()) HStoreKeyedFastElement(
38963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            elements,
38973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            key,
38983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            value,
38993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            boilerplate_elements_kind));
39003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
39013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_DOUBLE_ELEMENTS:
39023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddInstruction(new(zone()) HStoreKeyedFastDoubleElement(elements,
39033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                                key,
39043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                                value));
39053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
39063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      default:
39073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        UNREACHABLE();
39083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
39093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
39103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddSimulate(expr->GetIdForElement(i));
3912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
39133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnValue(Pop());
3914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Sets the lookup result and returns true if the store can be inlined.
3918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool ComputeStoredField(Handle<Map> type,
3919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               Handle<String> name,
3920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               LookupResult* lookup) {
3921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  type->LookupInDescriptors(NULL, *name, lookup);
39223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!lookup->IsFound()) return false;
3923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup->type() == FIELD) return true;
3924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return (lookup->type() == MAP_TRANSITION) &&
3925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      (type->unused_property_fields() > 0);
3926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic int ComputeStoredFieldIndex(Handle<Map> type,
3930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                   Handle<String> name,
3931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                   LookupResult* lookup) {
3932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(lookup->type() == FIELD || lookup->type() == MAP_TRANSITION);
3933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup->type() == FIELD) {
3934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return lookup->GetLocalFieldIndexFromMap(*type);
3935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Map* transition = lookup->GetTransitionMapFromMap(*type);
3937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return transition->PropertyIndexFor(*name) - type->inobject_properties();
3938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
3943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  Handle<String> name,
3944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  HValue* value,
3945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  Handle<Map> type,
3946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  LookupResult* lookup,
3947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  bool smi_and_map_check) {
3948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (smi_and_map_check) {
39498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(object));
39503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AddInstruction(new(zone()) HCheckMap(object, type, NULL,
39513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         ALLOW_ELEMENT_TRANSITION_MAPS));
3952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = ComputeStoredFieldIndex(type, name, lookup);
3955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_in_object = index < 0;
3956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int offset = index * kPointerSize;
3957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (index < 0) {
3958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Negative property indices are in-object properties, indexed
3959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // from the end of the fixed part of the object.
3960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset += type->instance_size();
3961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset += FixedArray::kHeaderSize;
3963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HStoreNamedField* instr =
39658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HStoreNamedField(object, name, value, is_in_object, offset);
3966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup->type() == MAP_TRANSITION) {
3967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Map> transition(lookup->GetTransitionMapFromMap(*type));
3968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_transition(transition);
3969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // TODO(fschneider): Record the new map type of the object in the IR to
3970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // enable elimination of redundant checks after the transition store.
39713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    instr->SetGVNFlag(kChangesMaps);
3972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
3974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
3978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    Handle<String> name,
3979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    HValue* value) {
3980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
39818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HStoreNamedGeneric(
39828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         context,
39838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         object,
39848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         name,
39858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         value,
39863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         function_strict_mode_flag());
39873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
39883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39903ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
39913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             HValue* value,
39923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             ObjectLiteral::Property* prop) {
39933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Literal* key = prop->key()->AsLiteral();
39943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> name = Handle<String>::cast(key->handle());
39953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!name.is_null());
39963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
39983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Map> type = prop->GetReceiverType();
39993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool is_monomorphic = prop->IsMonomorphic() &&
40003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ComputeStoredField(type, name, &lookup);
40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return is_monomorphic
40033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? BuildStoreNamedField(object, name, value, type, &lookup,
40043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             true)  // Needs smi and map check.
40053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : BuildStoreNamedGeneric(object, name, value);
40065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
40075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
40085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
40095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen MurdochHInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
40105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                             HValue* value,
4011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             Expression* expr) {
4012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = (expr->AsProperty() != NULL)
4013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ? expr->AsProperty()
4014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : expr->AsAssignment()->target()->AsProperty();
4015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Literal* key = prop->key()->AsLiteral();
4016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<String> name = Handle<String>::cast(key->handle());
4017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!name.is_null());
4018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
40193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
402069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  SmallMapList* types = expr->GetReceiverTypes();
4021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_monomorphic = expr->IsMonomorphic() &&
4022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ComputeStoredField(types->first(), name, &lookup);
4023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return is_monomorphic
4025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ? BuildStoreNamedField(object, name, value, types->first(), &lookup,
4026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             true)  // Needs smi and map check.
4027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : BuildStoreNamedGeneric(object, name, value);
4028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
4032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     HValue* object,
4033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     HValue* value,
403469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                                     SmallMapList* types,
4035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Handle<String> name) {
4036e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // TODO(ager): We should recognize when the prototype chains for different
4037e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // maps are identical. In that case we can avoid repeatedly generating the
4038e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // same prototype map checks.
4039e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int count = 0;
4040e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HBasicBlock* join = NULL;
4041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
4042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Map> map = types->at(i);
40433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LookupResult lookup(isolate());
4044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (ComputeStoredField(map, name, &lookup)) {
4045e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (count == 0) {
40468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckNonSmi(object));  // Only needed once.
4047e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        join = graph()->CreateBasicBlock();
4048e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
4049e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ++count;
4050e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* if_true = graph()->CreateBasicBlock();
4051e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HBasicBlock* if_false = graph()->CreateBasicBlock();
40528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HCompareMap* compare =
40538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          new(zone()) HCompareMap(object, map, if_true, if_false);
4054e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      current_block()->Finish(compare);
4055e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4056e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(if_true);
4057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instr =
4058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          BuildStoreNamedField(object, name, value, map, &lookup, false);
4059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr->set_position(expr->position());
4060e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Goto will add the HSimulate for the store.
4061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(instr);
4062e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (!ast_context()->IsEffect()) Push(value);
4063e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      current_block()->Goto(join);
4064e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4065e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(if_false);
4066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4069e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Finish up.  Unconditionally deoptimize if we've handled all the maps we
4070e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // know about and do not want to handle ones we've never seen.  Otherwise
4071e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // use a generic IC.
4072e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
4073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
4074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
40751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
4076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_position(expr->position());
4077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(instr);
4078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4079e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (join != NULL) {
4080e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (!ast_context()->IsEffect()) Push(value);
4081e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      current_block()->Goto(join);
4082e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
4083e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // The HSimulate for the store should not see the stored value in
4084e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // effect contexts (it is not materialized at expr->id() in the
4085e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // unoptimized code).
40863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (instr->HasObservableSideEffects()) {
4087e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (ast_context()->IsEffect()) {
4088e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          AddSimulate(expr->id());
4089e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else {
4090e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          Push(value);
4091e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          AddSimulate(expr->id());
4092e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          Drop(1);
4093e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
4094e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
40953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnValue(value);
40969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
4097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(join != NULL);
4100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  join->SetJoinId(expr->id());
4101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(join);
41023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
4103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
4107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = expr->target()->AsProperty();
4108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(prop != NULL);
4109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->RecordTypeFeedback(oracle());
4110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(prop->obj()));
4111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = NULL;
4113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = NULL;
4114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (prop->key()->IsPropertyName()) {
4116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Named store.
4117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->value()));
4118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    value = Pop();
4119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* object = Pop();
4120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Literal* key = prop->key()->AsLiteral();
4122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = Handle<String>::cast(key->handle());
4123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!name.is_null());
4124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
412569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    SmallMapList* types = expr->GetReceiverTypes();
41263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LookupResult lookup(isolate());
4127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (expr->IsMonomorphic()) {
4129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = BuildStoreNamed(object, value, expr);
4130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (types != NULL && types->length() > 1) {
4132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandlePolymorphicStoreNamedField(expr, object, value, types, name);
4133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
4134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
41361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      instr = BuildStoreNamedGeneric(object, name, value);
4137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Keyed store.
4141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(prop->key()));
4142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->value()));
4143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    value = Pop();
4144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* key = Pop();
4145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* object = Pop();
41463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool has_side_effects = false;
41473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(),
41483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             expr->position(),
41493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             true,  // is_store
41503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             &has_side_effects);
41513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Push(value);
41523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(has_side_effects);  // Stores always have side effects.
41533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddSimulate(expr->AssignmentId());
41543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnValue(Pop());
4155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Push(value);
4157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(expr->position());
4158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(instr);
41593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->HasObservableSideEffects()) AddSimulate(expr->AssignmentId());
41603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnValue(Pop());
4161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Because not every expression has a position and there is not common
4165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// superclass of Assignment and CountOperation, we cannot just pass the
4166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// owning expression instead of position and ast_id separately.
4167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
4168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   HValue* value,
4169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   int position,
4170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   int ast_id) {
41713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
41728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
41738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (type == kUseCell) {
41748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Handle<GlobalObject> global(info()->global_object());
41758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
41763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HInstruction* instr =
41773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails());
41788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr->set_position(position);
41798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(instr);
41803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->HasObservableSideEffects()) AddSimulate(ast_id);
41818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
4182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HValue* context =  environment()->LookupContext();
41838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HGlobalObject* global_object = new(zone()) HGlobalObject(context);
41848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(global_object);
41858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HStoreGlobalGeneric* instr =
41868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        new(zone()) HStoreGlobalGeneric(context,
41878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                        global_object,
41888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                        var->name(),
41898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                        value,
41903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        function_strict_mode_flag());
41918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr->set_position(position);
41928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(instr);
41933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(instr->HasObservableSideEffects());
41943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->HasObservableSideEffects()) AddSimulate(ast_id);
41958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
4196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
4200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Expression* target = expr->target();
4201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = target->AsVariableProxy();
4202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = target->AsProperty();
4203589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(proxy == NULL || prop == NULL);
4204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We have a second position recorded in the FullCodeGenerator to have
4206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // type feedback for the binary operation.
4207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BinaryOperation* operation = expr->binary_operation();
4208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4209589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (proxy != NULL) {
4210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Variable* var = proxy->var();
42113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (var->mode() == LET)  {
42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return Bailout("unsupported let compound assignment");
42133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
42143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(operation));
4216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4217589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    switch (var->location()) {
4218589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::UNALLOCATED:
4219589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HandleGlobalVariableAssignment(var,
4220589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       Top(),
4221589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       expr->position(),
4222589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       expr->AssignmentId());
4223589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        break;
4224589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4225589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::PARAMETER:
4226589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::LOCAL:
42273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (var->mode() == CONST)  {
42283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          return Bailout("unsupported const compound assignment");
42293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
4230589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Bind(var, Top());
4231589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        break;
4232589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4233589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::CONTEXT: {
4234589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // Bail out if we try to mutate a parameter value in a function
4235589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // using the arguments object.  We do not (yet) correctly handle the
4236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // arguments property of the function.
4237589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (info()->scope()->arguments() != NULL) {
4238589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // Parameters will be allocated to context slots.  We have no
4239589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // direct way to detect that the variable is a parameter so we do
4240589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // a linear search of the parameter variables.
4241589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          int count = info()->scope()->num_parameters();
4242589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          for (int i = 0; i < count; ++i) {
4243589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            if (var == info()->scope()->parameter(i)) {
4244589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch              Bailout(
4245589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                  "assignment to parameter, function uses arguments object");
4246589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            }
42473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          }
42483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
4249589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
42503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HStoreContextSlot::Mode mode;
42513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        switch (var->mode()) {
42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          case LET:
42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            mode = HStoreContextSlot::kCheckDeoptimize;
42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            break;
42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          case CONST:
42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            return ast_context()->ReturnValue(Pop());
42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          case CONST_HARMONY:
42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // This case is checked statically so no need to
42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // perform checks here
42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            UNREACHABLE();
42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          default:
42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            mode = HStoreContextSlot::kNoCheck;
42643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4266589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HValue* context = BuildContextChainWalk(var);
4267589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HStoreContextSlot* instr =
42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            new(zone()) HStoreContextSlot(context, var->index(), mode, Top());
4269589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        AddInstruction(instr);
42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (instr->HasObservableSideEffects()) {
42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AddSimulate(expr->AssignmentId());
42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
4273589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        break;
42743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
42753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4276589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::LOOKUP:
4277589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return Bailout("compound assignment to lookup slot");
4278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
42793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnValue(Pop());
4280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (prop != NULL) {
4282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    prop->RecordTypeFeedback(oracle());
4283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (prop->key()->IsPropertyName()) {
4285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Named property.
4286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->obj()));
4287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = Top();
4288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* load = NULL;
4290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (prop->IsMonomorphic()) {
4291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<Map> map = prop->GetReceiverTypes()->first();
4293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamed(obj, prop, map, name);
4294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
4295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamedGeneric(obj, prop);
4296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
4297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(load);
42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (load->HasObservableSideEffects()) AddSimulate(expr->CompoundLoadId());
4299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(expr->value()));
4301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* right = Pop();
4302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* left = Pop();
4303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instr = BuildBinaryOperation(operation, left, right);
4305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(instr);
43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (instr->HasObservableSideEffects()) AddSimulate(operation->id());
4307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* store = BuildStoreNamed(obj, instr, prop);
4309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(store);
4310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Drop the simulated receiver and value.  Return the value.
4311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(2);
4312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(instr);
43133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId());
43143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnValue(Pop());
4315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
4317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Keyed property.
4318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->obj()));
4319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->key()));
4320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = environment()->ExpressionStackAt(1);
4321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* key = environment()->ExpressionStackAt(0);
4322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
43233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bool has_side_effects = false;
43243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HValue* load = HandleKeyedElementAccess(
43253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          obj, key, NULL, prop, expr->CompoundLoadId(), RelocInfo::kNoPosition,
43263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          false,  // is_store
43273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          &has_side_effects);
43283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Push(load);
43293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (has_side_effects) AddSimulate(expr->CompoundLoadId());
43303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(expr->value()));
4333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* right = Pop();
4334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* left = Pop();
4335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instr = BuildBinaryOperation(operation, left, right);
4337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(instr);
43383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (instr->HasObservableSideEffects()) AddSimulate(operation->id());
4339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
43408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      expr->RecordTypeFeedback(oracle());
43413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(),
43423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               RelocInfo::kNoPosition,
43433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               true,  // is_store
43443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               &has_side_effects);
43453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Drop the simulated receiver, key, and value.  Return the value.
4347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(3);
4348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(instr);
43493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(has_side_effects);  // Stores always have side effects.
43503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      AddSimulate(expr->AssignmentId());
43513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnValue(Pop());
4352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Bailout("invalid lhs in compound assignment");
4356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitAssignment(Assignment* expr) {
4361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
4362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
4363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
4364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = expr->target()->AsVariableProxy();
4365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = expr->target()->AsProperty();
4366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(proxy == NULL || prop == NULL);
4367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->is_compound()) {
4369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HandleCompoundAssignment(expr);
4370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
4371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4373589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (prop != NULL) {
4374589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    HandlePropertyAssignment(expr);
4375589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL) {
4376589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Variable* var = proxy->var();
43773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (var->mode() == CONST) {
43793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (expr->op() != Token::INIT_CONST) {
43803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CHECK_ALIVE(VisitForValue(expr->value()));
43813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return ast_context()->ReturnValue(Pop());
43823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
43833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (var->IsStackAllocated()) {
43853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We insert a use of the old value to detect unsupported uses of const
43863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // variables (e.g. initialization inside a loop).
43873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HValue* old_value = environment()->Lookup(var);
43883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddInstruction(new HUseConst(old_value));
43893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
43903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (var->mode() == CONST_HARMONY) {
43913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (expr->op() != Token::INIT_CONST_HARMONY) {
43923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return Bailout("non-initializer assignment to const");
439385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      }
43943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
43953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (proxy->IsArguments()) return Bailout("assignment to arguments");
4397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Handle the assignment.
4399589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    switch (var->location()) {
4400589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::UNALLOCATED:
4401589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        CHECK_ALIVE(VisitForValue(expr->value()));
4402589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HandleGlobalVariableAssignment(var,
4403589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       Top(),
4404589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       expr->position(),
4405589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       expr->AssignmentId());
4406589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return ast_context()->ReturnValue(Pop());
4407589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4408589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::PARAMETER:
4409589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::LOCAL: {
44103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Perform an initialization check for let declared variables
44113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // or parameters.
44123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (var->mode() == LET && expr->op() == Token::ASSIGN) {
44133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          HValue* env_value = environment()->Lookup(var);
44143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (env_value == graph()->GetConstantHole()) {
44153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            return Bailout("assignment to let variable before initialization");
44163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
44173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
4418589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // We do not allow the arguments object to occur in a context where it
4419589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // may escape, but assignments to stack-allocated locals are
4420589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // permitted.
4421589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
4422589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HValue* value = Pop();
4423589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Bind(var, value);
4424589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return ast_context()->ReturnValue(value);
4425589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
44263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::CONTEXT: {
4428589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // Bail out if we try to mutate a parameter value in a function using
4429589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // the arguments object.  We do not (yet) correctly handle the
4430589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // arguments property of the function.
4431589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (info()->scope()->arguments() != NULL) {
4432589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // Parameters will rewrite to context slots.  We have no direct way
4433589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // to detect that the variable is a parameter.
4434589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          int count = info()->scope()->num_parameters();
4435589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          for (int i = 0; i < count; ++i) {
4436589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            if (var == info()->scope()->parameter(i)) {
4437589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch              return Bailout("assignment to parameter in arguments object");
4438589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            }
44393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          }
44403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
44411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4442589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        CHECK_ALIVE(VisitForValue(expr->value()));
44433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HStoreContextSlot::Mode mode;
44443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (expr->op() == Token::ASSIGN) {
44453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          switch (var->mode()) {
44463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case LET:
44473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              mode = HStoreContextSlot::kCheckDeoptimize;
44483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              break;
44493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case CONST:
44503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              return ast_context()->ReturnValue(Pop());
44513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case CONST_HARMONY:
44523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              // This case is checked statically so no need to
44533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              // perform checks here
44543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              UNREACHABLE();
44553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            default:
44563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              mode = HStoreContextSlot::kNoCheck;
44573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
44583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else if (expr->op() == Token::INIT_VAR ||
44593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   expr->op() == Token::INIT_LET ||
44603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   expr->op() == Token::INIT_CONST_HARMONY) {
44613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          mode = HStoreContextSlot::kNoCheck;
44623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
44633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ASSERT(expr->op() == Token::INIT_CONST);
44643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          mode = HStoreContextSlot::kCheckIgnoreAssignment;
44663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
44673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4468589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HValue* context = BuildContextChainWalk(var);
44693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HStoreContextSlot* instr = new(zone()) HStoreContextSlot(
44703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            context, var->index(), mode, Top());
4471589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        AddInstruction(instr);
44723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (instr->HasObservableSideEffects()) {
44733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AddSimulate(expr->AssignmentId());
44743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
4475589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return ast_context()->ReturnValue(Pop());
4476589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
44771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4478589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::LOOKUP:
4479589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return Bailout("assignment to LOOKUP variable");
4480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Bailout("invalid left-hand side in assignment");
4483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThrow(Throw* expr) {
4488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
4489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
4490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
4491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We don't optimize functions with invalid left-hand sides in
4492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // assignments, count operations, or for-in.  Consequently throw can
4493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // currently only occur in an effect context.
4494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(ast_context()->IsEffect());
4495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->exception()));
4496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
44973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
4498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = environment()->Pop();
44993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HThrow* instr = new(zone()) HThrow(context, value);
4500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(expr->position());
45011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(instr);
45021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddSimulate(expr->id());
45038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  current_block()->FinishExit(new(zone()) HAbnormalExit);
4504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  set_current_block(NULL);
4505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
4509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    Property* expr,
4510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    Handle<Map> type,
4511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    LookupResult* lookup,
4512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    bool smi_and_map_check) {
4513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (smi_and_map_check) {
45148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(object));
45153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AddInstruction(new(zone()) HCheckMap(object, type, NULL,
45163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         ALLOW_ELEMENT_TRANSITION_MAPS));
4517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = lookup->GetLocalFieldIndexFromMap(*type);
4520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (index < 0) {
4521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Negative property indices are in-object properties, indexed
4522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // from the end of the fixed part of the object.
4523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int offset = (index * kPointerSize) + type->instance_size();
45248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return new(zone()) HLoadNamedField(object, true, offset);
4525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Non-negative property indices are in the properties array.
4527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
45288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return new(zone()) HLoadNamedField(object, false, offset);
4529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj,
4534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   Property* expr) {
45353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expr->IsUninitialized() && !FLAG_always_opt) {
45363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AddInstruction(new(zone()) HSoftDeoptimize);
45373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    current_block()->MarkAsDeoptimizing();
45383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(expr->key()->IsPropertyName());
4540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Object> name = expr->key()->AsLiteral()->handle();
4541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
45428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HLoadNamedGeneric(context, obj, name);
4543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj,
4547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            Property* expr,
4548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            Handle<Map> map,
4549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            Handle<String> name) {
45503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
4551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  map->LookupInDescriptors(NULL, *name, &lookup);
45523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (lookup.IsFound() && lookup.type() == FIELD) {
4553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return BuildLoadNamedField(obj,
4554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               expr,
4555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               map,
4556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               &lookup,
4557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               true);
45583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (lookup.IsFound() && lookup.type() == CONSTANT_FUNCTION) {
45598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(obj));
45603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AddInstruction(new(zone()) HCheckMap(obj, map, NULL,
45613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         ALLOW_ELEMENT_TRANSITION_MAPS));
4562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map));
45638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return new(zone()) HConstant(function, Representation::Tagged());
4564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return BuildLoadNamedGeneric(obj, expr);
4566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
4571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   HValue* key) {
4572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
45738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HLoadKeyedGeneric(context, object, key);
4574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
45773fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHInstruction* HGraphBuilder::BuildExternalArrayElementAccess(
45783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HValue* external_elements,
45793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HValue* checked_key,
45803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HValue* val,
4581589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind,
45823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool is_store) {
45833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (is_store) {
45843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(val != NULL);
45853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    switch (elements_kind) {
4586589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_PIXEL_ELEMENTS: {
45873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        val = AddInstruction(new(zone()) HClampToUint8(val));
45883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
45893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
4590589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_BYTE_ELEMENTS:
4591589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4592589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_SHORT_ELEMENTS:
4593589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4594589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_INT_ELEMENTS:
4595589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
45963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!val->representation().IsInteger32()) {
45973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          val = AddInstruction(new(zone()) HChange(
45983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              val,
45993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Representation::Integer32(),
46003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              true,  // Truncate to int32.
46013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              false));  // Don't deoptimize undefined (irrelevant here).
46023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
46033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
46043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
4605589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_FLOAT_ELEMENTS:
4606589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case EXTERNAL_DOUBLE_ELEMENTS:
46073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
46083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_SMI_ONLY_ELEMENTS:
4609589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case FAST_ELEMENTS:
4610589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case FAST_DOUBLE_ELEMENTS:
4611589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case DICTIONARY_ELEMENTS:
4612589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case NON_STRICT_ARGUMENTS_ELEMENTS:
46133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        UNREACHABLE();
46143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
46153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
46163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return new(zone()) HStoreKeyedSpecializedArrayElement(
46173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        external_elements, checked_key, val, elements_kind);
46183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
46193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(val == NULL);
46203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return new(zone()) HLoadKeyedSpecializedArrayElement(
46213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        external_elements, checked_key, elements_kind);
46223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
46233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
46243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
46253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
46263ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements,
46273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                    HValue* checked_key,
46283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                    HValue* val,
46293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                    ElementsKind elements_kind,
46303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                    bool is_store) {
46313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_store) {
46323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(val != NULL);
46333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (elements_kind) {
46343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_DOUBLE_ELEMENTS:
46353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return new(zone()) HStoreKeyedFastDoubleElement(
46363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            elements, checked_key, val);
46373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_SMI_ONLY_ELEMENTS:
46383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Smi-only arrays need a smi check.
46393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddInstruction(new(zone()) HCheckSmi(val));
46403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Fall through.
46413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_ELEMENTS:
46423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return new(zone()) HStoreKeyedFastElement(
46433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            elements, checked_key, val, elements_kind);
46443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      default:
46453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        UNREACHABLE();
46463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return NULL;
46473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
46483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
46493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // It's an element load (!is_store).
46503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_DOUBLE_ELEMENTS) {
46513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key);
46523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {  // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS.
46533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return new(zone()) HLoadKeyedFastElement(elements, checked_key);
46543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
46553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
46563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46583fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
46593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                           HValue* key,
46603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                           HValue* val,
46613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                           Handle<Map> map,
46623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                           bool is_store) {
4663592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map));
46643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool fast_smi_only_elements = map->has_fast_smi_only_elements();
46653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool fast_elements = map->has_fast_elements();
466669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
46673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_store && (fast_elements || fast_smi_only_elements)) {
466869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    AddInstruction(new(zone()) HCheckMap(
466969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        elements, isolate()->factory()->fixed_array_map()));
467069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
46719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  HInstruction* length = NULL;
46727d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  HInstruction* checked_key = NULL;
46733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (map->has_external_array_elements()) {
467469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
46753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
46763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HLoadExternalArrayPointer* external_elements =
46773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        new(zone()) HLoadExternalArrayPointer(elements);
46783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(external_elements);
46793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return BuildExternalArrayElementAccess(external_elements, checked_key,
46803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                           val, map->elements_kind(), is_store);
46813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
46823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(fast_smi_only_elements ||
46833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         fast_elements ||
46843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         map->has_fast_double_elements());
46853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (map->instance_type() == JS_ARRAY_TYPE) {
468669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck));
46879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
468869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
46899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
469069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
46913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return BuildFastElementAccess(elements, checked_key, val,
46923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                map->elements_kind(), is_store);
4693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
46963fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
46973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      HValue* key,
46983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      HValue* val,
46993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      Expression* prop,
47003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      int ast_id,
47013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      int position,
47023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      bool is_store,
47033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      bool* has_side_effects) {
47043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  *has_side_effects = false;
47058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckNonSmi(object));
470669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  SmallMapList* maps = prop->GetReceiverTypes();
47073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool todo_external_array = false;
47083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4709589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  static const int kNumElementTypes = kElementsKindCount;
47103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool type_todo[kNumElementTypes];
47113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < kNumElementTypes; ++i) {
47123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    type_todo[i] = false;
47133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
47143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Elements_kind transition support.
47163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MapHandleList transition_target(maps->length());
47173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Collect possible transition targets.
47183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MapHandleList possible_transitioned_maps(maps->length());
4719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  for (int i = 0; i < maps->length(); ++i) {
47203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> map = maps->at(i);
47213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind elements_kind = map->elements_kind();
47223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (elements_kind == FAST_DOUBLE_ELEMENTS ||
47233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        elements_kind == FAST_ELEMENTS) {
47243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      possible_transitioned_maps.Add(map);
47253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
47263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
47273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get transition target for each map (NULL == no transition).
47283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < maps->length(); ++i) {
47293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> map = maps->at(i);
47303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> transitioned_map =
47313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        map->FindTransitionedMap(&possible_transitioned_maps);
47323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    transition_target.Add(transitioned_map);
47333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
47343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int num_untransitionable_maps = 0;
47363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Map> untransitionable_map;
47373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < maps->length(); ++i) {
47383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> map = maps->at(i);
47393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(map->IsMap());
47403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!transition_target.at(i).is_null()) {
47413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      AddInstruction(new(zone()) HTransitionElementsKind(
47423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          object, map, transition_target.at(i)));
47433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
47443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      type_todo[map->elements_kind()] = true;
47453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) {
47463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        todo_external_array = true;
47473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
47483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      num_untransitionable_maps++;
47493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      untransitionable_map = map;
47503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
47513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
47523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If only one map is left after transitioning, handle this case
47543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // monomorphically.
47553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (num_untransitionable_maps == 1) {
47563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HInstruction* instr = NULL;
47573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (untransitionable_map->has_slow_elements_kind()) {
47583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
47593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      : BuildLoadKeyedGeneric(object, key));
47603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
47613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr = AddInstruction(BuildMonomorphicElementAccess(
47623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          object, key, val, untransitionable_map, is_store));
47633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
47643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    *has_side_effects |= instr->HasObservableSideEffects();
47653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    instr->set_position(position);
47663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return is_store ? NULL : instr;
47673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
47683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInstruction(HCheckInstanceType::NewIsSpecObject(object));
47703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HBasicBlock* join = graph()->CreateBasicBlock();
47713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* elements_kind_instr =
47733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      AddInstruction(new(zone()) HElementsKind(object));
477469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HCompareConstantEqAndBranch* elements_kind_branch = NULL;
477569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
47763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HLoadExternalArrayPointer* external_elements = NULL;
47773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* checked_key = NULL;
47783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Generated code assumes that FAST_SMI_ONLY_ELEMENTS, FAST_ELEMENTS,
47803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS are handled before external
47813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // arrays.
47823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
47833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
47843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
47853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
47863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
47873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND;
4788589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch       elements_kind <= LAST_ELEMENTS_KIND;
4789589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch       elements_kind = ElementsKind(elements_kind + 1)) {
47903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // After having handled FAST_ELEMENTS, FAST_SMI_ONLY_ELEMENTS,
47913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS, we need to add some code
47923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // that's executed for all external array cases.
4793589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND ==
4794589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                  LAST_ELEMENTS_KIND);
4795589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND
47963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        && todo_external_array) {
47973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HInstruction* length =
479869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
47993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
48003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      external_elements = new(zone()) HLoadExternalArrayPointer(elements);
48013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      AddInstruction(external_elements);
48023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
48033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (type_todo[elements_kind]) {
48043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HBasicBlock* if_true = graph()->CreateBasicBlock();
48053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HBasicBlock* if_false = graph()->CreateBasicBlock();
480669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      elements_kind_branch = new(zone()) HCompareConstantEqAndBranch(
480769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          elements_kind_instr, elements_kind, Token::EQ_STRICT);
480869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      elements_kind_branch->SetSuccessorAt(0, if_true);
480969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      elements_kind_branch->SetSuccessorAt(1, if_false);
481069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      current_block()->Finish(elements_kind_branch);
48113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
48123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      set_current_block(if_true);
48133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HInstruction* access;
48143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (elements_kind == FAST_SMI_ONLY_ELEMENTS ||
48153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          elements_kind == FAST_ELEMENTS ||
4816589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          elements_kind == FAST_DOUBLE_ELEMENTS) {
48173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (is_store && elements_kind != FAST_DOUBLE_ELEMENTS) {
481869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          AddInstruction(new(zone()) HCheckMap(
481969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              elements, isolate()->factory()->fixed_array_map(),
482069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              elements_kind_branch));
482169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
48223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // TODO(jkummerow): The need for these two blocks could be avoided
48233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // in one of two ways:
48243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // (1) Introduce ElementsKinds for JSArrays that are distinct from
48253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //     those for fast objects.
48263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // (2) Put the common instructions into a third "join" block. This
48273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //     requires additional AST IDs that we can deopt to from inside
48283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //     that join block. They must be added to the Property class (when
48293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //     it's a keyed property) and registered in the full codegen.
48303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
48313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
48323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HHasInstanceTypeAndBranch* typecheck =
48333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE);
48343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        typecheck->SetSuccessorAt(0, if_jsarray);
48353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        typecheck->SetSuccessorAt(1, if_fastobject);
48363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        current_block()->Finish(typecheck);
48373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
48383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        set_current_block(if_jsarray);
48393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HInstruction* length;
48403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck));
48413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
48423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        access = AddInstruction(BuildFastElementAccess(
48433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            elements, checked_key, val, elements_kind, is_store));
48443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!is_store) {
48453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          Push(access);
48463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
48473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *has_side_effects |= access->HasObservableSideEffects();
48493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (position != -1) {
48503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          access->set_position(position);
48513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
48523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if_jsarray->Goto(join);
48533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
48543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        set_current_block(if_fastobject);
485569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
48563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
48573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        access = AddInstruction(BuildFastElementAccess(
48583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            elements, checked_key, val, elements_kind, is_store));
4859589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (elements_kind == DICTIONARY_ELEMENTS) {
48603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (is_store) {
48613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
48623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        } else {
48633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          access = AddInstruction(BuildLoadKeyedGeneric(object, key));
48643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
48653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {  // External array elements.
48663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        access = AddInstruction(BuildExternalArrayElementAccess(
48673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            external_elements, checked_key, val, elements_kind, is_store));
48683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
48693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      *has_side_effects |= access->HasObservableSideEffects();
48703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      access->set_position(position);
48713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (!is_store) {
48723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Push(access);
48733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
48743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      current_block()->Goto(join);
48753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      set_current_block(if_false);
48763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
48773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
48783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
48793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Deopt if none of the cases matched.
48803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
48813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  join->SetJoinId(ast_id);
48823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  set_current_block(join);
48833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return is_store ? NULL : Pop();
48841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
48851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
48861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
48873fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj,
48883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                HValue* key,
48893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                HValue* val,
48903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                Expression* expr,
48913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                int ast_id,
48923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                int position,
48933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                bool is_store,
48943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                bool* has_side_effects) {
48953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(!expr->IsPropertyName());
48963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* instr = NULL;
48973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (expr->IsMonomorphic()) {
48983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> map = expr->GetMonomorphicReceiverType();
48993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (map->has_slow_elements_kind()) {
49003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
49013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       : BuildLoadKeyedGeneric(obj, key);
49023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
49033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      AddInstruction(new(zone()) HCheckNonSmi(obj));
49043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr = BuildMonomorphicElementAccess(obj, key, val, map, is_store);
49053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
49063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else if (expr->GetReceiverTypes() != NULL &&
49073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch             !expr->GetReceiverTypes()->is_empty()) {
49083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return HandlePolymorphicElementAccess(
49093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        obj, key, val, expr, ast_id, position, is_store, has_side_effects);
49103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
49113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (is_store) {
49123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      instr = BuildStoreKeyedGeneric(obj, key, val);
49133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
49143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      instr = BuildLoadKeyedGeneric(obj, key);
49158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
49168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
49173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  instr->set_position(position);
49183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AddInstruction(instr);
49193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *has_side_effects = instr->HasObservableSideEffects();
49203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return instr;
49218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
49228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
49238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
4925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    HValue* key,
4926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    HValue* value) {
4927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
49288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) HStoreKeyedGeneric(
49298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         context,
49308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         object,
49318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         key,
49328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         value,
49333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         function_strict_mode_flag());
4934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryArgumentsAccess(Property* expr) {
4937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = expr->obj()->AsVariableProxy();
4938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (proxy == NULL) return false;
4939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!proxy->var()->IsStackAllocated()) return false;
4940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
4941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
4942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
494442effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // Our implementation of arguments (based on this stack frame or an
494542effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // adapter below it) does not work for inlined functions.
494642effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  if (function_state()->outer() != NULL) {
494742effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch    Bailout("arguments access in inlined function");
494842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch    return true;
494942effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  }
495042effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch
4951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* result = NULL;
4952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->key()->IsPropertyName()) {
4953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
4954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!name->IsEqualTo(CStrVector("length"))) return false;
49558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
49568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    result = new(zone()) HArgumentsLength(elements);
4957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4958e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Push(graph()->GetArgumentsObject());
4959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitForValue(expr->key());
4960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (HasStackOverflow() || current_block() == NULL) return true;
4961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* key = Pop();
4962e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Drop(1);  // Arguments object.
49638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
49648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HInstruction* length = AddInstruction(
49658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        new(zone()) HArgumentsLength(elements));
49667d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    HInstruction* checked_key =
49677d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch        AddInstruction(new(zone()) HBoundsCheck(key, length));
49687d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
4969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, expr->id());
4971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
4972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitProperty(Property* expr) {
4976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
4977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
4978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
4979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->RecordTypeFeedback(oracle());
4980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (TryArgumentsAccess(expr)) return;
4982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->obj()));
4984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = NULL;
49863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expr->AsProperty()->IsArrayLength()) {
4987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* array = Pop();
49888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(array));
498969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    HInstruction* mapcheck =
499069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        AddInstruction(HCheckInstanceType::NewIsJSArray(array));
499169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    instr = new(zone()) HJSArrayLength(array, mapcheck);
49929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
49931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else if (expr->IsStringLength()) {
49941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    HValue* string = Pop();
49958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(string));
4996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AddInstruction(HCheckInstanceType::NewIsString(string));
49978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr = new(zone()) HStringLength(string);
499844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (expr->IsStringAccess()) {
4999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->key()));
500044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* index = Pop();
500144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HValue* string = Pop();
50023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HValue* context = environment()->LookupContext();
50033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HStringCharCodeAt* char_code =
50043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      BuildStringCharCodeAt(context, string, index);
500544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AddInstruction(char_code);
50063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    instr = new(zone()) HStringCharFromCode(context, char_code);
50071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
50089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else if (expr->IsFunctionPrototype()) {
50099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    HValue* function = Pop();
50108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(function));
50118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    instr = new(zone()) HLoadFunctionPrototype(function);
5012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (expr->key()->IsPropertyName()) {
5014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
501569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    SmallMapList* types = expr->GetReceiverTypes();
5016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* obj = Pop();
5018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (expr->IsMonomorphic()) {
5019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = BuildLoadNamed(obj, expr, types->first(), name);
5020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (types != NULL && types->length() > 1) {
50218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      AddInstruction(new(zone()) HCheckNonSmi(obj));
50223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HValue* context = environment()->LookupContext();
50233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      instr = new(zone()) HLoadNamedFieldPolymorphic(context, obj, types, name);
5024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
5025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = BuildLoadNamedGeneric(obj, expr);
5026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
5029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->key()));
5030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* key = Pop();
5032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* obj = Pop();
50333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
50343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool has_side_effects = false;
50353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HValue* load = HandleKeyedElementAccess(
50363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        obj, key, NULL, expr, expr->id(), expr->position(),
50373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        false,  // is_store
50383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        &has_side_effects);
50393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (has_side_effects) {
50403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (ast_context()->IsEffect()) {
50413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AddSimulate(expr->id());
50423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
50433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Push(load);
50443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AddSimulate(expr->id());
50453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Drop(1);
50463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
50473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
50483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnValue(load);
5049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(expr->position());
50513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
5052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddCheckConstantFunction(Call* expr,
5056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             HValue* receiver,
5057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             Handle<Map> receiver_map,
5058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             bool smi_and_map_check) {
5059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Constant functions have the nice property that the map will change if they
5060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // are overwritten.  Therefore it is enough to check the map of the holder and
5061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // its prototypes.
5062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (smi_and_map_check) {
50638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(receiver));
50643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AddInstruction(new(zone()) HCheckMap(receiver, receiver_map, NULL,
50653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         ALLOW_ELEMENT_TRANSITION_MAPS));
5066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!expr->holder().is_null()) {
50688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AddInstruction(new(zone()) HCheckPrototypeMaps(
5069b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        Handle<JSObject>(JSObject::cast(receiver_map->prototype())),
5070b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        expr->holder()));
5071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
5076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                               HValue* receiver,
507769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                               SmallMapList* types,
5078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                               Handle<String> name) {
5079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(ager): We should recognize when the prototype chains for different
5080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // maps are identical. In that case we can avoid repeatedly generating the
5081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // same prototype map checks.
508244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int argument_count = expr->arguments()->length() + 1;  // Includes receiver.
508344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int count = 0;
508444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HBasicBlock* join = NULL;
508544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < types->length() && count < kMaxCallPolymorphism; ++i) {
5086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Map> map = types->at(i);
5087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (expr->ComputeTarget(map, name)) {
508844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (count == 0) {
50898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        // Only needed once.
50908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckNonSmi(receiver));
509144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        join = graph()->CreateBasicBlock();
509244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
509344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ++count;
509444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HBasicBlock* if_true = graph()->CreateBasicBlock();
509544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HBasicBlock* if_false = graph()->CreateBasicBlock();
50968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HCompareMap* compare =
50978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          new(zone()) HCompareMap(receiver, map, if_true, if_false);
509844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      current_block()->Finish(compare);
509944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
510044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      set_current_block(if_true);
5101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddCheckConstantFunction(expr, receiver, map, false);
5102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
5103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF("Trying to inline the polymorphic call to %s\n",
5104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               *name->ToCString());
5105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
51063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (FLAG_polymorphic_inlining && TryInlineCall(expr)) {
5107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Trying to inline will signal that we should bailout from the
5108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // entire compilation by setting stack overflow on the visitor.
5109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (HasStackOverflow()) return;
5110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
5111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        HCallConstantFunction* call =
51128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) HCallConstantFunction(expr->target(), argument_count);
5113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        call->set_position(expr->position());
51141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        PreProcessCall(call);
511544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        AddInstruction(call);
511644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (!ast_context()->IsEffect()) Push(call);
5117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
511844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
511944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (current_block() != NULL) current_block()->Goto(join);
512044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      set_current_block(if_false);
5121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
512444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Finish up.  Unconditionally deoptimize if we've handled all the maps we
512544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // know about and do not want to handle ones we've never seen.  Otherwise
512644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // use a generic IC.
512744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
5128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
512944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
5130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HValue* context = environment()->LookupContext();
51318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count);
5132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    call->set_position(expr->position());
51331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    PreProcessCall(call);
5134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
513544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (join != NULL) {
513644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      AddInstruction(call);
513744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (!ast_context()->IsEffect()) Push(call);
513844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      current_block()->Goto(join);
513944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
51403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnInstruction(call, expr->id());
51419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
5142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
514344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
514444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // We assume that control flow is always live after an expression.  So
514544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // even without predecessors to the join block, we set it as the exit
514644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // block and continue by adding instructions there.
514744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(join != NULL);
514844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (join->HasPredecessor()) {
5149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(join);
515044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    join->SetJoinId(expr->id());
51513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
5152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
5153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(NULL);
515444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
5155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::TraceInline(Handle<JSFunction> target,
5159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Handle<JSFunction> caller,
5160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                const char* reason) {
5161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (FLAG_trace_inlining) {
5162589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SmartArrayPointer<char> target_name =
5163589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        target->shared()->DebugName()->ToCString();
5164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SmartArrayPointer<char> caller_name =
5165589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        caller->shared()->DebugName()->ToCString();
5166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (reason == NULL) {
5167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      PrintF("Inlined %s called from %s.\n", *target_name, *caller_name);
5168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
5169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      PrintF("Did not inline %s called from %s (%s).\n",
5170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch             *target_name, *caller_name, reason);
5171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
5172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
51763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraphBuilder::TryInline(CallKind call_kind,
51773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Handle<JSFunction> target,
51783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              ZoneList<Expression*>* arguments,
51793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              HValue* receiver,
51803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int ast_id,
51813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int return_id,
51823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              ReturnHandlingFlag return_handling) {
5183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!FLAG_use_inlining) return false;
5184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Precondition: call is monomorphic and we have found a target with the
5186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // appropriate arity.
5187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<JSFunction> caller = info()->closure();
5188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<SharedFunctionInfo> target_shared(target->shared());
5189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Do a quick check on source code length to avoid parsing large
5191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // inlining candidates.
51923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if ((FLAG_limit_inlining && target_shared->SourceSize() > kMaxSourceSize)
51933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      || target_shared->SourceSize() > kUnlimitedMaxSourceSize) {
5194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TraceInline(target, caller, "target text too big");
5195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
5196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Target must be inlineable.
5199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!target->IsInlineable()) {
5200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TraceInline(target, caller, "target not inlineable");
5201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return false;
5202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
52033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (target_shared->dont_inline() || target_shared->dont_optimize()) {
52043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    TraceInline(target, caller, "target contains unsupported syntax [early]");
52053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return false;
52063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
52083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int nodes_added = target_shared->ast_node_count();
52093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if ((FLAG_limit_inlining && nodes_added > kMaxInlinedSize) ||
52103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      nodes_added > kUnlimitedMaxInlinedSize) {
52113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    TraceInline(target, caller, "target AST is too large [early]");
52123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return false;
52133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
52143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#if !defined(V8_TARGET_ARCH_IA32)
52163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Target must be able to use caller's context.
5217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompilationInfo* outer_info = info();
5218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (target->context() != outer_info->closure()->context() ||
5219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_info->scope()->contains_with() ||
5220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_info->scope()->num_heap_slots() > 0) {
5221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TraceInline(target, caller, "target requires context change");
5222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
5223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
52243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
52253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
52278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Don't inline deeper than kMaxInliningLevels calls.
5228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* env = environment();
52298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int current_level = 1;
52308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  while (env->outer() != NULL) {
52318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (current_level == Compiler::kMaxInliningLevels) {
5232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      TraceInline(target, caller, "inline depth limit reached");
52338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return false;
52348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
52353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (env->outer()->frame_type() == JS_FUNCTION) {
52363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current_level++;
52373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
52388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    env = env->outer();
5239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
5240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Don't inline recursive functions.
52423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (FunctionState* state = function_state();
52433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       state != NULL;
52443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       state = state->outer()) {
52453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (state->compilation_info()->closure()->shared() == *target_shared) {
52463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      TraceInline(target, caller, "target is recursive");
52473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return false;
52483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
5250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We don't want to add more than a certain number of nodes from inlining.
52523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if ((FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) ||
52533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      inlined_count_ > kUnlimitedMaxInlinedNodes) {
5254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TraceInline(target, caller, "cumulative AST node limit reached");
5255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
5256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Parse and allocate variables.
5259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompilationInfo target_info(target);
52603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!ParserApi::Parse(&target_info, kNoParsingFlags) ||
5261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      !Scope::Analyze(&target_info)) {
526244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (target_info.isolate()->has_pending_exception()) {
5263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Parse or scope error, never optimize this function.
52641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      SetStackOverflow();
52653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      target_shared->DisableOptimization();
52661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
5267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TraceInline(target, caller, "parse failure");
5268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return false;
5269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
5270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
5271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (target_info.scope()->num_heap_slots() > 0) {
5272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TraceInline(target, caller, "target has context-allocated variables");
5273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
5274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  FunctionLiteral* function = target_info.function();
5276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
52773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The following conditions must be checked again after re-parsing, because
52783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // earlier the information might not have been complete due to lazy parsing.
52793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  nodes_added = function->ast_node_count();
52803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if ((FLAG_limit_inlining && nodes_added > kMaxInlinedSize) ||
52813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      nodes_added > kUnlimitedMaxInlinedSize) {
52823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    TraceInline(target, caller, "target AST is too large [late]");
5283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
5284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
52853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AstProperties::Flags* flags(function->flags());
52863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (flags->Contains(kDontInline) || flags->Contains(kDontOptimize)) {
52873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    TraceInline(target, caller, "target contains unsupported syntax [late]");
528885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    return false;
5289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
52913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the function uses the arguments object check that inlining of functions
52923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // with arguments object is enabled and the arguments-variable is
52933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // stack allocated.
52943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (function->scope()->arguments() != NULL) {
52953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!FLAG_inline_arguments) {
52963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      TraceInline(target, caller, "target uses arguments object");
52973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return false;
52983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
52993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!function->scope()->arguments()->IsStackAllocated()) {
53013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      TraceInline(target,
53023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  caller,
53033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  "target uses non-stackallocated arguments object");
53043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return false;
53053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
53063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
53073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // All declarations must be inlineable.
53093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ZoneList<Declaration*>* decls = target_info.scope()->declarations();
53103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int decl_count = decls->length();
53113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < decl_count; ++i) {
53123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!decls->at(i)->IsInlineable()) {
53133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      TraceInline(target, caller, "target has non-trivial declaration");
53143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return false;
53153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
53163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Generate the deoptimization data for the unoptimized version of
5319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the target function if we don't already have it.
5320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!target_shared->has_deoptimization_support()) {
5321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Note that we compile here using the same AST that we will use for
5322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // generating the optimized inline code.
5323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    target_info.EnableDeoptimizationSupport();
5324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (!FullCodeGenerator::MakeCode(&target_info)) {
5325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      TraceInline(target, caller, "could not generate deoptimization info");
5326e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      return false;
5327e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
53283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (target_shared->scope_info() == ScopeInfo::Empty()) {
53293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // The scope info might not have been set if a lazily compiled
53303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // function is inlined before being called for the first time.
53313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<ScopeInfo> target_scope_info =
53323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ScopeInfo::Create(target_info.scope());
53333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      target_shared->set_scope_info(*target_scope_info);
53343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5335e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    target_shared->EnableDeoptimizationSupport(*target_info.code());
5336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG,
5337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                        &target_info,
5338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                        target_shared);
5339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // ----------------------------------------------------------------
53423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // After this point, we've made a decision to inline this function (so
53433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // TryInline should always return true).
53443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Save the pending call context and type feedback oracle. Set up new ones
5346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // for the inlined function.
5347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(target_shared->has_deoptimization_support());
5348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  TypeFeedbackOracle target_oracle(
5349e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Handle<Code>(target_shared->code()),
53503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Context>(target->context()->global_context()),
53513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate());
53523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The function state is new-allocated because we need to delete it
53533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in two different places.
53543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FunctionState* target_state = new FunctionState(
53553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      this, &target_info, &target_oracle, return_handling);
5356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
535744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HConstant* undefined = graph()->GetConstantUndefined();
535844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEnvironment* inner_env =
5359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      environment()->CopyForInlining(target,
53603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     arguments->length(),
5361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     function,
5362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     undefined,
53633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     call_kind,
53643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     function_state()->is_construct());
53653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef V8_TARGET_ARCH_IA32
53663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // IA32 only, overwrite the caller's context in the deoptimization
53673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // environment with the correct one.
53683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //
53693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(kmillikin): implement the same inlining on other platforms so we
53703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // can remove the unsightly ifdefs in this function.
53713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HConstant* context = new HConstant(Handle<Context>(target->context()),
53723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Representation::Tagged());
53733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInstruction(context);
53743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inner_env->BindContext(context);
53753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
53763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddSimulate(return_id);
53773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  current_block()->UpdateEnvironment(inner_env);
5378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AddInstruction(new(zone()) HEnterInlined(target,
53793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           arguments->length(),
5380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                           function,
53813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           call_kind,
53823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           function_state()->is_construct(),
53833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           function->scope()->arguments()));
53843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the function uses arguments object create and bind one.
53853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (function->scope()->arguments() != NULL) {
53863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(function->scope()->arguments()->IsStackAllocated());
53873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    environment()->Bind(function->scope()->arguments(),
53883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        graph()->GetArgumentsObject());
53893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
53903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  VisitDeclarations(target_info.scope()->declarations());
539144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  VisitStatements(function->body());
5392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (HasStackOverflow()) {
5393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Bail out if the inline function did, as we cannot residualize a call
5394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // instead.
5395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TraceInline(target, caller, "inline graph construction failed");
53963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    target_shared->DisableOptimization();
5397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    inline_bailout_ = true;
53983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    delete target_state;
5399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return true;
5400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Update inlined nodes count.
5403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  inlined_count_ += nodes_added;
5404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TraceInline(target, caller, NULL);
5406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
540744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (current_block() != NULL) {
54083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Add default return value (i.e. undefined for normals calls or the newly
54093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // allocated receiver for construct calls) if control can fall off the
54103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // body.  In a test context, undefined is false and any JSObject is true.
54113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (call_context()->IsValue()) {
54125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ASSERT(function_return() != NULL);
54133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HValue* return_value = function_state()->is_construct()
54143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? receiver
54153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : undefined;
54163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current_block()->AddLeaveInlined(return_value,
54173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       function_return(),
54183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       function_state()->drop_extra());
54193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (call_context()->IsEffect()) {
54203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(function_return() != NULL);
54213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current_block()->Goto(function_return(), function_state()->drop_extra());
5422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
54233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(call_context()->IsTest());
54243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(inlined_test_context() != NULL);
54253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HBasicBlock* target = function_state()->is_construct()
54263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? inlined_test_context()->if_true()
54273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : inlined_test_context()->if_false();
54283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current_block()->Goto(target, function_state()->drop_extra());
5429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Fix up the function exits.
5433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (inlined_test_context() != NULL) {
5434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* if_true = inlined_test_context()->if_true();
5435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HBasicBlock* if_false = inlined_test_context()->if_false();
54363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Pop the return test context from the expression context stack.
54383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(ast_context() == inlined_test_context());
5439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ClearInlinedTestContext();
54403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    delete target_state;
5441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Forward to the real test context.
5443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (if_true->HasPredecessor()) {
54443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if_true->SetJoinId(ast_id);
5445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
54463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if_true->Goto(true_target, function_state()->drop_extra());
5447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
5448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (if_false->HasPredecessor()) {
54493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if_false->SetJoinId(ast_id);
5450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
54513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if_false->Goto(false_target, function_state()->drop_extra());
5452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
5453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(NULL);
54543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return true;
5455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (function_return()->HasPredecessor()) {
54573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    function_return()->SetJoinId(ast_id);
5458e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    set_current_block(function_return());
5459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
5460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(NULL);
5461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
54623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  delete target_state;
546385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return true;
54645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
54655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
54665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
54673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) {
54683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The function call we are inlining is a method call if the call
54693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // is a property call.
54703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = (expr->expression()->AsProperty() == NULL)
54713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? CALL_AS_FUNCTION
54723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : CALL_AS_METHOD;
54733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
54743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return TryInline(call_kind,
54753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   expr->target(),
54763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   expr->arguments(),
54773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   NULL,
54783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   expr->id(),
54793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   expr->ReturnId(),
54803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN);
54813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
54823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
54833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
54843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraphBuilder::TryInlineConstruct(CallNew* expr, HValue* receiver) {
54853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return TryInline(CALL_AS_FUNCTION,
54863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   expr->target(),
54873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   expr->arguments(),
54883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   receiver,
54893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   expr->id(),
54903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   expr->ReturnId(),
54913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   CONSTRUCT_CALL_RETURN);
54923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
54933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
54943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
54953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) {
54963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
54973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
54983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (id) {
54993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathRound:
55003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathAbs:
55013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathSqrt:
55023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathLog:
55033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathSin:
55043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathCos:
55053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathTan:
55063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (expr->arguments()->length() == 1) {
55073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HValue* argument = Pop();
55083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HValue* context = environment()->LookupContext();
55093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Drop(1);  // Receiver.
55103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HUnaryMathOperation* op =
55113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            new(zone()) HUnaryMathOperation(context, argument, id);
55123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        op->set_position(expr->position());
55133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (drop_extra) Drop(1);  // Optionally drop the function.
55143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ast_context()->ReturnInstruction(op, expr->id());
55153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return true;
55163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
55173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
55183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default:
55193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Not supported for inlining yet.
55203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
55213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
55223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return false;
55233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
55243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr,
55273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               HValue* receiver,
55283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               Handle<Map> receiver_map,
55293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               CheckType check_type) {
55301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null());
5531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Try to inline calls like Math.* as operations in the calling function.
55321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
5533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
5534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
5535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (id) {
55361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case kStringCharCodeAt:
553744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    case kStringCharAt:
55381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (argument_count == 2 && check_type == STRING_CHECK) {
55391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        HValue* index = Pop();
55401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        HValue* string = Pop();
55413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HValue* context = environment()->LookupContext();
55421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ASSERT(!expr->holder().is_null());
55438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckPrototypeMaps(
55441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK),
55451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            expr->holder()));
55463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HStringCharCodeAt* char_code =
55473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            BuildStringCharCodeAt(context, string, index);
554844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (id == kStringCharCodeAt) {
554944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ast_context()->ReturnInstruction(char_code, expr->id());
555044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          return true;
555144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
555244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        AddInstruction(char_code);
55538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        HStringCharFromCode* result =
55543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            new(zone()) HStringCharFromCode(context, char_code);
55551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ast_context()->ReturnInstruction(result, expr->id());
55561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        return true;
55571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
55581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
5559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathRound:
5560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathFloor:
5561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathAbs:
5562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathSqrt:
5563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathLog:
5564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathSin:
5565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathCos:
55663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathTan:
55671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
55681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AddCheckConstantFunction(expr, receiver, receiver_map, true);
5569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* argument = Pop();
55703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HValue* context = environment()->LookupContext();
5571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Drop(1);  // Receiver.
55723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HUnaryMathOperation* op =
55733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            new(zone()) HUnaryMathOperation(context, argument, id);
5574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        op->set_position(expr->position());
5575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ast_context()->ReturnInstruction(op, expr->id());
5576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return true;
5577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
5579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathPow:
55801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
55811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AddCheckConstantFunction(expr, receiver, receiver_map, true);
5582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* right = Pop();
5583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* left = Pop();
5584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Pop();  // Pop receiver.
55853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HValue* context = environment()->LookupContext();
5586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HInstruction* result = NULL;
5587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Use sqrt() if exponent is 0.5 or -0.5.
5588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
5589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          double exponent = HConstant::cast(right)->DoubleValue();
5590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (exponent == 0.5) {
55913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            result =
55923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                new(zone()) HUnaryMathOperation(context, left, kMathPowHalf);
5593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (exponent == -0.5) {
5594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HConstant* double_one =
55958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                new(zone()) HConstant(Handle<Object>(Smi::FromInt(1)),
55968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                      Representation::Double());
5597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AddInstruction(double_one);
5598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HUnaryMathOperation* square_root =
55993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                new(zone()) HUnaryMathOperation(context, left, kMathPowHalf);
5600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AddInstruction(square_root);
5601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // MathPowHalf doesn't have side effects so there's no need for
5602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // an environment simulation here.
56033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ASSERT(!square_root->HasObservableSideEffects());
56043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            result = new(zone()) HDiv(context, double_one, square_root);
5605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (exponent == 2.0) {
56063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            result = new(zone()) HMul(context, left, left);
5607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
5608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else if (right->IsConstant() &&
56091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                   HConstant::cast(right)->HasInteger32Value() &&
56101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                   HConstant::cast(right)->Integer32Value() == 2) {
56113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          result = new(zone()) HMul(context, left, left);
5612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
5613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
56141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if (result == NULL) {
56158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          result = new(zone()) HPower(left, right);
56161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        }
5617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ast_context()->ReturnInstruction(result, expr->id());
5618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return true;
5619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
56213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathRandom:
56223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) {
56233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddCheckConstantFunction(expr, receiver, receiver_map, true);
56243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Drop(1);  // Receiver.
56253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HValue* context = environment()->LookupContext();
56263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HGlobalObject* global_object = new(zone()) HGlobalObject(context);
56273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddInstruction(global_object);
56283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HRandom* result = new(zone()) HRandom(global_object);
56293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ast_context()->ReturnInstruction(result, expr->id());
56303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return true;
56313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
56323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
56333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathMax:
56343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case kMathMin:
56353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
56363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddCheckConstantFunction(expr, receiver, receiver_map, true);
56373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HValue* right = Pop();
56383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HValue* left = Pop();
56393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Pop();  // Pop receiver.
56403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
56413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HValue* left_operand = left;
56423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HValue* right_operand = right;
56433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
56443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // If we do not have two integers, we convert to double for comparison.
56453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!left->representation().IsInteger32() ||
56463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            !right->representation().IsInteger32()) {
56473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (!left->representation().IsDouble()) {
56483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            HChange* left_convert = new(zone()) HChange(
56493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                left,
56503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Representation::Double(),
56513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                false,  // Do not truncate when converting to double.
56523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                true);  // Deoptimize for undefined.
56533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            left_convert->SetFlag(HValue::kBailoutOnMinusZero);
56543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            left_operand = AddInstruction(left_convert);
56553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
56563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (!right->representation().IsDouble()) {
56573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            HChange* right_convert = new(zone()) HChange(
56583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                right,
56593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Representation::Double(),
56603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                false,  // Do not truncate when converting to double.
56613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                true);  // Deoptimize for undefined.
56623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            right_convert->SetFlag(HValue::kBailoutOnMinusZero);
56633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            right_operand = AddInstruction(right_convert);
56643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
56653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
56663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
56673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(left_operand->representation().Equals(
56683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               right_operand->representation()));
56693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(!left_operand->representation().IsTagged());
56703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
56713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Token::Value op = (id == kMathMin) ? Token::LT : Token::GT;
56723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
56733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HCompareIDAndBranch* compare =
56743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            new(zone()) HCompareIDAndBranch(left_operand, right_operand, op);
56753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        compare->SetInputRepresentation(left_operand->representation());
56763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
56773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HBasicBlock* return_left = graph()->CreateBasicBlock();
56783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HBasicBlock* return_right = graph()->CreateBasicBlock();
56793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
56803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        compare->SetSuccessorAt(0, return_left);
56813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        compare->SetSuccessorAt(1, return_right);
56823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        current_block()->Finish(compare);
56833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
56843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        set_current_block(return_left);
56853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Push(left);
56863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        set_current_block(return_right);
56873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The branch above always returns the right operand if either of
56883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // them is NaN, but the spec requires that max/min(NaN, X) = NaN.
56893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We add another branch that checks if the left operand is NaN or not.
56903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (left_operand->representation().IsDouble()) {
56913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // If left_operand != left_operand then it is NaN.
56923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          HCompareIDAndBranch* compare_nan = new(zone()) HCompareIDAndBranch(
56933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              left_operand, left_operand, Token::EQ);
56943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          compare_nan->SetInputRepresentation(left_operand->representation());
56953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          HBasicBlock* left_is_number = graph()->CreateBasicBlock();
56963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          HBasicBlock* left_is_nan = graph()->CreateBasicBlock();
56973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          compare_nan->SetSuccessorAt(0, left_is_number);
56983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          compare_nan->SetSuccessorAt(1, left_is_nan);
56993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          current_block()->Finish(compare_nan);
57003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          set_current_block(left_is_nan);
57013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Push(left);
57023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          set_current_block(left_is_number);
57033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Push(right);
57043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          return_right = CreateJoin(left_is_number, left_is_nan, expr->id());
57053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
57063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Push(right);
57073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
57083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
57093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HBasicBlock* join = CreateJoin(return_left, return_right, expr->id());
57103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        set_current_block(join);
57113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ast_context()->ReturnValue(Pop());
57123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return true;
57133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
57143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
5715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    default:
5716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Not yet supported for inlining.
5717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
5718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return false;
5720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryCallApply(Call* expr) {
5724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Expression* callee = expr->expression();
5725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = callee->AsProperty();
5726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(prop != NULL);
5727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
572842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) {
572942effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch    return false;
573042effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  }
573142effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  Handle<Map> function_map = expr->GetReceiverTypes()->first();
573242effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  if (function_map->instance_type() != JS_FUNCTION_TYPE ||
573342effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch      !expr->target()->shared()->HasBuiltinFunctionId() ||
573442effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch      expr->target()->shared()->builtin_function_id() != kFunctionApply) {
573542effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch    return false;
573642effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  }
5737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
573842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  if (info()->scope()->arguments() == NULL) return false;
5739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
5741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (args->length() != 2) return false;
5742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* arg_two = args->at(1)->AsVariableProxy();
5744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
5745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* arg_two_value = environment()->Lookup(arg_two->var());
5746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
5747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Found pattern f.apply(receiver, arguments).
5749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForValue(prop->obj());
5750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (HasStackOverflow() || current_block() == NULL) return true;
5751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* function = Top();
5752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AddCheckConstantFunction(expr, function, function_map, true);
5753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Drop(1);
5754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForValue(args->at(0));
5756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (HasStackOverflow() || current_block() == NULL) return true;
5757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* receiver = Pop();
57583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
57593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (function_state()->outer() == NULL) {
57603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
57613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HInstruction* length =
57623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddInstruction(new(zone()) HArgumentsLength(elements));
57633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HValue* wrapped_receiver =
57643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddInstruction(new(zone()) HWrapReceiver(receiver, function));
57653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HInstruction* result =
57663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        new(zone()) HApplyArguments(function,
57673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    wrapped_receiver,
57683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    length,
57693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    elements);
57703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    result->set_position(expr->position());
57713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ast_context()->ReturnInstruction(result, expr->id());
57723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return true;
57733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
57743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We are inside inlined function and we know exactly what is inside
57753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // arguments object.
57763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HValue* context = environment()->LookupContext();
57773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
57783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HValue* wrapped_receiver =
57793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AddInstruction(new(zone()) HWrapReceiver(receiver, function));
57803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PushAndAdd(new(zone()) HPushArgument(wrapped_receiver));
57813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
57823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HEnvironment* arguments_env = environment()->arguments_environment();
57833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
57843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int parameter_count = arguments_env->parameter_count();
57853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 1; i < arguments_env->parameter_count(); i++) {
57863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PushAndAdd(new(zone()) HPushArgument(arguments_env->Lookup(i)));
57873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
57883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
57893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HInvokeFunction* call = new(zone()) HInvokeFunction(
57903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        context,
57913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        function,
57923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        parameter_count);
57933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Drop(parameter_count);
57943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    call->set_position(expr->position());
57953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ast_context()->ReturnInstruction(call, expr->id());
57963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return true;
57973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCall(Call* expr) {
5802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
5803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
5804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
5805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Expression* callee = expr->expression();
5806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
5807e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HInstruction* call = NULL;
5808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = callee->AsProperty();
5810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (prop != NULL) {
5811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!prop->key()->IsPropertyName()) {
5812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Keyed function call.
58133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      CHECK_ALIVE(VisitArgument(prop->obj()));
5814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->key()));
5816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Push receiver and key like the non-optimized code generator expects it.
5817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* key = Pop();
5818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* receiver = Pop();
5819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(key);
5820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(receiver);
5821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
58223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      CHECK_ALIVE(VisitArgumentList(expr->arguments()));
5823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      HValue* context = environment()->LookupContext();
58253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      call = new(zone()) HCallKeyed(context, key, argument_count);
5826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      call->set_position(expr->position());
58273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Drop(argument_count + 1);  // 1 is the key.
58283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnInstruction(call, expr->id());
5829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Named function call.
5832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD);
5833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (TryCallApply(expr)) return;
5835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(prop->obj()));
5837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitExpressions(expr->arguments()));
5838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
5840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
584169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    SmallMapList* types = expr->GetReceiverTypes();
5842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
58431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    HValue* receiver =
58441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        environment()->ExpressionStackAt(expr->arguments()->length());
58451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (expr->IsMonomorphic()) {
584669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Handle<Map> receiver_map = (types == NULL || types->is_empty())
584769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          ? Handle<Map>::null()
584869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          : types->first();
58493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (TryInlineBuiltinMethodCall(expr,
58503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     receiver,
58513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     receiver_map,
58523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     expr->check_type())) {
58533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (FLAG_trace_inlining) {
58543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          PrintF("Inlining builtin ");
58553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          expr->target()->ShortPrint();
58563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          PrintF("\n");
58573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
5858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return;
5859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
58613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (CallStubCompiler::HasCustomCallGenerator(expr->target()) ||
58621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          expr->check_type() != RECEIVER_MAP_CHECK) {
58631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // When the target has a custom call IC generator, use the IC,
586444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // because it is likely to generate better code.  Also use the IC
586544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // when a primitive receiver check is required.
5866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        HValue* context = environment()->LookupContext();
58678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        call = PreProcessCall(
58688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) HCallNamed(context, name, argument_count));
58691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
58701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AddCheckConstantFunction(expr, receiver, receiver_map, true);
58711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
58723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (TryInlineCall(expr)) return;
5873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        call = PreProcessCall(
5874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            new(zone()) HCallConstantFunction(expr->target(),
5875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              argument_count));
58761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
5877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (types != NULL && types->length() > 1) {
5878b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
5879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandlePolymorphicCallNamed(expr, receiver, types, name);
5880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
5881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
5883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      HValue* context = environment()->LookupContext();
58848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      call = PreProcessCall(
58858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          new(zone()) HCallNamed(context, name, argument_count));
5886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
58893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION);
5890589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    VariableProxy* proxy = expr->expression()->AsVariableProxy();
5891589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
5892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
58933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (proxy != NULL && proxy->var()->is_possibly_eval()) {
58943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return Bailout("possible direct call to eval");
58953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
58963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (global_call) {
5898589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Variable* var = proxy->var();
5899e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      bool known_global_function = false;
5900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // If there is a global property cell for the name at compile time and
5901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // access check is not enabled we assume that the function will not change
5902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // and generate optimized code for calling the function.
59033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LookupResult lookup(isolate());
59048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
59058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (type == kUseCell &&
5906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          !info()->global_object()->IsAccessCheckNeeded()) {
5907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        Handle<GlobalObject> global(info()->global_object());
59088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        known_global_function = expr->ComputeGlobalTarget(global, &lookup);
5909e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
5910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (known_global_function) {
5911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Push the global object instead of the global receiver because
5912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // code generated by the full code generator expects it.
5913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        HValue* context = environment()->LookupContext();
59148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        HGlobalObject* global_object = new(zone()) HGlobalObject(context);
59151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        PushAndAdd(global_object);
5916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        CHECK_ALIVE(VisitExpressions(expr->arguments()));
5917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        CHECK_ALIVE(VisitForValue(expr->expression()));
5919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* function = Pop();
59208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddInstruction(new(zone()) HCheckFunction(function, expr->target()));
5921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Replace the global object with the global receiver.
59238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        HGlobalReceiver* global_receiver =
59248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) HGlobalReceiver(global_object);
5925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Index of the receiver from the top of the expression stack.
5926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        const int receiver_index = argument_count - 1;
5927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        AddInstruction(global_receiver);
5928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(environment()->ExpressionStackAt(receiver_index)->
5929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               IsGlobalObject());
5930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        environment()->SetExpressionStackAt(receiver_index, global_receiver);
5931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
59323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (TryInlineBuiltinFunctionCall(expr, false)) {  // Nothing to drop.
59333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (FLAG_trace_inlining) {
59343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            PrintF("Inlining builtin ");
59353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            expr->target()->ShortPrint();
59363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            PrintF("\n");
59373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
59383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          return;
59393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
59403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (TryInlineCall(expr)) return;
59418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
5942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                           argument_count));
5943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
5944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        HValue* context = environment()->LookupContext();
59453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        HGlobalObject* receiver = new(zone()) HGlobalObject(context);
59463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AddInstruction(receiver);
59473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        PushAndAdd(new(zone()) HPushArgument(receiver));
59483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        CHECK_ALIVE(VisitArgumentList(expr->arguments()));
5949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
59503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        call = new(zone()) HCallGlobal(context, var->name(), argument_count);
59513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Drop(argument_count);
5952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
59543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (expr->IsMonomorphic()) {
59553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // The function is on the stack in the unoptimized code during
59563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // evaluation of the arguments.
59573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK_ALIVE(VisitForValue(expr->expression()));
59583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HValue* function = Top();
59593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HValue* context = environment()->LookupContext();
59603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HGlobalObject* global = new(zone()) HGlobalObject(context);
59613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global);
59623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      AddInstruction(global);
59633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PushAndAdd(receiver);
59643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK_ALIVE(VisitExpressions(expr->arguments()));
59653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      AddInstruction(new(zone()) HCheckFunction(function, expr->target()));
59663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
59673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (TryInlineBuiltinFunctionCall(expr, true)) {  // Drop the function.
59683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (FLAG_trace_inlining) {
59693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          PrintF("Inlining builtin ");
59703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          expr->target()->ShortPrint();
59713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          PrintF("\n");
59723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
59733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return;
59743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
59753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
59763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (TryInlineCall(expr, true)) {   // Drop function from environment.
59773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return;
59783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
59793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        call = PreProcessCall(new(zone()) HInvokeFunction(context,
59803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                          function,
59813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                          argument_count));
59823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Drop(1);  // The function.
59833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
59843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
59863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK_ALIVE(VisitForValue(expr->expression()));
59873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HValue* function = Top();
5988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      HValue* context = environment()->LookupContext();
59898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HGlobalObject* global_object = new(zone()) HGlobalObject(context);
59903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object);
59911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      AddInstruction(global_object);
59923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      AddInstruction(receiver);
59933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      PushAndAdd(new(zone()) HPushArgument(receiver));
59943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      CHECK_ALIVE(VisitArgumentList(expr->arguments()));
5995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
59963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call = new(zone()) HCallFunction(context, function, argument_count);
59973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Drop(argument_count + 1);
5998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  call->set_position(expr->position());
60023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(call, expr->id());
6003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
60063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Checks whether allocation using the given constructor can be inlined.
60073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool IsAllocationInlineable(Handle<JSFunction> constructor) {
60083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return constructor->has_initial_map() &&
60093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      constructor->initial_map()->instance_type() == JS_OBJECT_TYPE;
60103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
60113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
60123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallNew(CallNew* expr) {
6014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
60173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  expr->RecordTypeFeedback(oracle());
60183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int argument_count = expr->arguments()->length() + 1;  // Plus constructor.
6019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
60201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
60213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_inline_construct &&
60223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      expr->IsMonomorphic() &&
60233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      IsAllocationInlineable(expr->target())) {
60243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The constructor function is on the stack in the unoptimized code
60253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // during evaluation of the arguments.
60263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_ALIVE(VisitForValue(expr->expression()));
60273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HValue* function = Top();
60283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_ALIVE(VisitExpressions(expr->arguments()));
60293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> constructor = expr->target();
60303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HValue* check = AddInstruction(
60313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        new(zone()) HCheckFunction(function, constructor));
60323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
60333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Force completion of inobject slack tracking before generating
60343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // allocation code to finalize instance size.
60353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (constructor->shared()->IsInobjectSlackTrackingInProgress()) {
60363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      constructor->shared()->CompleteInobjectSlackTracking();
60373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
60383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
60393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Replace the constructor function with a newly allocated receiver.
60403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HInstruction* receiver = new(zone()) HAllocateObject(context, constructor);
60413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Index of the receiver from the top of the expression stack.
60423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const int receiver_index = argument_count - 1;
60433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AddInstruction(receiver);
60443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(environment()->ExpressionStackAt(receiver_index) == function);
60453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    environment()->SetExpressionStackAt(receiver_index, receiver);
60463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
60473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (TryInlineConstruct(expr, receiver)) return;
60483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
60493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // TODO(mstarzinger): For now we remove the previous HAllocateObject and
60503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // add HPushArgument for the arguments in case inlining failed.  What we
60513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // actually should do is emit HInvokeFunction on the constructor instead
60523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // of using HCallNew as a fallback.
60533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    receiver->DeleteAndReplaceWith(NULL);
60543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    check->DeleteAndReplaceWith(NULL);
60553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    environment()->SetExpressionStackAt(receiver_index, function);
60563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HInstruction* call = PreProcessCall(
60573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        new(zone()) HCallNew(context, function, argument_count));
60583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    call->set_position(expr->position());
60593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ast_context()->ReturnInstruction(call, expr->id());
60603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
60613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The constructor function is both an operand to the instruction and an
60623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // argument to the construct call.
60633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HValue* constructor = NULL;
60643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_ALIVE(constructor = VisitArgument(expr->expression()));
60653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_ALIVE(VisitArgumentList(expr->arguments()));
60663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HInstruction* call =
60673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        new(zone()) HCallNew(context, constructor, argument_count);
60683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Drop(argument_count);
60693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    call->set_position(expr->position());
60703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ast_context()->ReturnInstruction(call, expr->id());
60713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for generating inlined runtime functions.
6076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Lookup table for generators for runtime calls that are  generated inline.
6078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Elements of the table are member pointers to functions of HGraphBuilder.
6079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize)  \
6080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    &HGraphBuilder::Generate##Name,
6081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst HGraphBuilder::InlineFunctionGenerator
6083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HGraphBuilder::kInlineFunctionGenerators[] = {
6084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
6085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
6086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
6087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef INLINE_FUNCTION_GENERATOR_ADDRESS
6088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
6091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
6094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->is_jsruntime()) {
6095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Bailout("call to a JavaScript runtime function");
6096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
609844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Runtime::Function* function = expr->function();
6099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(function != NULL);
6100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (function->intrinsic_type == Runtime::INLINE) {
6101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(expr->name()->length() > 0);
6102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(expr->name()->Get(0) == '_');
6103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Call to an inline function.
6104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int lookup_index = static_cast<int>(function->function_id) -
6105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        static_cast<int>(Runtime::kFirstInlineFunction);
6106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(lookup_index >= 0);
6107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(static_cast<size_t>(lookup_index) <
6108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           ARRAY_SIZE(kInlineFunctionGenerators));
6109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
6110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Call the inline code generator using the pointer-to-member.
6112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    (this->*generator)(expr);
6113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
6114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(function->intrinsic_type == Runtime::RUNTIME);
6115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitArgumentList(expr->arguments()));
6116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
61173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HValue* context = environment()->LookupContext();
6118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Handle<String> name = expr->name();
6119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int argument_count = expr->arguments()->length();
61208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HCallRuntime* call =
61213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        new(zone()) HCallRuntime(context, name, function, argument_count);
6122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    call->set_position(RelocInfo::kNoPosition);
6123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Drop(argument_count);
61243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnInstruction(call, expr->id());
6125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
6130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
6133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  switch (expr->op()) {
6134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::DELETE: return VisitDelete(expr);
6135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::VOID: return VisitVoid(expr);
6136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::TYPEOF: return VisitTypeof(expr);
6137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::ADD: return VisitAdd(expr);
6138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::SUB: return VisitSub(expr);
6139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::BIT_NOT: return VisitBitNot(expr);
6140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::NOT: return VisitNot(expr);
6141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    default: UNREACHABLE();
6142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitDelete(UnaryOperation* expr) {
6146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Property* prop = expr->expression()->AsProperty();
6147589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  VariableProxy* proxy = expr->expression()->AsVariableProxy();
6148589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (prop != NULL) {
614969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CHECK_ALIVE(VisitForValue(prop->obj()));
615069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CHECK_ALIVE(VisitForValue(prop->key()));
615169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    HValue* key = Pop();
615269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    HValue* obj = Pop();
615369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    HValue* context = environment()->LookupContext();
615469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key);
615569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return ast_context()->ReturnInstruction(instr, expr->id());
6156589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL) {
6157589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Variable* var = proxy->var();
6158589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (var->IsUnallocated()) {
6159589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Bailout("delete with global variable");
6160589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else if (var->IsStackAllocated() || var->IsContextSlot()) {
6161589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Result of deleting non-global variables is false.  'this' is not
6162589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // really a variable, though we implement it as one.  The
6163589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // subexpression does not have side effects.
6164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      HValue* value = var->is_this()
6165589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          ? graph()->GetConstantTrue()
6166589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          : graph()->GetConstantFalse();
6167589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return ast_context()->ReturnValue(value);
6168589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else {
6169589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Bailout("delete with non-global variable");
6170589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
6171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
6172589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Result of deleting non-property, non-variable reference is true.
6173589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Evaluate the subexpression for side effects.
6174589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    CHECK_ALIVE(VisitForEffect(expr->expression()));
6175589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return ast_context()->ReturnValue(graph()->GetConstantTrue());
6176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
617944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitVoid(UnaryOperation* expr) {
6181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForEffect(expr->expression()));
61823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
6183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitTypeof(UnaryOperation* expr) {
6187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForTypeOf(expr->expression()));
6188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* value = Pop();
61893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
61903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* instr = new(zone()) HTypeof(context, value);
61913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
6192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitAdd(UnaryOperation* expr) {
6196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->expression()));
6197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* value = Pop();
61983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
61993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* instr =
62003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HMul(context, value, graph_->GetConstant1());
62013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
6202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitSub(UnaryOperation* expr) {
6206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->expression()));
6207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* value = Pop();
62083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
62093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* instr =
62103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HMul(context, value, graph_->GetConstantMinus1());
6211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TypeInfo info = oracle()->UnaryType(expr);
62123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (info.IsUninitialized()) {
62133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(new(zone()) HSoftDeoptimize);
62143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    current_block()->MarkAsDeoptimizing();
62153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    info = TypeInfo::Unknown();
62163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
6217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Representation rep = ToRepresentation(info);
6218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TraceRepresentation(expr->op(), info, instr, rep);
6219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  instr->AssumeRepresentation(rep);
62203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
6221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitBitNot(UnaryOperation* expr) {
6225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->expression()));
6226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* value = Pop();
62273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  TypeInfo info = oracle()->UnaryType(expr);
62283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (info.IsUninitialized()) {
62293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(new(zone()) HSoftDeoptimize);
62303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    current_block()->MarkAsDeoptimizing();
62313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
6232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HInstruction* instr = new(zone()) HBitNot(value);
62333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
6234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitNot(UnaryOperation* expr) {
6238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (ast_context()->IsTest()) {
6239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TestContext* context = TestContext::cast(ast_context());
6240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VisitForControl(expr->expression(),
6241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    context->if_false(),
6242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    context->if_true());
6243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return;
6244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (ast_context()->IsEffect()) {
6247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VisitForEffect(expr->expression());
6248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return;
6249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(ast_context()->IsValue());
6252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HBasicBlock* materialize_false = graph()->CreateBasicBlock();
6253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HBasicBlock* materialize_true = graph()->CreateBasicBlock();
6254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_BAILOUT(VisitForControl(expr->expression(),
6255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                materialize_false,
6256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                materialize_true));
6257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (materialize_false->HasPredecessor()) {
62593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    materialize_false->SetJoinId(expr->MaterializeFalseId());
6260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(materialize_false);
6261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Push(graph()->GetConstantFalse());
626244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
6263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    materialize_false = NULL;
6264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (materialize_true->HasPredecessor()) {
62673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    materialize_true->SetJoinId(expr->MaterializeTrueId());
6268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(materialize_true);
6269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Push(graph()->GetConstantTrue());
6270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
6271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    materialize_true = NULL;
6272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HBasicBlock* join =
6275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CreateJoin(materialize_false, materialize_true, expr->id());
6276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  set_current_block(join);
62773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (join != NULL) return ast_context()->ReturnValue(Pop());
6278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input,
6282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            CountOperation* expr) {
6283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // The input to the count operation is on top of the expression stack.
6284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TypeInfo info = oracle()->IncrementType(expr);
6285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Representation rep = ToRepresentation(info);
6286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (rep.IsTagged()) {
6287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    rep = Representation::Integer32();
6288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (returns_original_input) {
6291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // We need an explicit HValue representing ToNumber(input).  The
6292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // actual HChange instruction we need is (sometimes) added in a later
6293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // phase, so it is not available now to be used as an input to HAdd and
6294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // as the return value.
6295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep);
6296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AddInstruction(number_input);
6297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Push(number_input);
6298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // The addition has no side effects, so we do not need
6301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // to simulate the expression stack after this instruction.
6302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Any later failures deopt to the load of the input or earlier.
6303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HConstant* delta = (expr->op() == Token::INC)
6304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ? graph_->GetConstant1()
6305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : graph_->GetConstantMinus1();
63063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
63073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* instr = new(zone()) HAdd(context, Top(), delta);
6308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TraceRepresentation(expr->op(), info, instr, rep);
6309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  instr->AssumeRepresentation(rep);
6310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AddInstruction(instr);
6311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
6312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCountOperation(CountOperation* expr) {
6316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
63198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Expression* target = expr->expression();
6320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = target->AsVariableProxy();
6321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = target->AsProperty();
6322589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (proxy == NULL && prop == NULL) {
6323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Bailout("invalid lhs in count operation");
6324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Match the full code generator stack by simulating an extra stack
6327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // element for postfix operations in a non-effect context.  The return
6328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // value is ToNumber(input).
6329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool returns_original_input =
6330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      expr->is_postfix() && !ast_context()->IsEffect();
6331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* input = NULL;  // ToNumber(original_input).
6332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* after = NULL;  // The result after incrementing or decrementing.
6333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6334589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (proxy != NULL) {
6335589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Variable* var = proxy->var();
63363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (var->mode() == CONST)  {
63373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return Bailout("unsupported count operation with const");
63383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
6339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Argument of the count operation is a variable, not a property.
6340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(prop == NULL);
6341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(target));
6342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    after = BuildIncrement(returns_original_input, expr);
6344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    input = returns_original_input ? Top() : Pop();
6345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Push(after);
6346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6347589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    switch (var->location()) {
6348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::UNALLOCATED:
6349589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HandleGlobalVariableAssignment(var,
6350589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       after,
6351589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       expr->position(),
6352589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                       expr->AssignmentId());
6353589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        break;
6354589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
6355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::PARAMETER:
6356589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::LOCAL:
6357589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Bind(var, after);
6358589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        break;
6359589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
6360589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::CONTEXT: {
6361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // Bail out if we try to mutate a parameter value in a function
6362589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // using the arguments object.  We do not (yet) correctly handle the
6363589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // arguments property of the function.
6364589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (info()->scope()->arguments() != NULL) {
6365589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // Parameters will rewrite to context slots.  We have no direct
6366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // way to detect that the variable is a parameter so we use a
6367589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // linear search of the parameter list.
6368589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          int count = info()->scope()->num_parameters();
6369589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          for (int i = 0; i < count; ++i) {
6370589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            if (var == info()->scope()->parameter(i)) {
6371589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch              return Bailout("assignment to parameter in arguments object");
6372589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            }
63733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          }
63743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
6375589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
6376589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HValue* context = BuildContextChainWalk(var);
63773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HStoreContextSlot::Mode mode =
63783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            (var->mode() == LET || var->mode() == CONST_HARMONY)
63793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
6380589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HStoreContextSlot* instr =
63813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            new(zone()) HStoreContextSlot(context, var->index(), mode, after);
6382589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        AddInstruction(instr);
63833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (instr->HasObservableSideEffects()) {
63843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AddSimulate(expr->AssignmentId());
63853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
6386589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        break;
63873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
63883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6389589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      case Variable::LOOKUP:
6390589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return Bailout("lookup variable in count operation");
6391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
6392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
6394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Argument of the count operation is a property.
6395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(prop != NULL);
6396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    prop->RecordTypeFeedback(oracle());
6397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (prop->key()->IsPropertyName()) {
6399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Named property.
6400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (returns_original_input) Push(graph_->GetConstantUndefined());
6401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->obj()));
6403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = Top();
6404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* load = NULL;
6406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (prop->IsMonomorphic()) {
6407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
6408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<Map> map = prop->GetReceiverTypes()->first();
6409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamed(obj, prop, map, name);
6410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
6411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamedGeneric(obj, prop);
6412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
6413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(load);
64143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (load->HasObservableSideEffects()) AddSimulate(expr->CountId());
6415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      after = BuildIncrement(returns_original_input, expr);
6417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      input = Pop();
6418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* store = BuildStoreNamed(obj, after, prop);
6420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(store);
6421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Overwrite the receiver in the bailout environment with the result
6423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // of the operation, and the placeholder with the original value if
6424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // necessary.
6425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      environment()->SetExpressionStackAt(0, after);
6426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (returns_original_input) environment()->SetExpressionStackAt(1, input);
64273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId());
6428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
6430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Keyed property.
6431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (returns_original_input) Push(graph_->GetConstantUndefined());
6432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->obj()));
6434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_ALIVE(VisitForValue(prop->key()));
6435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = environment()->ExpressionStackAt(1);
6436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* key = environment()->ExpressionStackAt(0);
6437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
64383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bool has_side_effects = false;
64393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HValue* load = HandleKeyedElementAccess(
64403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          obj, key, NULL, prop, expr->CountId(), RelocInfo::kNoPosition,
64413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          false,  // is_store
64423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          &has_side_effects);
64433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Push(load);
64443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (has_side_effects) AddSimulate(expr->CountId());
6445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      after = BuildIncrement(returns_original_input, expr);
6447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      input = Pop();
6448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
64498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      expr->RecordTypeFeedback(oracle());
64503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(),
64513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               RelocInfo::kNoPosition,
64523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               true,  // is_store
64533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               &has_side_effects);
6454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Drop the key from the bailout environment.  Overwrite the receiver
6456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // with the result of the operation, and the placeholder with the
6457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // original value if necessary.
6458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(1);
6459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      environment()->SetExpressionStackAt(0, after);
6460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (returns_original_input) environment()->SetExpressionStackAt(1, input);
64613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(has_side_effects);  // Stores always have side effects.
64623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      AddSimulate(expr->AssignmentId());
6463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
6464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Drop(returns_original_input ? 2 : 1);
64673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
6468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
64713fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context,
64723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                        HValue* string,
64731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                                        HValue* index) {
64748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AddInstruction(new(zone()) HCheckNonSmi(string));
6475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AddInstruction(HCheckInstanceType::NewIsString(string));
64768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HStringLength* length = new(zone()) HStringLength(string);
64771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddInstruction(length);
64787d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  HInstruction* checked_index =
64797d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch      AddInstruction(new(zone()) HBoundsCheck(index, length));
64803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return new(zone()) HStringCharCodeAt(context, string, checked_index);
64811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
64821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
64831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
6485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  HValue* left,
6486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  HValue* right) {
64873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
6488053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  TypeInfo info = oracle()->BinaryType(expr);
64893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (info.IsUninitialized()) {
64903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(new(zone()) HSoftDeoptimize);
64913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    current_block()->MarkAsDeoptimizing();
64923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    info = TypeInfo::Unknown();
64933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
64943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HInstruction* instr = NULL;
64953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (expr->op()) {
64963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::ADD:
64973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (info.IsString()) {
64983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AddInstruction(new(zone()) HCheckNonSmi(left));
64993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AddInstruction(HCheckInstanceType::NewIsString(left));
65003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AddInstruction(new(zone()) HCheckNonSmi(right));
65013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AddInstruction(HCheckInstanceType::NewIsString(right));
65023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        instr = new(zone()) HStringAdd(context, left, right);
65033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
65043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        instr = HAdd::NewHAdd(zone(), context, left, right);
65053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
65063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
65073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::SUB:
65083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr = HSub::NewHSub(zone(), context, left, right);
65093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
65103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::MUL:
65113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr = HMul::NewHMul(zone(), context, left, right);
65123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
65133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::MOD:
65143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr = HMod::NewHMod(zone(), context, left, right);
65153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
65163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::DIV:
65173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr = HDiv::NewHDiv(zone(), context, left, right);
65183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
65193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::BIT_XOR:
65203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::BIT_AND:
65213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::BIT_OR:
65223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right);
65233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
65243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::SAR:
65253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr = HSar::NewHSar(zone(), context, left, right);
65263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
65273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::SHR:
65283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr = HShr::NewHShr(zone(), context, left, right);
65293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
65303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::SHL:
65313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr = HShl::NewHShl(zone(), context, left, right);
65323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
65333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    default:
65343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      UNREACHABLE();
65353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
65363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If we hit an uninitialized binary op stub we will get type info
6538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // for a smi operation. If one of the operands is a constant string
6539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // do not generate code assuming it is a smi operation.
6540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsSmi() &&
6541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) ||
6542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch       (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) {
6543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return instr;
6544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
65451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Representation rep = ToRepresentation(info);
65461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We only generate either int32 or generic tagged bitwise operations.
65471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) {
65481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    rep = Representation::Integer32();
65491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
6550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TraceRepresentation(expr->op(), info, instr, rep);
6551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  instr->AssumeRepresentation(rep);
6552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
6553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check for the form (%_ClassOf(foo) === 'BarClass').
6557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool IsClassOfTest(CompareOperation* expr) {
6558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->op() != Token::EQ_STRICT) return false;
6559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CallRuntime* call = expr->left()->AsCallRuntime();
6560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (call == NULL) return false;
6561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Literal* literal = expr->right()->AsLiteral();
6562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (literal == NULL) return false;
6563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!literal->handle()->IsString()) return false;
6564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false;
6565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(call->arguments()->length() == 1);
6566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
6567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
6571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
6574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  switch (expr->op()) {
65753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::COMMA:
65763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return VisitComma(expr);
65773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::OR:
65783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::AND:
65793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return VisitLogicalExpression(expr);
65803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    default:
65813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return VisitArithmeticExpression(expr);
6582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitComma(BinaryOperation* expr) {
6587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForEffect(expr->left()));
6588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Visit the right subexpression in the same AST context as the entire
6589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // expression.
6590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Visit(expr->right());
6591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
6593e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
65943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
65953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool is_logical_and = expr->op() == Token::AND;
6596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (ast_context()->IsTest()) {
6597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    TestContext* context = TestContext::cast(ast_context());
6598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Translate left subexpression.
6599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* eval_right = graph()->CreateBasicBlock();
6600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (is_logical_and) {
6601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(VisitForControl(expr->left(),
6602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    eval_right,
6603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    context->if_false()));
6604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
6605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(VisitForControl(expr->left(),
6606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    context->if_true(),
6607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    eval_right));
6608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
6609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Translate right subexpression by visiting it in the same AST
6611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // context as the entire expression.
6612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (eval_right->HasPredecessor()) {
6613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      eval_right->SetJoinId(expr->RightId());
6614e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      set_current_block(eval_right);
6615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Visit(expr->right());
6616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
6617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
6618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (ast_context()->IsValue()) {
6619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(expr->left()));
6620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(current_block() != NULL);
6621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // We need an extra block to maintain edge-split form.
6623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* empty_block = graph()->CreateBasicBlock();
6624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* eval_right = graph()->CreateBasicBlock();
662569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    unsigned test_id = expr->left()->test_id();
662669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    ToBooleanStub::Types expected(oracle()->ToBooleanTypes(test_id));
66273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HBranch* test = is_logical_and
662869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      ? new(zone()) HBranch(Top(), eval_right, empty_block, expected)
662969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      : new(zone()) HBranch(Top(), empty_block, eval_right, expected);
6630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    current_block()->Finish(test);
6631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(eval_right);
6633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Drop(1);  // Value of the left subexpression.
6634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_BAILOUT(VisitForValue(expr->right()));
6635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* join_block =
6637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CreateJoin(empty_block, current_block(), expr->id());
6638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(join_block);
66393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnValue(Pop());
6640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
6641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
6642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(ast_context()->IsEffect());
6643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // In an effect context, we don't need the value of the left subexpression,
6644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // only its control flow and side effects.  We need an extra block to
6645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // maintain edge-split form.
6646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* empty_block = graph()->CreateBasicBlock();
6647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* right_block = graph()->CreateBasicBlock();
6648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (is_logical_and) {
6649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
6650e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
6651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
6652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
6653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // TODO(kmillikin): Find a way to fix this.  It's ugly that there are
6655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // actually two empty blocks (one here and one inserted by
6656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // TestContext::BuildBranch, and that they both have an HSimulate though the
6657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // second one is not a merge node, and that we really have no good AST ID to
6658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // put on that first HSimulate.
6659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (empty_block->HasPredecessor()) {
6661053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block      empty_block->SetJoinId(expr->id());
6662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
6663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      empty_block = NULL;
6664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
6665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (right_block->HasPredecessor()) {
6667053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block      right_block->SetJoinId(expr->RightId());
6668053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block      set_current_block(right_block);
6669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CHECK_BAILOUT(VisitForEffect(expr->right()));
6670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      right_block = current_block();
6671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
6672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      right_block = NULL;
6673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
6674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HBasicBlock* join_block =
6676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CreateJoin(empty_block, right_block, expr->id());
6677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    set_current_block(join_block);
6678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // We did not materialize any value in the predecessor environments,
6679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // so there is no need to handle it here.
6680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
66843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
6685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->left()));
6686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->right()));
6687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* right = Pop();
6688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* left = Pop();
6689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HInstruction* instr = BuildBinaryOperation(expr, left, right);
6690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  instr->set_position(expr->position());
66913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(instr, expr->id());
6692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
6693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::TraceRepresentation(Token::Value op,
6696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        TypeInfo info,
6697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        HValue* value,
6698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        Representation rep) {
6699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!FLAG_trace_representation) return;
6700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // TODO(svenpanne) Under which circumstances are we actually not flexible?
6701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // At first glance, this looks a bit weird...
6702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool flexible = value->CheckFlag(HValue::kFlexibleRepresentation);
6703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  PrintF("Operation %s has type info %s, %schange representation assumption "
6704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         "for %s (ID %d) from %s to %s\n",
6705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         Token::Name(op),
6706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         info.ToString(),
6707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         flexible ? "" : " DO NOT ",
6708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         value->Mnemonic(),
6709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         graph_->GetMaximumValueID(),
6710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         value->representation().Mnemonic(),
6711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         rep.Mnemonic());
6712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochRepresentation HGraphBuilder::ToRepresentation(TypeInfo info) {
6716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsSmi()) return Representation::Integer32();
6717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsInteger32()) return Representation::Integer32();
6718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsDouble()) return Representation::Double();
6719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsNumber()) return Representation::Double();
6720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Representation::Tagged();
6721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
67243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
67253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               HTypeof* typeof_expr,
67263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                               Handle<String> check) {
67273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Note: The HTypeof itself is removed during canonicalization, if possible.
67283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HValue* value = typeof_expr->value();
67293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check);
67303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  instr->set_position(expr->position());
67313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ast_context()->ReturnControl(instr, expr->id());
6732592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
6733592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
6734592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
67353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool MatchLiteralCompareNil(HValue* left,
67363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Token::Value op,
67373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   HValue* right,
67383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Handle<Object> nil,
67393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   HValue** expr) {
67403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (left->IsConstant() &&
67413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HConstant::cast(left)->handle().is_identical_to(nil) &&
67423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Token::IsEqualityOp(op)) {
67433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    *expr = right;
67443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return true;
67453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
67463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return false;
67473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
67483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
67493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
67503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool MatchLiteralCompareTypeof(HValue* left,
67513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Token::Value op,
67523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      HValue* right,
67533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      HTypeof** typeof_expr,
67543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<String>* check) {
67553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (left->IsTypeof() &&
67563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Token::IsEqualityOp(op) &&
67573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      right->IsConstant() &&
67583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HConstant::cast(right)->HasStringValue()) {
67593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    *typeof_expr = HTypeof::cast(left);
67603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    *check = Handle<String>::cast(HConstant::cast(right)->handle());
67613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return true;
67623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
67633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return false;
67643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
67653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
67663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
67673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool IsLiteralCompareTypeof(HValue* left,
67683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Token::Value op,
67693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   HValue* right,
67703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   HTypeof** typeof_expr,
67713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Handle<String>* check) {
67723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return MatchLiteralCompareTypeof(left, op, right, typeof_expr, check) ||
67733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MatchLiteralCompareTypeof(right, op, left, typeof_expr, check);
67743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
67753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
67763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
67773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool IsLiteralCompareNil(HValue* left,
67783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Token::Value op,
67793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                HValue* right,
67803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Handle<Object> nil,
67813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                HValue** expr) {
67823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return MatchLiteralCompareNil(left, op, right, nil, expr) ||
67833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MatchLiteralCompareNil(right, op, left, nil, expr);
67843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
67853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
67863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
67873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool IsLiteralCompareBool(HValue* left,
67883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Token::Value op,
67893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 HValue* right) {
67903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return op == Token::EQ_STRICT &&
67913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) ||
67923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean()));
6793c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
6794c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
6795c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
6796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
6797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
6800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (IsClassOfTest(expr)) {
6801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CallRuntime* call = expr->left()->AsCallRuntime();
68023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(call->arguments()->length() == 1);
6803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
6804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = Pop();
6805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Literal* literal = expr->right()->AsLiteral();
6806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> rhs = Handle<String>::cast(literal->handle());
68073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HClassOfTestAndBranch* instr =
68083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        new(zone()) HClassOfTestAndBranch(value, rhs);
6809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_position(expr->position());
68103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnControl(instr, expr->id());
68113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
68123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
68133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  TypeInfo type_info = oracle()->CompareType(expr);
68143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check if this expression was ever executed according to type feedback.
68153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Note that for the special typeof/null/undefined cases we get unknown here.
68163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (type_info.IsUninitialized()) {
68173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(new(zone()) HSoftDeoptimize);
68183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    current_block()->MarkAsDeoptimizing();
68193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    type_info = TypeInfo::Unknown();
68203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
68213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->left()));
6823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(expr->right()));
6824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
68253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
6826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* right = Pop();
6827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* left = Pop();
6828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Token::Value op = expr->op();
6829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
68303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HTypeof* typeof_expr = NULL;
68313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> check;
68323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (IsLiteralCompareTypeof(left, op, right, &typeof_expr, &check)) {
68333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return HandleLiteralCompareTypeof(expr, typeof_expr, check);
68343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
68353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HValue* sub_expr = NULL;
68363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Factory* f = graph()->isolate()->factory();
68373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (IsLiteralCompareNil(left, op, right, f->undefined_value(), &sub_expr)) {
68383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
68393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
68403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (IsLiteralCompareNil(left, op, right, f->null_value(), &sub_expr)) {
68413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
68423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
68433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (IsLiteralCompareBool(left, op, right)) {
68443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HCompareObjectEqAndBranch* result =
68453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        new(zone()) HCompareObjectEqAndBranch(left, right);
68463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    result->set_position(expr->position());
68473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ast_context()->ReturnControl(result, expr->id());
68483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
68493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (op == Token::INSTANCEOF) {
6851086aeeaae12517475c22695a200be45495516549Ben Murdoch    // Check to see if the rhs of the instanceof is a global function not
6852086aeeaae12517475c22695a200be45495516549Ben Murdoch    // residing in new space. If it is we assume that the function will stay the
6853086aeeaae12517475c22695a200be45495516549Ben Murdoch    // same.
6854086aeeaae12517475c22695a200be45495516549Ben Murdoch    Handle<JSFunction> target = Handle<JSFunction>::null();
6855589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    VariableProxy* proxy = expr->right()->AsVariableProxy();
6856589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated();
6857086aeeaae12517475c22695a200be45495516549Ben Murdoch    if (global_function &&
6858e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        info()->has_global_object() &&
6859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        !info()->global_object()->IsAccessCheckNeeded()) {
6860589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Handle<String> name = proxy->name();
6861e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Handle<GlobalObject> global(info()->global_object());
68623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LookupResult lookup(isolate());
6863086aeeaae12517475c22695a200be45495516549Ben Murdoch      global->Lookup(*name, &lookup);
68643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (lookup.IsFound() &&
6865086aeeaae12517475c22695a200be45495516549Ben Murdoch          lookup.type() == NORMAL &&
6866086aeeaae12517475c22695a200be45495516549Ben Murdoch          lookup.GetValue()->IsJSFunction()) {
6867086aeeaae12517475c22695a200be45495516549Ben Murdoch        Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
6868086aeeaae12517475c22695a200be45495516549Ben Murdoch        // If the function is in new space we assume it's more likely to
6869086aeeaae12517475c22695a200be45495516549Ben Murdoch        // change and thus prefer the general IC code.
687044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (!isolate()->heap()->InNewSpace(*candidate)) {
6871086aeeaae12517475c22695a200be45495516549Ben Murdoch          target = candidate;
6872086aeeaae12517475c22695a200be45495516549Ben Murdoch        }
6873086aeeaae12517475c22695a200be45495516549Ben Murdoch      }
6874086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
6875086aeeaae12517475c22695a200be45495516549Ben Murdoch
6876086aeeaae12517475c22695a200be45495516549Ben Murdoch    // If the target is not null we have found a known global function that is
6877086aeeaae12517475c22695a200be45495516549Ben Murdoch    // assumed to stay the same for this instanceof.
6878086aeeaae12517475c22695a200be45495516549Ben Murdoch    if (target.is_null()) {
68793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HInstanceOf* result = new(zone()) HInstanceOf(context, left, right);
68803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      result->set_position(expr->position());
68813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnInstruction(result, expr->id());
6882086aeeaae12517475c22695a200be45495516549Ben Murdoch    } else {
68838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      AddInstruction(new(zone()) HCheckFunction(right, target));
68843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HInstanceOfKnownGlobal* result =
68853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          new(zone()) HInstanceOfKnownGlobal(context, left, target);
68863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      result->set_position(expr->position());
68873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnInstruction(result, expr->id());
6888086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
6889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::IN) {
68903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HIn* result = new(zone()) HIn(context, left, right);
68913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    result->set_position(expr->position());
68923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnInstruction(result, expr->id());
6893e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (type_info.IsNonPrimitive()) {
6894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    switch (op) {
6895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case Token::EQ:
6896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case Token::EQ_STRICT: {
68973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Can we get away with map check and not instance type check?
68983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Handle<Map> map = oracle()->GetCompareMap(expr);
68993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!map.is_null()) {
69003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AddInstruction(new(zone()) HCheckNonSmi(left));
69013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AddInstruction(new(zone()) HCheckMap(left, map, NULL,
69023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               ALLOW_ELEMENT_TRANSITION_MAPS));
69033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AddInstruction(new(zone()) HCheckNonSmi(right));
69043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AddInstruction(new(zone()) HCheckMap(right, map, NULL,
69053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               ALLOW_ELEMENT_TRANSITION_MAPS));
69063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          HCompareObjectEqAndBranch* result =
69073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              new(zone()) HCompareObjectEqAndBranch(left, right);
69083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          result->set_position(expr->position());
69093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          return ast_context()->ReturnControl(result, expr->id());
69103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
69113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AddInstruction(new(zone()) HCheckNonSmi(left));
69123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AddInstruction(HCheckInstanceType::NewIsSpecObject(left));
69133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AddInstruction(new(zone()) HCheckNonSmi(right));
69143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AddInstruction(HCheckInstanceType::NewIsSpecObject(right));
69153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          HCompareObjectEqAndBranch* result =
69163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              new(zone()) HCompareObjectEqAndBranch(left, right);
69173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          result->set_position(expr->position());
69183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          return ast_context()->ReturnControl(result, expr->id());
69193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
6920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
6921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      default:
6922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return Bailout("Unsupported non-primitive compare");
6923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
6924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) &&
6925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch             (op == Token::EQ || op == Token::EQ_STRICT)) {
69263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(left));
69273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(HCheckInstanceType::NewIsSymbol(left));
69283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(new(zone()) HCheckNonSmi(right));
69293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    AddInstruction(HCheckInstanceType::NewIsSymbol(right));
69303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HCompareObjectEqAndBranch* result =
69313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        new(zone()) HCompareObjectEqAndBranch(left, right);
69323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    result->set_position(expr->position());
69333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnControl(result, expr->id());
6934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
6935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Representation r = ToRepresentation(type_info);
69363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (r.IsTagged()) {
69373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HCompareGeneric* result =
69383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          new(zone()) HCompareGeneric(context, left, right, op);
69393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      result->set_position(expr->position());
69403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnInstruction(result, expr->id());
69413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
69423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      HCompareIDAndBranch* result =
69433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          new(zone()) HCompareIDAndBranch(left, right, op);
69443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      result->set_position(expr->position());
69453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      result->SetInputRepresentation(r);
69463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ast_context()->ReturnControl(result, expr->id());
69473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
6948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
69523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
69533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            HValue* value,
69543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            NilValue nil) {
6955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
69583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EqualityKind kind =
69593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality;
69603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil);
69613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  instr->set_position(expr->position());
69623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(instr, expr->id());
6963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
6967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!HasStackOverflow());
6968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block() != NULL);
6969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(current_block()->HasPredecessor());
69703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HThisFunction* self = new(zone()) HThisFunction(
69713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function_state()->compilation_info()->closure());
69723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(self, expr->id());
6973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
6974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
69763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
69773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int length = declarations->length();
69783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int global_count = 0;
69793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < declarations->length(); i++) {
69803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Declaration* decl = declarations->at(i);
69813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration();
69823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HandleDeclaration(decl->proxy(),
69833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      decl->mode(),
69843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      fun_decl != NULL ? fun_decl->fun() : NULL,
69853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      &global_count);
69863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
69873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
69883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Batch declare global functions and variables.
69893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (global_count > 0) {
69903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<FixedArray> array =
69913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate()->factory()->NewFixedArray(2 * global_count, TENURED);
69923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int j = 0, i = 0; i < length; i++) {
69933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Declaration* decl = declarations->at(i);
69943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Variable* var = decl->proxy()->var();
69953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
69963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (var->IsUnallocated()) {
69973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        array->set(j++, *(var->name()));
69983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration();
69993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (fun_decl == NULL) {
70003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (var->binding_needs_init()) {
70013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // In case this binding needs initialization use the hole.
70023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            array->set_the_hole(j++);
70033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else {
70043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            array->set_undefined(j++);
70053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
70063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
70073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Handle<SharedFunctionInfo> function =
70083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Compiler::BuildFunctionInfo(fun_decl->fun(), info()->script());
70093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Check for stack-overflow exception.
70103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (function.is_null()) {
70113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            SetStackOverflow();
70123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            return;
70133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
70143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          array->set(j++, *function);
70153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
70163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
70173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
70183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
70193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                DeclareGlobalsNativeFlag::encode(info()->is_native()) |
70203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                DeclareGlobalsLanguageMode::encode(info()->language_mode());
70213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HInstruction* result =
70223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        new(zone()) HDeclareGlobals(environment()->LookupContext(),
70233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    array,
70243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    flags);
70253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AddInstruction(result);
70263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7027589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
7028589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
7029589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
7030589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
70313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      VariableMode mode,
70323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      FunctionLiteral* function,
70333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      int* global_count) {
7034589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Variable* var = proxy->var();
70353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool binding_needs_init =
70363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (mode == CONST || mode == CONST_HARMONY || mode == LET);
7037589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (var->location()) {
7038589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::UNALLOCATED:
70393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ++(*global_count);
70403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return;
7041589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::PARAMETER:
7042589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOCAL:
7043589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::CONTEXT:
70443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (binding_needs_init || function != NULL) {
7045589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        HValue* value = NULL;
70463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (function != NULL) {
70473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          CHECK_ALIVE(VisitForValue(function));
704885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch          value = Pop();
70493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
70503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          value = graph()->GetConstantHole();
7051589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        }
7052589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (var->IsContextSlot()) {
7053589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          HValue* context = environment()->LookupContext();
70543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          HStoreContextSlot* store = new HStoreContextSlot(
70553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              context, var->index(), HStoreContextSlot::kNoCheck, value);
7056589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          AddInstruction(store);
70573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (store->HasObservableSideEffects()) AddSimulate(proxy->id());
7058589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        } else {
7059589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          environment()->Bind(var, value);
7060589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        }
7061589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
7062589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
7063589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOOKUP:
7064589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return Bailout("unsupported lookup slot in declaration");
70653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
7066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
70693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
70703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
70713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
70723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
70733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
70743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
70753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
70763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
70773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
70783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
70793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) {
70803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
70813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
70823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
70833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
70843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
70853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
70863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
70873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
70883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
70893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
70903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
70913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
70923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
70933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
70943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) {
70953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(rossberg)
70963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
70973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
70983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
70993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitModuleVariable(ModuleVariable* module) {
71003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(rossberg)
71013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
71023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
71033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
71043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitModulePath(ModulePath* module) {
71053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(rossberg)
71063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
71073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
71083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
71093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitModuleUrl(ModuleUrl* module) {
71103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(rossberg)
71113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
71123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
71133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Generators for inline runtime functions.
7115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for types.
7116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsSmi(CallRuntime* call) {
7117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
71203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value);
71213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
7126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
71293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HHasInstanceTypeAndBranch* result =
71303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HHasInstanceTypeAndBranch(value,
71313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                            FIRST_SPEC_OBJECT_TYPE,
71323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                            LAST_SPEC_OBJECT_TYPE);
71333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsFunction(CallRuntime* call) {
7138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
71413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HHasInstanceTypeAndBranch* result =
71423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE);
71433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
7148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
71513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HHasCachedArrayIndexAndBranch* result =
71523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HHasCachedArrayIndexAndBranch(value);
71533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsArray(CallRuntime* call) {
7158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
71613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HHasInstanceTypeAndBranch* result =
71623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE);
71633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
7168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
71713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HHasInstanceTypeAndBranch* result =
71723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE);
71733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsObject(CallRuntime* call) {
7178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
71813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value);
71823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
7187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("inlined runtime function: IsNonNegativeSmi");
7188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
7192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(call->arguments()->length() == 1);
7193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* value = Pop();
71953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HIsUndetectableAndBranch* result =
71963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HIsUndetectableAndBranch(value);
71973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
7202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    CallRuntime* call) {
7203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout(
7204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
7205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
72081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Support for construct call checks.
7209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
7210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 0);
72118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (function_state()->outer() != NULL) {
72123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We are generating graph for inlined function.
72133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HValue* value = function_state()->is_construct()
72143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ? graph()->GetConstantTrue()
72153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : graph()->GetConstantFalse();
72163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ast_context()->ReturnValue(value);
72178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
72183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch,
72193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                        call->id());
72208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
7221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for arguments.length and arguments[?].
7225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
722642effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // Our implementation of arguments (based on this stack frame or an
722742effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // adapter below it) does not work for inlined functions.  This runtime
722842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // function is blacklisted by AstNode::IsInlineable.
722942effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  ASSERT(function_state()->outer() == NULL);
7230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 0);
72318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
72328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HArgumentsLength* result = new(zone()) HArgumentsLength(elements);
72333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateArguments(CallRuntime* call) {
723842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // Our implementation of arguments (based on this stack frame or an
723942effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // adapter below it) does not work for inlined functions.  This runtime
724042effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  // function is blacklisted by AstNode::IsInlineable.
724142effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch  ASSERT(function_state()->outer() == NULL);
7242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* index = Pop();
72458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
72468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements));
72478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HAccessArgumentsAt* result =
72488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HAccessArgumentsAt(elements, length, index);
72493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for accessing the class and value fields of an object.
7254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateClassOf(CallRuntime* call) {
7255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The special form detected by IsClassOfTest is detected before we get here
7256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // and does not cause a bailout.
7257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("inlined runtime function: ClassOf");
7258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateValueOf(CallRuntime* call) {
7262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
72658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HValueOf* result = new(zone()) HValueOf(value);
72663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
72703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::GenerateDateField(CallRuntime* call) {
72713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(call->arguments()->length() == 2);
72723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral());
72733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle()));
72743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
72753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HValue* date = Pop();
72763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HDateField* result = new(zone()) HDateField(date, index);
72773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ast_context()->ReturnInstruction(result, call->id());
72783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
72793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
72803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
72823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(call->arguments()->length() == 2);
72833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
72843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
72853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HValue* value = Pop();
72863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HValue* object = Pop();
72873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if object is a not a smi.
72883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(object);
72893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* if_smi = graph()->CreateBasicBlock();
72903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* if_heap_object = graph()->CreateBasicBlock();
72913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* join = graph()->CreateBasicBlock();
72923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  smicheck->SetSuccessorAt(0, if_smi);
72933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  smicheck->SetSuccessorAt(1, if_heap_object);
72943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  current_block()->Finish(smicheck);
72953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if_smi->Goto(join);
72963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
72973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if object is a JSValue.
72983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  set_current_block(if_heap_object);
72993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HHasInstanceTypeAndBranch* typecheck =
73003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE);
73013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* if_js_value = graph()->CreateBasicBlock();
73023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* not_js_value = graph()->CreateBasicBlock();
73033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typecheck->SetSuccessorAt(0, if_js_value);
73043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typecheck->SetSuccessorAt(1, not_js_value);
73053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  current_block()->Finish(typecheck);
73063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  not_js_value->Goto(join);
73073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
73083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Create in-object property store to kValueOffset.
73093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  set_current_block(if_js_value);
73103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> name = isolate()->factory()->undefined_symbol();
73113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInstruction(new HStoreNamedField(object,
73123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      name,
73133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      value,
73143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      true,  // in-object store.
73153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      JSValue::kValueOffset));
73163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if_js_value->Goto(join);
73173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  join->SetJoinId(call->id());
73183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  set_current_block(join);
73193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ast_context()->ReturnValue(value);
7320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for charCodeAt(n).
7324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
7325e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 2);
7326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
73281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  HValue* index = Pop();
73291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  HValue* string = Pop();
73303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
73313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HStringCharCodeAt* result = BuildStringCharCodeAt(context, string, index);
73323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n].
7337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
733844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(call->arguments()->length() == 1);
7339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
734044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HValue* char_code = Pop();
73413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
73423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HStringCharFromCode* result =
73433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HStringCharFromCode(context, char_code);
73443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n].
7349e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
735044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(call->arguments()->length() == 2);
7351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
735344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HValue* index = Pop();
735444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HValue* string = Pop();
73553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HValue* context = environment()->LookupContext();
73563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index);
735744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  AddInstruction(char_code);
73583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HStringCharFromCode* result =
73593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HStringCharFromCode(context, char_code);
73603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for object equality testing.
7365e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
7366e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 2);
7367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
7369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* right = Pop();
7370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* left = Pop();
73713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HCompareObjectEqAndBranch* result =
73723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      new(zone()) HCompareObjectEqAndBranch(left, right);
73733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnControl(result, call->id());
7374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7377e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateLog(CallRuntime* call) {
7378e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // %_Log is ignored in optimized code.
73793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
7380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for Math.random().
7384e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
73853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HValue* context = environment()->LookupContext();
73863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HGlobalObject* global_object = new(zone()) HGlobalObject(context);
73873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AddInstruction(global_object);
73883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HRandom* result = new(zone()) HRandom(global_object);
73893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringAdd.
7394e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringAdd(CallRuntime* call) {
7395e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(2, call->arguments()->length());
7396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
73988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2);
7399e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(2);
74003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for SubString.
7405e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSubString(CallRuntime* call) {
7406e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(3, call->arguments()->length());
7407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
74098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3);
7410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(3);
74113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringCompare.
7416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCompare(CallRuntime* call) {
7417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(2, call->arguments()->length());
7418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
74208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
74218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::StringCompare, 2);
7422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(2);
74233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for direct calls from JavaScript to native RegExp code.
7428e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
7429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(4, call->arguments()->length());
7430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
74328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4);
7433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(4);
74343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Construct a RegExp exec result with two in-object properties.
7439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
7440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(3, call->arguments()->length());
7441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
7443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCallStub* result =
74448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3);
7445e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(3);
74463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for fast native caches.
7451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
7452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("inlined runtime function: GetFromCache");
7453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for number to string.
7457e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateNumberToString(CallRuntime* call) {
7458e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(1, call->arguments()->length());
7459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
74618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
74628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::NumberToString, 1);
7463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(1);
74643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call for custom callbacks.
7469e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateCallFunction(CallRuntime* call) {
7470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // 1 ~ The function to call is not itself an argument to the call.
7471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int arg_count = call->arguments()->length() - 1;
7472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(arg_count >= 1);  // There's always at least a receiver.
7473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < arg_count; ++i) {
7475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CHECK_ALIVE(VisitArgument(call->arguments()->at(i)));
7476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
7477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->last()));
74783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* function = Pop();
7480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
74813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
74823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Branch for function proxies, or other non-functions.
74833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HHasInstanceTypeAndBranch* typecheck =
74843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE);
74853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* if_jsfunction = graph()->CreateBasicBlock();
74863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* if_nonfunction = graph()->CreateBasicBlock();
74873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HBasicBlock* join = graph()->CreateBasicBlock();
74883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typecheck->SetSuccessorAt(0, if_jsfunction);
74893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typecheck->SetSuccessorAt(1, if_nonfunction);
74903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  current_block()->Finish(typecheck);
74913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
74923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  set_current_block(if_jsfunction);
74933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HInstruction* invoke_result = AddInstruction(
74943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new(zone()) HInvokeFunction(context, function, arg_count));
7495592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Drop(arg_count);
74963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Push(invoke_result);
74973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if_jsfunction->Goto(join);
74983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
74993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  set_current_block(if_nonfunction);
75003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HInstruction* call_result = AddInstruction(
75013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new(zone()) HCallFunction(context, function, arg_count));
75023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Drop(arg_count);
75033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Push(call_result);
75043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if_nonfunction->Goto(join);
75053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
75063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  set_current_block(join);
75073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  join->SetJoinId(call->id());
75083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ast_context()->ReturnValue(Pop());
7509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call to math functions.
7513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathPow(CallRuntime* call) {
7514e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(2, call->arguments()->length());
7515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
7517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* right = Pop();
7518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* left = Pop();
75198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HPower* result = new(zone()) HPower(left, right);
75203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathSin(CallRuntime* call) {
7525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(1, call->arguments()->length());
7526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
75288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
75298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
7530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->set_transcendental_type(TranscendentalCache::SIN);
7531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(1);
75323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathCos(CallRuntime* call) {
7537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(1, call->arguments()->length());
7538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
75408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
75418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
7542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->set_transcendental_type(TranscendentalCache::COS);
7543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(1);
75443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
75483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::GenerateMathTan(CallRuntime* call) {
75493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(1, call->arguments()->length());
75503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
75513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HValue* context = environment()->LookupContext();
75523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HCallStub* result =
75533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
75543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  result->set_transcendental_type(TranscendentalCache::TAN);
75553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Drop(1);
75563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ast_context()->ReturnInstruction(result, call->id());
75573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
75583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
75593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathLog(CallRuntime* call) {
7561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT_EQ(1, call->arguments()->length());
7562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitArgumentList(call->arguments()));
7563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  HValue* context = environment()->LookupContext();
75648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HCallStub* result =
75658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
7566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->set_transcendental_type(TranscendentalCache::LOG);
7567e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Drop(1);
75683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
7573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("inlined runtime function: MathSqrt");
7574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check whether two RegExps are equivalent
7578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
7579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("inlined runtime function: IsRegExpEquivalent");
7580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
7584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(call->arguments()->length() == 1);
7585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HValue* value = Pop();
75878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value);
75883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return ast_context()->ReturnInstruction(result, call->id());
7589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
7593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Bailout("inlined runtime function: FastAsciiArrayJoin");
7594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef CHECK_BAILOUT
7598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#undef CHECK_ALIVE
7599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(HEnvironment* outer,
7602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           Scope* scope,
7603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           Handle<JSFunction> closure)
7604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : closure_(closure),
7605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      values_(0),
7606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      assigned_variables_(4),
76073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      frame_type_(JS_FUNCTION),
7608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parameter_count_(0),
7609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      specials_count_(1),
7610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      local_count_(0),
7611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_(outer),
7612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      pop_count_(0),
7613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      push_count_(0),
76145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ast_id_(AstNode::kNoNumber) {
7615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0);
7616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(const HEnvironment* other)
7620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : values_(0),
7621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      assigned_variables_(0),
76223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      frame_type_(JS_FUNCTION),
7623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parameter_count_(0),
7624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      specials_count_(1),
7625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      local_count_(0),
7626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_(NULL),
7627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      pop_count_(0),
7628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      push_count_(0),
76295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ast_id_(other->ast_id()) {
7630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Initialize(other);
7631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
76343ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHEnvironment::HEnvironment(HEnvironment* outer,
76353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Handle<JSFunction> closure,
76363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           FrameType frame_type,
76373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           int arguments)
76383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    : closure_(closure),
76393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      values_(arguments),
76403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      assigned_variables_(0),
76413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      frame_type_(frame_type),
76423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      parameter_count_(arguments),
76433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      local_count_(0),
76443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      outer_(outer),
76453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      pop_count_(0),
76463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      push_count_(0),
76473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ast_id_(AstNode::kNoNumber) {
76483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
76493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
76503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::Initialize(int parameter_count,
7652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              int local_count,
7653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              int stack_height) {
7654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  parameter_count_ = parameter_count;
7655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  local_count_ = local_count;
7656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Avoid reallocating the temporaries' backing store on the first Push.
7658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int total = parameter_count + specials_count_ + local_count + stack_height;
7659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  values_.Initialize(total + 4);
7660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < total; ++i) values_.Add(NULL);
7661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
76649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Initialize(const HEnvironment* other) {
76659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  closure_ = other->closure();
76669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  values_.AddAll(other->values_);
76679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  assigned_variables_.AddAll(other->assigned_variables_);
76683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  frame_type_ = other->frame_type_;
76699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  parameter_count_ = other->parameter_count_;
76709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  local_count_ = other->local_count_;
76719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (other->outer_ != NULL) outer_ = other->outer_->Copy();  // Deep copy.
76729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  pop_count_ = other->pop_count_;
76739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  push_count_ = other->push_count_;
76749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ast_id_ = other->ast_id_;
76759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
76769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
76779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
7678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
7679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!block->IsLoopHeader());
7680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(values_.length() == other->values_.length());
7681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = values_.length();
7683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; ++i) {
7684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = values_[i];
7685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (value != NULL && value->IsPhi() && value->block() == block) {
7686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // There is already a phi for the i'th value.
7687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = HPhi::cast(value);
7688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Assert index is correct and that we haven't missed an incoming edge.
7689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(phi->merged_index() == i);
7690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(phi->OperandCount() == block->predecessors()->length());
7691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->AddInput(other->values_[i]);
7692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (values_[i] != other->values_[i]) {
7693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // There is a fresh value on the incoming edge, a phi is needed.
7694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(values_[i] != NULL && other->values_[i] != NULL);
76958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      HPhi* phi = new(block->zone()) HPhi(i);
7696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* old_value = values_[i];
7697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < block->predecessors()->length(); j++) {
7698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->AddInput(old_value);
7699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
7700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->AddInput(other->values_[i]);
7701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      this->values_[i] = phi;
7702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->AddPhi(phi);
7703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
77089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Bind(int index, HValue* value) {
77099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(value != NULL);
77109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (!assigned_variables_.Contains(index)) {
77119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    assigned_variables_.Add(index);
77129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
77139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  values_[index] = value;
7714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
77179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::HasExpressionAt(int index) const {
7718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return index >= parameter_count_ + specials_count_ + local_count_;
77199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
77209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
77219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
77229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::ExpressionStackIsEmpty() const {
77233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(length() >= first_expression_index());
77243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return length() == first_expression_index();
77259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
77269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
77279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
77289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
77299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  int count = index_from_top + 1;
77309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  int index = values_.length() - count;
77319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(HasExpressionAt(index));
77329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // The push count must include at least the element in question or else
77339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // the new value will not be included in this environment's history.
77349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (push_count_ < count) {
77359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // This is the same effect as popping then re-pushing 'count' elements.
77369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    pop_count_ += (count - push_count_);
77379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    push_count_ = count;
77389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
77399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  values_[index] = value;
77409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
77419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
77429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
77439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Drop(int count) {
77449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  for (int i = 0; i < count; ++i) {
77459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Pop();
7746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::Copy() const {
77518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(closure()->GetIsolate()->zone()) HEnvironment(this);
7752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyWithoutHistory() const {
7756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* result = Copy();
7757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->ClearHistory();
7758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
7759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
7763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* new_env = Copy();
7764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < values_.length(); ++i) {
77658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HPhi* phi = new(loop_header->zone()) HPhi(i);
7766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    phi->AddInput(values_[i]);
7767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_env->values_[i] = phi;
7768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    loop_header->AddPhi(phi);
7769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  new_env->ClearHistory();
7771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return new_env;
7772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
77753ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
77763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  Handle<JSFunction> target,
77773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  FrameType frame_type,
77783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  int arguments) const {
77793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEnvironment* new_env = new(closure()->GetIsolate()->zone())
77803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HEnvironment(outer, target, frame_type, arguments + 1);
77813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i <= arguments; ++i) {  // Include receiver.
77823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    new_env->Push(ExpressionStackAt(arguments - i));
77833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
77843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_env->ClearHistory();
77853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return new_env;
77863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
77873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
77883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHEnvironment* HEnvironment::CopyForInlining(
7790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<JSFunction> target,
77913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int arguments,
7792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    FunctionLiteral* function,
7793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    HConstant* undefined,
77943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallKind call_kind,
77953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_construct) const {
77963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(frame_type() == JS_FUNCTION);
77973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
77983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Zone* zone = closure()->GetIsolate()->zone();
77993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Outer environment is a copy of this one without the arguments.
7801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int arity = function->scope()->num_parameters();
78023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* outer = Copy();
78043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  outer->Drop(arguments + 1);  // Including receiver.
7805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  outer->ClearHistory();
78063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
78073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_construct) {
78083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Create artificial constructor stub environment.  The receiver should
78093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // actually be the constructor function, but we pass the newly allocated
78103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // object instead, DoComputeConstructStubFrame() relies on that.
78113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
78123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
78133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
78143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (arity != arguments) {
78153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Create artificial arguments adaptation environment.
78163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
78173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
78183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
78198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HEnvironment* inner =
78208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      new(zone) HEnvironment(outer, function->scope(), target);
7821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Get the argument values from the original environment.
78223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i <= arity; ++i) {  // Include receiver.
78233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HValue* push = (i <= arguments) ?
78243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExpressionStackAt(arguments - i) : undefined;
78253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    inner->SetValueAt(i, push);
78263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
78273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // If the function we are inlining is a strict mode function or a
78283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // builtin function, pass undefined as the receiver for function
78293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // calls (instead of the global receiver).
78303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if ((target->shared()->native() || !function->is_classic_mode()) &&
78313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      call_kind == CALL_AS_FUNCTION && !is_construct) {
7832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    inner->SetValueAt(0, undefined);
7833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
78343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inner->SetValueAt(arity + 1, LookupContext());
7835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = arity + 2; i < inner->length(); ++i) {
7836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    inner->SetValueAt(i, undefined);
7837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
78398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  inner->set_ast_id(AstNode::kFunctionEntryId);
7840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return inner;
7841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintTo(StringStream* stream) {
78459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  for (int i = 0; i < length(); i++) {
7846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (i == 0) stream->Add("parameters\n");
7847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (i == parameter_count()) stream->Add("specials\n");
7848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (i == parameter_count() + specials_count()) stream->Add("locals\n");
7849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (i == parameter_count() + specials_count() + local_count()) {
78503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      stream->Add("expressions\n");
7851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
7852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* val = values_.at(i);
7853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    stream->Add("%d: ", i);
7854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (val != NULL) {
7855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      val->PrintNameTo(stream);
7856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
7857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      stream->Add("NULL");
7858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    stream->Add("\n");
7860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
78613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrintF("\n");
7862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintToStd() {
7866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HeapStringAllocator string_allocator;
7867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StringStream trace(&string_allocator);
7868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintTo(&trace);
7869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("%s", *trace.ToCString());
7870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceCompilation(FunctionLiteral* function) {
7874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Tag tag(this, "compilation");
7875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<String> name = function->debug_name();
7876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("name", *name->ToCString());
7877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("method", *name->ToCString());
7878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis()));
7879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLithium(const char* name, LChunk* chunk) {
7883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Trace(name, chunk->graph(), chunk);
7884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceHydrogen(const char* name, HGraph* graph) {
7888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Trace(name, graph, NULL);
7889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
7893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Tag tag(this, "cfg");
7894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("name", name);
7895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<HBasicBlock*>* blocks = graph->blocks();
7896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks->length(); i++) {
7897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* current = blocks->at(i);
7898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Tag block_tag(this, "block");
7899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintBlockProperty("name", current->block_id());
7900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintIntProperty("from_bci", -1);
7901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintIntProperty("to_bci", -1);
7902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!current->predecessors()->is_empty()) {
7904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintIndent();
7905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add("predecessors");
7906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < current->predecessors()->length(); ++j) {
7907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
7908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
7909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add("\n");
7910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
7911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintEmptyProperty("predecessors");
7912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
79143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (current->end()->SuccessorCount() == 0) {
7915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintEmptyProperty("successors");
79163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else  {
79173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      PrintIndent();
79183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      trace_.Add("successors");
79193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
79203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        trace_.Add(" \"B%d\"", it.Current()->block_id());
79213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
79223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      trace_.Add("\n");
7923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintEmptyProperty("xhandlers");
79263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const char* flags = current->IsLoopSuccessorDominator()
79273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ? "dom-loop-succ"
79283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : "";
79293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintStringProperty("flags", flags);
7930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->dominator() != NULL) {
7932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintBlockProperty("dominator", current->dominator()->block_id());
7933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7935589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    PrintIntProperty("loop_depth", current->LoopNestingDepth());
7936589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
7937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (chunk != NULL) {
7938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int first_index = current->first_instruction_index();
7939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int last_index = current->last_instruction_index();
7940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintIntProperty(
7941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          "first_lir_id",
7942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          LifetimePosition::FromInstructionIndex(first_index).Value());
7943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintIntProperty(
7944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          "last_lir_id",
7945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          LifetimePosition::FromInstructionIndex(last_index).Value());
7946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    {
7949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag states_tag(this, "states");
7950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag locals_tag(this, "locals");
7951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int total = current->phis()->length();
7952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      PrintIntProperty("size", current->phis()->length());
7953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      PrintStringProperty("method", "None");
7954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < total; ++j) {
7955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HPhi* phi = current->phis()->at(j);
7956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        PrintIndent();
7957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add("%d ", phi->merged_index());
7958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->PrintNameTo(&trace_);
7959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" ");
7960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->PrintTo(&trace_);
7961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add("\n");
7962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
7963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    {
7966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag HIR_tag(this, "HIR");
7967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instruction = current->first();
7968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      while (instruction != NULL) {
7969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int bci = 0;
7970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        int uses = instruction->UseCount();
7971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        PrintIndent();
7972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add("%d %d ", bci, uses);
7973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instruction->PrintNameTo(&trace_);
7974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" ");
7975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instruction->PrintTo(&trace_);
7976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" <|@\n");
7977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instruction = instruction->next();
7978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
7979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (chunk != NULL) {
7983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag LIR_tag(this, "LIR");
7984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int first_index = current->first_instruction_index();
7985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int last_index = current->last_instruction_index();
7986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (first_index != -1 && last_index != -1) {
7987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        const ZoneList<LInstruction*>* instructions = chunk->instructions();
7988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        for (int i = first_index; i <= last_index; ++i) {
7989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          LInstruction* linstr = instructions->at(i);
7990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (linstr != NULL) {
7991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            PrintIndent();
7992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            trace_.Add("%d ",
7993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       LifetimePosition::FromInstructionIndex(i).Value());
7994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            linstr->PrintTo(&trace_);
7995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            trace_.Add(" <|@\n");
7996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
7997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
7998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
7999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
8000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
8005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Tag tag(this, "intervals");
8006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("name", name);
8007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
800844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
8009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < fixed_d->length(); ++i) {
8010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceLiveRange(fixed_d->at(i), "fixed");
8011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
801344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
8014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < fixed->length(); ++i) {
8015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceLiveRange(fixed->at(i), "fixed");
8016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
8019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < live_ranges->length(); ++i) {
8020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceLiveRange(live_ranges->at(i), "object");
8021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRange(LiveRange* range, const char* type) {
8026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (range != NULL && !range->IsEmpty()) {
8027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    PrintIndent();
8028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    trace_.Add("%d %s", range->id(), type);
8029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (range->HasRegisterAssigned()) {
80303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LOperand* op = range->CreateAssignedOperand(ZONE);
8031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int assigned_reg = op->index();
8032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (op->IsDoubleRegister()) {
8033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"%s\"",
8034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   DoubleRegister::AllocationIndexToString(assigned_reg));
8035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
8036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(op->IsRegister());
8037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg));
8038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
8039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (range->IsSpilled()) {
8040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      LOperand* op = range->TopLevel()->GetSpillOperand();
8041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (op->IsDoubleStackSlot()) {
8042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"double_stack:%d\"", op->index());
8043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
8044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(op->IsStackSlot());
8045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"stack:%d\"", op->index());
8046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
8047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
8048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int parent_index = -1;
8049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (range->IsChild()) {
8050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parent_index = range->parent()->id();
8051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
8052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parent_index = range->id();
8053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
8054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LOperand* op = range->FirstHint();
8055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int hint_index = -1;
80563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (op != NULL && op->IsUnallocated()) {
80573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      hint_index = LUnallocated::cast(op)->virtual_register();
80583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    trace_.Add(" %d %d", parent_index, hint_index);
8060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    UseInterval* cur_interval = range->first_interval();
8061e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    while (cur_interval != NULL && range->Covers(cur_interval->start())) {
8062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add(" [%d, %d[",
8063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 cur_interval->start().Value(),
8064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 cur_interval->end().Value());
8065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      cur_interval = cur_interval->next();
8066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
8067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    UsePosition* current_pos = range->first_pos();
8069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current_pos != NULL) {
8070e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
8071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" %d M", current_pos->pos().Value());
8072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
8073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current_pos = current_pos->next();
8074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
8075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    trace_.Add(" \"\"\n");
8077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::FlushToFile() {
8082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AppendChars(filename_, *trace_.ToCString(), trace_.length(), false);
8083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  trace_.Reset();
8084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
808744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HStatistics::Initialize(CompilationInfo* info) {
808844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  source_size_ += info->shared_info()->SourceSize();
808944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
809044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
809144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStatistics::Print() {
8093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("Timing results:\n");
8094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int64_t sum = 0;
8095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < timing_.length(); ++i) {
8096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    sum += timing_[i];
8097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < names_.length(); ++i) {
8100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("%30s", names_[i]);
8101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    double ms = static_cast<double>(timing_[i]) / 1000;
8102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    double percent = static_cast<double>(timing_[i]) * 100 / sum;
8103b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    PrintF(" - %7.3f ms / %4.1f %% ", ms, percent);
8104b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
8105b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    unsigned size = sizes_[i];
8106b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    double size_percent = static_cast<double>(size) * 100 / total_size_;
8107b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    PrintF(" %8u bytes / %4.1f %%\n", size, size_percent);
8108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
810944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  double source_size_in_kb = static_cast<double>(source_size_) / 1024;
811044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  double normalized_time =  source_size_in_kb > 0
811144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? (static_cast<double>(sum) / 1000) / source_size_in_kb
811244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : 0;
811344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  double normalized_bytes = source_size_in_kb > 0
811444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? total_size_ / source_size_in_kb
811544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : 0;
811644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  PrintF("%30s - %7.3f ms           %7.3f bytes\n", "Sum",
811744f0eee88ff00398ff7f715fab053374d808c90dSteve Block         normalized_time, normalized_bytes);
8118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("---------------------------------------------------------------\n");
8119b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  PrintF("%30s - %7.3f ms (%.1f times slower than full code gen)\n",
8120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         "Total",
8121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         static_cast<double>(total_) / 1000,
8122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         static_cast<double>(total_) / full_code_gen_);
8123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8126b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid HStatistics::SaveTiming(const char* name, int64_t ticks, unsigned size) {
8127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (name == HPhase::kFullCodeGen) {
8128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    full_code_gen_ += ticks;
8129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (name == HPhase::kTotal) {
8130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    total_ += ticks;
8131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
8132b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    total_size_ += size;
8133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < names_.length(); ++i) {
8134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (names_[i] == name) {
8135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        timing_[i] += ticks;
8136b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        sizes_[i] += size;
8137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return;
8138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
8139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
8140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    names_.Add(name);
8141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    timing_.Add(ticks);
8142b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    sizes_.Add(size);
8143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kFullCodeGen = "Full code generator";
8148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kTotal = "Total";
8149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::Begin(const char* name,
8152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   HGraph* graph,
8153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   LChunk* chunk,
8154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   LAllocator* allocator) {
8155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  name_ = name;
8156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_ = graph;
8157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  chunk_ = chunk;
8158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  allocator_ = allocator;
8159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (allocator != NULL && chunk_ == NULL) {
8160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    chunk_ = allocator->chunk();
8161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
816244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_hydrogen_stats) start_ = OS::Ticks();
8163b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  start_allocation_size_ = Zone::allocation_size_;
8164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::End() const {
816844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_hydrogen_stats) {
8169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int64_t end = OS::Ticks();
8170b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    unsigned size = Zone::allocation_size_ - start_allocation_size_;
8171b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    HStatistics::Instance()->SaveTiming(name_, end - start_, size);
8172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
81743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Produce trace output if flag is set so that the first letter of the
81753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // phase name matches the command line parameter FLAG_trace_phase.
81763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_hydrogen &&
81773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL) {
8178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_);
8179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_);
8180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (allocator_ != NULL) {
8181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HTracer::Instance()->TraceLiveRanges(name_, allocator_);
8182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
8183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
8184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
81863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (graph_ != NULL) graph_->Verify(false);  // No full verify.
8187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (allocator_ != NULL) allocator_->Verify();
8188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
8189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
8190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} }  // namespace v8::internal
8192