hydrogen.cc revision 086aeeaae12517475c22695a200be45495516549
1b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Copyright 2010 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
28b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "hydrogen.h"
29b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "codegen.h"
31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "data-flow.h"
32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h"
33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "hashmap.h"
34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "lithium-allocator.h"
35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "parser.h"
36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "scopes.h"
37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
38b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#if V8_TARGET_ARCH_IA32
39b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "ia32/lithium-codegen-ia32.h"
40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#elif V8_TARGET_ARCH_X64
41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "x64/lithium-codegen-x64.h"
42b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#elif V8_TARGET_ARCH_ARM
43b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "arm/lithium-codegen-arm.h"
44b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#else
45b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#error Unsupported target architecture.
46b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
47b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 {
49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal {
50b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
51b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock::HBasicBlock(HGraph* graph)
52b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : block_id_(graph->GetNextBlockID()),
53b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      graph_(graph),
54b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phis_(4),
55b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      first_(NULL),
56b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      last_(NULL),
57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      end_(NULL),
58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      loop_information_(NULL),
59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      predecessors_(2),
60b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      dominator_(NULL),
61b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      dominated_blocks_(4),
62b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      last_environment_(NULL),
63b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      argument_count_(-1),
64b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      first_instruction_index_(-1),
65b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      last_instruction_index_(-1),
66b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      deleted_phis_(4),
67b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      is_inline_return_target_(false) {
68b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
69b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
70b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
71b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AttachLoopInformation() {
72b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsLoopHeader());
73b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  loop_information_ = new HLoopInformation(this);
74b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
75b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::DetachLoopInformation() {
78b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(IsLoopHeader());
79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  loop_information_ = NULL;
80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddPhi(HPhi* phi) {
84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsStartBlock());
85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phis_.Add(phi);
86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phi->SetBlock(this);
87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::RemovePhi(HPhi* phi) {
91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(phi->block() == this);
92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(phis_.Contains(phi));
93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(phi->HasNoUses());
94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phi->ClearOperands();
95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phis_.RemoveElement(phi);
96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phi->SetBlock(NULL);
97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddInstruction(HInstruction* instr) {
101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsStartBlock() || !IsFinished());
102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!instr->IsLinked());
103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsFinished());
104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (first_ == NULL) {
105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBlockEntry* entry = new HBlockEntry();
106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    entry->InitializeAsFirst(this);
107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    first_ = entry;
108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->InsertAfter(GetLastInstruction());
110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HBasicBlock::GetLastInstruction() {
114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (end_ != NULL) return end_->previous();
115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (first_ == NULL) return NULL;
116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (last_ == NULL) last_ = first_;
117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (last_->next() != NULL) last_ = last_->next();
118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return last_;
119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHSimulate* HBasicBlock::CreateSimulate(int id) {
123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(HasEnvironment());
124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* environment = last_environment();
125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(id == AstNode::kNoNumber ||
126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         environment->closure()->shared()->VerifyBailoutId(id));
127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int push_count = environment->push_count();
129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int pop_count = environment->pop_count();
130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  int length = environment->length();
132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSimulate* instr = new HSimulate(id, pop_count, length);
133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = push_count - 1; i >= 0; --i) {
134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->AddPushedValue(environment->ExpressionStackAt(i));
135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < environment->assigned_variables()->length(); ++i) {
137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int index = environment->assigned_variables()->at(i);
138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->AddAssignedValue(index, environment->Lookup(index));
139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  environment->ClearHistory();
141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Finish(HControlInstruction* end) {
146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!IsFinished());
147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(end);
148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  end_ = end;
149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (end->FirstSuccessor() != NULL) {
150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    end->FirstSuccessor()->RegisterPredecessor(this);
151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (end->SecondSuccessor() != NULL) {
152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      end->SecondSuccessor()->RegisterPredecessor(this);
153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Goto(HBasicBlock* block, bool include_stack_check) {
159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddSimulate(AstNode::kNoNumber);
160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGoto* instr = new HGoto(block);
161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_include_stack_check(include_stack_check);
162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Finish(instr);
163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!HasEnvironment());
168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(first() == NULL);
169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UpdateEnvironment(env);
170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::SetJoinId(int id) {
174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = predecessors_.length();
175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(length > 0);
176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; i++) {
177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* predecessor = predecessors_[i];
178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(predecessor->end()->IsGoto());
179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HSimulate* simulate = HSimulate::cast(predecessor->GetLastInstruction());
180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // We only need to verify the ID once.
181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(i != 0 ||
182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           predecessor->last_environment()->closure()->shared()
183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               ->VerifyBailoutId(id));
184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    simulate->set_ast_id(id);
185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HBasicBlock::Dominates(HBasicBlock* other) const {
190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* current = other->dominator();
191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (current != NULL) {
192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current == this) return true;
193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current = current->dominator();
194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return false;
196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(IsLoopHeader());
201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetJoinId(stmt->EntryId());
203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (predecessors()->length() == 1) {
204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // This is a degenerated loop.
205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    DetachLoopInformation();
206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Only the first entry into the loop is from outside the loop. All other
210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // entries must be back edges.
211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 1; i < predecessors()->length(); ++i) {
212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    loop_information()->RegisterBackEdge(predecessors()->at(i));
213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!predecessors_.is_empty()) {
219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Only loop header blocks can have a predecessor added after
220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // instructions have been added to the block (they have phis for all
221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // values in the environment, these phis may be eliminated later).
222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(IsLoopHeader() || first_ == NULL);
223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HEnvironment* incoming_env = pred->last_environment();
224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (IsLoopHeader()) {
2259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ASSERT(phis()->length() == incoming_env->length());
226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int i = 0; i < phis_.length(); ++i) {
227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phis_[i]->AddInput(incoming_env->values()->at(i));
228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      last_environment()->AddIncomingEdge(this, pred->last_environment());
231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (!HasEnvironment() && !IsFinished()) {
233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!IsLoopHeader());
234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetInitialEnvironment(pred->last_environment()->Copy());
235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  predecessors_.Add(pred);
238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!dominated_blocks_.Contains(block));
243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Keep the list of dominated blocks sorted such that if there is two
244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // succeeding block in this list, the predecessor is before the successor.
245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = 0;
246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (index < dominated_blocks_.length() &&
247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         dominated_blocks_[index]->block_id() < block->block_id()) {
248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ++index;
249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  dominated_blocks_.InsertAt(index, block);
251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (dominator_ == NULL) {
256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    dominator_ = other;
257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    other->AddDominatedBlock(this);
258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (other->dominator() != NULL) {
259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* first = dominator_;
260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* second = other;
261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (first != second) {
263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (first->block_id() > second->block_id()) {
264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        first = first->dominator();
265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        second = second->dominator();
267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(first != NULL && second != NULL);
269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (dominator_ != first) {
272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(dominator_->dominated_blocks_.Contains(this));
273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      dominator_->dominated_blocks_.RemoveElement(this);
274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      dominator_ = first;
275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      first->AddDominatedBlock(this);
276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const {
282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < predecessors_.length(); ++i) {
283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (predecessors_[i] == predecessor) return i;
284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UNREACHABLE();
286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return -1;
287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Verify() {
292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check that every block is finished.
293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(IsFinished());
294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(block_id() >= 0);
295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Verify that all blocks targetting a branch target, have the same boolean
297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // value on top of their expression stack.
298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!cond().is_null()) {
299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(predecessors()->length() > 0);
300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 1; i < predecessors()->length(); i++) {
301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* pred = predecessors()->at(i);
302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* top = pred->last_environment()->Top();
303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(top->IsConstant());
304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Object* a = *HConstant::cast(top)->handle();
305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Object* b = *cond();
306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(a == b);
307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  this->back_edges_.Add(block);
315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddBlock(block);
316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HLoopInformation::GetLastBackEdge() const {
320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int max_id = -1;
321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* result = NULL;
322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < back_edges_.length(); ++i) {
323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* cur = back_edges_[i];
324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (cur->block_id() > max_id) {
325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      max_id = cur->block_id();
326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      result = cur;
327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HLoopInformation::AddBlock(HBasicBlock* block) {
334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block == loop_header()) return;
335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->parent_loop_header() == loop_header()) return;
336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->parent_loop_header() != NULL) {
337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddBlock(block->parent_loop_header());
338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    block->set_parent_loop_header(loop_header());
340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    blocks_.Add(block);
341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < block->predecessors()->length(); ++i) {
342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddBlock(block->predecessors()->at(i));
343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Checks reachability of the blocks in this graph and stores a bit in
351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the BitVector "reachable()" for every block that can be reached
352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// from the start block of the graph. If "dont_visit" is non-null, the given
353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// block is treated as if it would not be part of the graph. "visited_count()"
354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// returns the number of reachable blocks.
355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass ReachabilityAnalyzer BASE_EMBEDDED {
356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ReachabilityAnalyzer(HBasicBlock* entry_block,
358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       int block_count,
359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       HBasicBlock* dont_visit)
360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : visited_count_(0),
361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        stack_(16),
362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        reachable_(block_count),
363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        dont_visit_(dont_visit) {
364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PushBlock(entry_block);
365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Analyze();
366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int visited_count() const { return visited_count_; }
369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const BitVector* reachable() const { return &reachable_; }
370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void PushBlock(HBasicBlock* block) {
373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block != NULL && block != dont_visit_ &&
374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        !reachable_.Contains(block->block_id())) {
375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      reachable_.Add(block->block_id());
376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      stack_.Add(block);
377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      visited_count_++;
378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze() {
382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (!stack_.is_empty()) {
383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HControlInstruction* end = stack_.RemoveLast()->end();
384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushBlock(end->FirstSuccessor());
385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushBlock(end->SecondSuccessor());
386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int visited_count_;
390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HBasicBlock*> stack_;
391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BitVector reachable_;
392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* dont_visit_;
393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Verify() const {
397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); i++) {
398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = blocks_.at(i);
399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    block->Verify();
401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that every block contains at least one node and that only the last
403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // node is a control instruction.
404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = block->first();
405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(current != NULL && current->IsBlockEntry());
406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT((current->next() == NULL) == current->IsControlInstruction());
408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(current->block() == block);
409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current->Verify();
410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that successors are correctly set.
414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* first = block->end()->FirstSuccessor();
415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* second = block->end()->SecondSuccessor();
416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(second == NULL || first != NULL);
417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that the predecessor array is correct.
419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (first != NULL) {
420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(first->predecessors()->Contains(block));
421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (second != NULL) {
422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(second->predecessors()->Contains(block));
423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that phis have correct arguments.
427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < block->phis()->length(); j++) {
428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = block->phis()->at(j);
429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->Verify();
430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check that all join blocks have predecessors that end with an
433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // unconditional goto and agree on their environment node id.
434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->predecessors()->length() >= 2) {
435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int id = block->predecessors()->first()->last_environment()->ast_id();
436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int k = 0; k < block->predecessors()->length(); k++) {
437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HBasicBlock* predecessor = block->predecessors()->at(k);
438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(predecessor->end()->IsGoto());
439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(predecessor->last_environment()->ast_id() == id);
440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check special property of first block to have no predecessors.
445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(blocks_.at(0)->predecessors()->is_empty());
446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check that the graph is fully connected.
448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(analyzer.visited_count() == blocks_.length());
450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check that entry block dominator is NULL.
452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(entry_block_->dominator() == NULL);
453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check dominators.
455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); ++i) {
456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = blocks_.at(i);
457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->dominator() == NULL) {
458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Only start block may have no dominator assigned to.
459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(i == 0);
460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Assert that block is unreachable if dominator must not be visited.
462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ReachabilityAnalyzer dominator_analyzer(entry_block_,
463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                              blocks_.length(),
464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                              block->dominator());
465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(!dominator_analyzer.reachable()->Contains(block->block_id()));
466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               Object* value) {
475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!pointer->is_set()) {
476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HConstant* constant = new HConstant(Handle<Object>(value),
477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                        Representation::Tagged());
478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    constant->InsertAfter(GetConstantUndefined());
479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    pointer->set(constant);
480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return pointer->get();
482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstant1() {
486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return GetConstant(&constant_1_, Smi::FromInt(1));
487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantMinus1() {
491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return GetConstant(&constant_minus1_, Smi::FromInt(-1));
492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantTrue() {
496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return GetConstant(&constant_true_, Heap::true_value());
497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantFalse() {
501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return GetConstant(&constant_false_, Heap::false_value());
502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::AppendOptional(HSubgraph* graph,
506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               bool on_true_branch,
507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               HValue* boolean_value) {
508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(HasExit() && graph->HasExit());
509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* other_block = graph_->CreateBasicBlock();
510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* join_block = graph_->CreateBasicBlock();
511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* true_branch = other_block;
513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* false_branch = graph->entry_block();
514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (on_true_branch) {
515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    true_branch = graph->entry_block();
516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    false_branch = other_block;
517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  exit_block_->Finish(new HBranch(true_branch, false_branch, boolean_value));
520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  other_block->Goto(join_block);
521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph->exit_block()->Goto(join_block);
522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  exit_block_ = join_block;
523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::AppendJoin(HSubgraph* then_graph,
527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           HSubgraph* else_graph,
528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           AstNode* node) {
529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (then_graph->HasExit() && else_graph->HasExit()) {
530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // We need to merge, create new merge block.
531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* join_block = graph_->CreateBasicBlock();
532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    then_graph->exit_block()->Goto(join_block);
533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    else_graph->exit_block()->Goto(join_block);
534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    join_block->SetJoinId(node->id());
535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    exit_block_ = join_block;
536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (then_graph->HasExit()) {
537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    exit_block_ = then_graph->exit_block_;
538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (else_graph->HasExit()) {
539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    exit_block_ = else_graph->exit_block_;
540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    exit_block_ = NULL;
542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::ResolveContinue(IterationStatement* statement) {
547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* continue_block = BundleContinue(statement);
548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (continue_block != NULL) {
549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    exit_block_ = JoinBlocks(exit_block(),
550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             continue_block,
551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             statement->ContinueId());
552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HSubgraph::BundleBreak(BreakableStatement* statement) {
557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return BundleBreakContinue(statement, false, statement->ExitId());
558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HSubgraph::BundleContinue(IterationStatement* statement) {
562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return BundleBreakContinue(statement, true, statement->ContinueId());
563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HSubgraph::BundleBreakContinue(BreakableStatement* statement,
567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            bool is_continue,
568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            int join_id) {
569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* result = NULL;
570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<BreakContinueInfo*>* infos = break_continue_info();
571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < infos->length(); ++i) {
572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BreakContinueInfo* info = infos->at(i);
573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (info->is_continue() == is_continue &&
574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        info->target() == statement &&
575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        !info->IsResolved()) {
576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (result == NULL) {
577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        result = graph_->CreateBasicBlock();
578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      info->block()->Goto(result);
580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      info->Resolve();
581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (result != NULL) result->SetJoinId(join_id);
585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HSubgraph::JoinBlocks(HBasicBlock* a, HBasicBlock* b, int id) {
591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (a == NULL) return b;
592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (b == NULL) return a;
593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* target = graph_->CreateBasicBlock();
594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  a->Goto(target);
595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  b->Goto(target);
596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  target->SetJoinId(id);
597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return target;
598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::AppendEndless(HSubgraph* body, IterationStatement* statement) {
602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ConnectExitTo(body->entry_block());
603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  body->ResolveContinue(statement);
604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  body->ConnectExitTo(body->entry_block(), true);
605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  exit_block_ = body->BundleBreak(statement);
606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  body->entry_block()->PostProcessLoopHeader(statement);
607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::AppendDoWhile(HSubgraph* body,
611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              IterationStatement* statement,
612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              HSubgraph* go_back,
613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              HSubgraph* exit) {
614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ConnectExitTo(body->entry_block());
615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  go_back->ConnectExitTo(body->entry_block(), true);
616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* break_block = body->BundleBreak(statement);
618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  exit_block_ =
619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      JoinBlocks(exit->exit_block(), break_block, statement->ExitId());
620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  body->entry_block()->PostProcessLoopHeader(statement);
621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::AppendWhile(HSubgraph* condition,
625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            HSubgraph* body,
626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            IterationStatement* statement,
627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            HSubgraph* continue_subgraph,
628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            HSubgraph* exit) {
629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ConnectExitTo(condition->entry_block());
630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* break_block = body->BundleBreak(statement);
632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  exit_block_ =
633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      JoinBlocks(exit->exit_block(), break_block, statement->ExitId());
634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (continue_subgraph != NULL) {
636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    body->ConnectExitTo(continue_subgraph->entry_block(), true);
637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    continue_subgraph->entry_block()->SetJoinId(statement->EntryId());
638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    exit_block_ = JoinBlocks(exit_block_,
639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             continue_subgraph->exit_block(),
640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             statement->ExitId());
641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    body->ConnectExitTo(condition->entry_block(), true);
643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  condition->entry_block()->PostProcessLoopHeader(statement);
645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::Append(HSubgraph* next, BreakableStatement* stmt) {
649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  exit_block_->Goto(next->entry_block());
650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  exit_block_ = next->exit_block_;
651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (stmt != NULL) {
653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    next->entry_block()->SetJoinId(stmt->EntryId());
654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* break_block = next->BundleBreak(stmt);
655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    exit_block_ = JoinBlocks(exit_block(), break_block, stmt->ExitId());
656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::FinishExit(HControlInstruction* instruction) {
661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(HasExit());
662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  exit_block_->Finish(instruction);
663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  exit_block_->ClearEnvironment();
664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  exit_block_ = NULL;
665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::FinishBreakContinue(BreakableStatement* target,
669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    bool is_continue) {
670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!exit_block_->IsFinished());
671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BreakContinueInfo* info = new BreakContinueInfo(target, exit_block_,
672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  is_continue);
673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  break_continue_info_.Add(info);
674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  exit_block_ = NULL;
675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHGraph::HGraph(CompilationInfo* info)
679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : HSubgraph(this),
680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      next_block_id_(0),
681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      info_(info),
682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      blocks_(8),
683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      values_(16),
684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi_list_(NULL) {
685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  start_environment_ = new HEnvironment(NULL, info->scope(), info->closure());
686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  start_environment_->set_ast_id(info->function()->id());
687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHandle<Code> HGraph::Compile() {
691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int values = GetMaximumValueID();
692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (values > LAllocator::max_initial_value_ids()) {
693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (FLAG_trace_bailout) PrintF("Function is too big\n");
694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return Handle<Code>::null();
695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LAllocator allocator(values, this);
698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LChunkBuilder builder(this, &allocator);
699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LChunk* chunk = builder.Build();
700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (chunk == NULL) return Handle<Code>::null();
701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!FLAG_alloc_lithium) return Handle<Code>::null();
703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  allocator.Allocate(chunk);
705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!FLAG_use_lithium) return Handle<Code>::null();
707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  MacroAssembler assembler(NULL, 0);
709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LCodeGen generator(chunk, &assembler, info());
710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_eliminate_empty_blocks) {
712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    chunk->MarkEmptyBlocks();
713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (generator.GenerateCode()) {
716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (FLAG_trace_codegen) {
717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintF("Crankshaft Compiler - ");
718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CodeGenerator::MakeCodePrologue(info());
720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Code::Flags flags =
721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Code::ComputeFlags(Code::OPTIMIZED_FUNCTION, NOT_IN_LOOP);
722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Code> code =
723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        CodeGenerator::MakeCodeEpilogue(&assembler, flags, info());
724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    generator.FinishCode(code);
725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CodeGenerator::PrintCode(code, info());
726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return code;
727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Handle<Code>::null();
729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraph::CreateBasicBlock() {
733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* result = new HBasicBlock(this);
734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  blocks_.Add(result);
735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Canonicalize() {
740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Canonicalize", this);
741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_use_canonicalizing) {
742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < blocks()->length(); ++i) {
743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* b = blocks()->at(i);
744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (HInstruction* insn = b->first(); insn != NULL; insn = insn->next()) {
745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* value = insn->Canonicalize();
746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (value != insn) {
747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (value != NULL) {
748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            insn->ReplaceAndDelete(value);
749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else {
750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            insn->Delete();
751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::OrderBlocks() {
760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Block ordering");
761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BitVector visited(blocks_.length());
762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HBasicBlock*> reverse_result(8);
764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* start = blocks_[0];
765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Postorder(start, &visited, &reverse_result, NULL);
766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  blocks_.Clear();
768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = 0;
769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = reverse_result.length() - 1; i >= 0; --i) {
770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* b = reverse_result[i];
771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    blocks_.Add(b);
772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    b->set_block_id(index++);
773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::PostorderLoopBlocks(HLoopInformation* loop,
778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 BitVector* visited,
779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 ZoneList<HBasicBlock*>* order,
780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 HBasicBlock* loop_header) {
781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < loop->blocks()->length(); ++i) {
782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* b = loop->blocks()->at(i);
783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Postorder(b->end()->SecondSuccessor(), visited, order, loop_header);
784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Postorder(b->end()->FirstSuccessor(), visited, order, loop_header);
785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (b->IsLoopHeader() && b != loop->loop_header()) {
786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PostorderLoopBlocks(b->loop_information(), visited, order, loop_header);
787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Postorder(HBasicBlock* block,
793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       BitVector* visited,
794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       ZoneList<HBasicBlock*>* order,
795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       HBasicBlock* loop_header) {
796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block == NULL || visited->Contains(block->block_id())) return;
797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->parent_loop_header() != loop_header) return;
798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  visited->Add(block->block_id());
799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->IsLoopHeader()) {
800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PostorderLoopBlocks(block->loop_information(), visited, order, loop_header);
801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Postorder(block->end()->SecondSuccessor(), visited, order, block);
802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Postorder(block->end()->FirstSuccessor(), visited, order, block);
803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Postorder(block->end()->SecondSuccessor(), visited, order, loop_header);
805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Postorder(block->end()->FirstSuccessor(), visited, order, loop_header);
806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(block->end()->FirstSuccessor() == NULL ||
808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         order->Contains(block->end()->FirstSuccessor()) ||
809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         block->end()->FirstSuccessor()->IsLoopHeader());
810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(block->end()->SecondSuccessor() == NULL ||
811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         order->Contains(block->end()->SecondSuccessor()) ||
812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         block->end()->SecondSuccessor()->IsLoopHeader());
813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  order->Add(block);
814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::AssignDominators() {
818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Assign dominators", this);
819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); ++i) {
820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (blocks_[i]->IsLoopHeader()) {
821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->first());
822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < blocks_[i]->predecessors()->length(); ++j) {
824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::EliminateRedundantPhis() {
832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Phi elimination", this);
833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HValue*> uses_to_replace(2);
834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Worklist of phis that can potentially be eliminated. Initialized
836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // with all phi nodes. When elimination of a phi node modifies
837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // another phi node the modified phi node is added to the worklist.
838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HPhi*> worklist(blocks_.length());
839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); ++i) {
840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    worklist.AddAll(*blocks_[i]->phis());
841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (!worklist.is_empty()) {
844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = worklist.RemoveLast();
845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = phi->block();
846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Skip phi node if it was already replaced.
848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block == NULL) continue;
849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Get replacement value if phi is redundant.
851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = phi->GetRedundantReplacement();
852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (value != NULL) {
854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Iterate through uses finding the ones that should be
855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // replaced.
856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      const ZoneList<HValue*>* uses = phi->uses();
857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int i = 0; i < uses->length(); ++i) {
858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* use = uses->at(i);
859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (!use->block()->IsStartBlock()) {
860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          uses_to_replace.Add(use);
861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Replace the uses and add phis modified to the work list.
864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int i = 0; i < uses_to_replace.length(); ++i) {
865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* use = uses_to_replace[i];
866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->ReplaceAtUse(use, value);
867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (use->IsPhi()) worklist.Add(HPhi::cast(use));
868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      uses_to_replace.Rewind(0);
870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->RemovePhi(phi);
871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (phi->HasNoUses() &&
872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               !phi->HasReceiverOperand() &&
873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               FLAG_eliminate_dead_phis) {
874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // We can't eliminate phis that have the receiver as an operand
875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // because in case of throwing an error we need the correct
876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // receiver value in the environment to construct a corrent
877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // stack trace.
878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->RemovePhi(phi);
879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->RecordDeletedPhi(phi->merged_index());
880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraph::CollectPhis() {
886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<HBasicBlock*>* blocks = graph_->blocks();
887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  phi_list_ = new ZoneList<HPhi*>(blocks->length());
888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks->length(); ++i) {
889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < blocks->at(i)->phis()->length(); j++) {
890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = blocks->at(i)->phis()->at(j);
891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi_list_->Add(phi);
892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // We don't support phi uses of arguments for now.
893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (phi->CheckFlag(HValue::kIsArguments)) return false;
894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InferTypes(ZoneList<HValue*>* worklist) {
901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BitVector in_worklist(GetMaximumValueID());
902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < worklist->length(); ++i) {
903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!in_worklist.Contains(worklist->at(i)->id()));
904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    in_worklist.Add(worklist->at(i)->id());
905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (!worklist->is_empty()) {
908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* current = worklist->RemoveLast();
909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    in_worklist.Remove(current->id());
910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->UpdateInferredType()) {
911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < current->uses()->length(); j++) {
912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* use = current->uses()->at(j);
913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (!in_worklist.Contains(use->id())) {
914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          in_worklist.Add(use->id());
915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          worklist->Add(use);
916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HRangeAnalysis BASE_EMBEDDED {
924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit HRangeAnalysis(HGraph* graph) : graph_(graph), changed_ranges_(16) {}
926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze();
928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void TraceRange(const char* msg, ...);
931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze(HBasicBlock* block);
932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferControlFlowRange(HBranch* branch, HBasicBlock* dest);
933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferControlFlowRange(Token::Value op, HValue* value, HValue* other);
934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferPhiRange(HPhi* phi);
935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferRange(HValue* value);
936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void RollBackTo(int index);
937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AddRange(HValue* value, Range* range);
938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HValue*> changed_ranges_;
941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::TraceRange(const char* msg, ...) {
945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_range) {
946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_list arguments;
947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_start(arguments, msg);
948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    OS::VPrint(msg, arguments);
949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_end(arguments);
950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::Analyze() {
955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Range analysis", graph_);
956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Analyze(graph_->blocks()->at(0));
957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::Analyze(HBasicBlock* block) {
961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("Analyzing block B%d\n", block->block_id());
962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int last_changed_range = changed_ranges_.length() - 1;
964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Infer range based on control flow.
966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->predecessors()->length() == 1) {
967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* pred = block->predecessors()->first();
968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (pred->end()->IsBranch()) {
969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InferControlFlowRange(HBranch::cast(pred->end()), block);
970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Process phi instructions.
974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < block->phis()->length(); ++i) {
975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = block->phis()->at(i);
976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferPhiRange(phi);
977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Go through all instructions of the current block.
980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = block->first();
981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (instr != block->end()) {
982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferRange(instr);
983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = instr->next();
984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Continue analysis in all dominated blocks.
987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Analyze(block->dominated_blocks()->at(i));
989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RollBackTo(last_changed_range);
992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferControlFlowRange(HBranch* branch, HBasicBlock* dest) {
996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(branch->FirstSuccessor() == dest || branch->SecondSuccessor() == dest);
997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(branch->FirstSuccessor() != dest || branch->SecondSuccessor() != dest);
998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (branch->value()->IsCompare()) {
1000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HCompare* compare = HCompare::cast(branch->value());
1001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Token::Value op = compare->token();
1002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (branch->SecondSuccessor() == dest) {
1003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      op = Token::NegateCompareOp(op);
1004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Token::Value inverted_op = Token::InvertCompareOp(op);
1006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferControlFlowRange(op, compare->left(), compare->right());
1007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferControlFlowRange(inverted_op, compare->right(), compare->left());
1008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// We know that value [op] other. Use this information to update the range on
1013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// value.
1014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferControlFlowRange(Token::Value op,
1015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                           HValue* value,
1016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                           HValue* other) {
1017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Range* range = other->range();
1018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (range == NULL) range = new Range();
1019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Range* new_range = NULL;
1020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("Control flow range infer %d %s %d\n",
1022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             value->id(),
1023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             Token::Name(op),
1024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             other->id());
1025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (op == Token::EQ || op == Token::EQ_STRICT) {
1027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // The same range has to apply for value.
1028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_range = range->Copy();
1029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::LT || op == Token::LTE) {
1030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_range = range->CopyClearLower();
1031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (op == Token::LT) {
1032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new_range->AddConstant(-1);
1033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::GT || op == Token::GTE) {
1035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_range = range->CopyClearUpper();
1036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (op == Token::GT) {
1037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new_range->AddConstant(1);
1038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (new_range != NULL && !new_range->IsMostGeneric()) {
1042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddRange(value, new_range);
1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferPhiRange(HPhi* phi) {
1048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(twuerthinger): Infer loop phi ranges.
1049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  InferRange(phi);
1050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferRange(HValue* value) {
1054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!value->HasRange());
1055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!value->representation().IsNone()) {
1056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    value->ComputeInitialRange();
1057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Range* range = value->range();
1058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n",
1059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               value->id(),
1060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               value->Mnemonic(),
1061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               range->lower(),
1062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               range->upper());
1063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::RollBackTo(int index) {
1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = index + 1; i < changed_ranges_.length(); ++i) {
1069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    changed_ranges_[i]->RemoveLastAddedRange();
1070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  changed_ranges_.Rewind(index + 1);
1072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::AddRange(HValue* value, Range* range) {
1076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Range* original_range = value->range();
1077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  value->AddNewRange(range);
1078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  changed_ranges_.Add(value);
1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Range* new_range = value->range();
1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("Updated range of %d set to [%d,%d]\n",
1081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             value->id(),
1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             new_range->lower(),
1083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             new_range->upper());
1084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (original_range != NULL) {
1085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceRange("Original range was [%d,%d]\n",
1086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               original_range->lower(),
1087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               original_range->upper());
1088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceRange("New information was [%d,%d]\n",
1090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             range->lower(),
1091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             range->upper());
1092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TraceGVN(const char* msg, ...) {
1096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_gvn) {
1097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_list arguments;
1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_start(arguments, msg);
1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    OS::VPrint(msg, arguments);
1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    va_end(arguments);
1101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHValueMap::HValueMap(const HValueMap* other)
1106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : array_size_(other->array_size_),
1107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      lists_size_(other->lists_size_),
1108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      count_(other->count_),
1109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      present_flags_(other->present_flags_),
1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      array_(Zone::NewArray<HValueMapListElement>(other->array_size_)),
1111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      lists_(Zone::NewArray<HValueMapListElement>(other->lists_size_)),
1112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      free_list_head_(other->free_list_head_) {
1113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memcpy(array_, other->array_, array_size_ * sizeof(HValueMapListElement));
1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memcpy(lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement));
1115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Kill(int flags) {
1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int depends_flags = HValue::ConvertChangesToDependsFlags(flags);
1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if ((present_flags_ & depends_flags) == 0) return;
1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  present_flags_ = 0;
1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < array_size_; ++i) {
1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = array_[i].value;
1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (value != NULL) {
1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Clear list of collisions first, so we know if it becomes empty.
1126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int kept = kNil;  // List of kept elements.
1127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int next;
1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int current = array_[i].next; current != kNil; current = next) {
1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        next = lists_[current].next;
1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if ((lists_[current].value->flags() & depends_flags) != 0) {
1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          // Drop it.
1132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          count_--;
1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[current].next = free_list_head_;
1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          free_list_head_ = current;
1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else {
1136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          // Keep it.
1137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[current].next = kept;
1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          kept = current;
1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          present_flags_ |= lists_[current].value->flags();
1140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      array_[i].next = kept;
1143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Now possibly drop directly indexed element.
1145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if ((array_[i].value->flags() & depends_flags) != 0) {  // Drop it.
1146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        count_--;
1147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int head = array_[i].next;
1148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (head == kNil) {
1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          array_[i].value = NULL;
1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else {
1151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          array_[i].value = lists_[head].value;
1152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          array_[i].next = lists_[head].next;
1153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[head].next = free_list_head_;
1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          free_list_head_ = head;
1155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        present_flags_ |= array_[i].value->flags();  // Keep it.
1158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHValue* HValueMap::Lookup(HValue* value) const {
1165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint32_t hash = static_cast<uint32_t>(value->Hashcode());
1166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint32_t pos = Bound(hash);
1167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (array_[pos].value != NULL) {
1168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (array_[pos].value->Equals(value)) return array_[pos].value;
1169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int next = array_[pos].next;
1170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (next != kNil) {
1171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (lists_[next].value->Equals(value)) return lists_[next].value;
1172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      next = lists_[next].next;
1173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return NULL;
1176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Resize(int new_size) {
1180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(new_size > count_);
1181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Hashing the values into the new array has no more collisions than in the
1182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // old hash map, so we can use the existing lists_ array, if we are careful.
1183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Make sure we have at least one free element.
1185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (free_list_head_ == kNil) {
1186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ResizeLists(lists_size_ << 1);
1187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* new_array =
1190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Zone::NewArray<HValueMapListElement>(new_size);
1191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(new_array, 0, sizeof(HValueMapListElement) * new_size);
1192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* old_array = array_;
1194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int old_size = array_size_;
1195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int old_count = count_;
1197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  count_ = 0;
1198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Do not modify present_flags_.  It is currently correct.
1199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  array_size_ = new_size;
1200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  array_ = new_array;
1201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (old_array != NULL) {
1203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Iterate over all the elements in lists, rehashing them.
1204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < old_size; ++i) {
1205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (old_array[i].value != NULL) {
1206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int current = old_array[i].next;
1207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        while (current != kNil) {
1208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          Insert(lists_[current].value);
1209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          int next = lists_[current].next;
1210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          lists_[current].next = free_list_head_;
1211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          free_list_head_ = current;
1212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          current = next;
1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Rehash the directly stored value.
1215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Insert(old_array[i].value);
1216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  USE(old_count);
1220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(count_ == old_count);
1221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::ResizeLists(int new_size) {
1225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(new_size > lists_size_);
1226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* new_lists =
1228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Zone::NewArray<HValueMapListElement>(new_size);
1229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memset(new_lists, 0, sizeof(HValueMapListElement) * new_size);
1230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMapListElement* old_lists = lists_;
1232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int old_size = lists_size_;
1233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  lists_size_ = new_size;
1235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  lists_ = new_lists;
1236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (old_lists != NULL) {
1238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    memcpy(lists_, old_lists, old_size * sizeof(HValueMapListElement));
1239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = old_size; i < lists_size_; ++i) {
1241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    lists_[i].next = free_list_head_;
1242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    free_list_head_ = i;
1243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Insert(HValue* value) {
1248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(value != NULL);
1249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Resizing when half of the hashtable is filled up.
1250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (count_ >= array_size_ >> 1) Resize(array_size_ << 1);
1251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(count_ < array_size_);
1252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  count_++;
1253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint32_t pos = Bound(static_cast<uint32_t>(value->Hashcode()));
1254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (array_[pos].value == NULL) {
1255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    array_[pos].value = value;
1256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    array_[pos].next = kNil;
1257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
1258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (free_list_head_ == kNil) {
1259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ResizeLists(lists_size_ << 1);
1260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int new_element_pos = free_list_head_;
1262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(new_element_pos != kNil);
1263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    free_list_head_ = lists_[free_list_head_].next;
1264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    lists_[new_element_pos].value = value;
1265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    lists_[new_element_pos].next = array_[pos].next;
1266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value != NULL);
1267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    array_[pos].next = new_element_pos;
1268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HStackCheckEliminator BASE_EMBEDDED {
1273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
1274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { }
1275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Process();
1277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
1279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void RemoveStackCheck(HBasicBlock* block);
1280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
1282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStackCheckEliminator::Process() {
1286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // For each loop block walk the dominator tree from the backwards branch to
1287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the loop header. If a call instruction is encountered the backwards branch
1288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // is dominated by a call and the stack check in the backwards branch can be
1289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // removed.
1290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < graph_->blocks()->length(); i++) {
1291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
1293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge();
1294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* dominator = back_edge;
1295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool back_edge_dominated_by_call = false;
1296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      while (dominator != block && !back_edge_dominated_by_call) {
1297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HInstruction* instr = dominator->first();
1298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        while (instr != NULL && !back_edge_dominated_by_call) {
1299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (instr->IsCall()) {
1300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            RemoveStackCheck(back_edge);
1301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            back_edge_dominated_by_call = true;
1302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
1303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          instr = instr->next();
1304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        dominator = dominator->dominator();
1306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStackCheckEliminator::RemoveStackCheck(HBasicBlock* block) {
1313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = block->first();
1314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (instr != NULL) {
1315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (instr->IsGoto()) {
1316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HGoto::cast(instr)->set_include_stack_check(false);
1317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
1318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = instr->next();
1320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HGlobalValueNumberer BASE_EMBEDDED {
1325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
1326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit HGlobalValueNumberer(HGraph* graph)
1327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : graph_(graph),
1328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        block_side_effects_(graph_->blocks()->length()),
1329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        loop_side_effects_(graph_->blocks()->length()) {
1330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(Heap::allow_allocation(false));
1331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    block_side_effects_.AddBlock(0, graph_->blocks()->length());
1332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    loop_side_effects_.AddBlock(0, graph_->blocks()->length());
1333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ~HGlobalValueNumberer() {
1335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!Heap::allow_allocation(true));
1336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze();
1339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
1341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
1342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void ComputeBlockSideEffects();
1343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void LoopInvariantCodeMotion();
1344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void ProcessLoopBlock(HBasicBlock* block,
1345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        HBasicBlock* before_loop,
1346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        int loop_kills);
1347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
1348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
1350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // A map of block IDs to their side effects.
1352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<int> block_side_effects_;
1353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // A map of loop header block IDs to their loop's side effects.
1355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<int> loop_side_effects_;
1356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::Analyze() {
1360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ComputeBlockSideEffects();
1361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_loop_invariant_code_motion) {
1362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LoopInvariantCodeMotion();
1363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueMap* map = new HValueMap();
1365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AnalyzeBlock(graph_->blocks()->at(0), map);
1366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::ComputeBlockSideEffects() {
1370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Compute side effects for the block.
1372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* instr = block->first();
1374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int id = block->block_id();
1375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int side_effects = 0;
1376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (instr != NULL) {
1377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      side_effects |= (instr->flags() & HValue::ChangesFlagsMask());
1378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = instr->next();
1379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    block_side_effects_[id] |= side_effects;
1381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Loop headers are part of their loop.
1383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
1384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      loop_side_effects_[id] |= side_effects;
1385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Propagate loop side effects upwards.
1388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->HasParentLoopHeader()) {
1389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int header_id = block->parent_loop_header()->block_id();
1390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      loop_side_effects_[header_id] |=
1391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          block->IsLoopHeader() ? loop_side_effects_[id] : side_effects;
1392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::LoopInvariantCodeMotion() {
1398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
1401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int side_effects = loop_side_effects_[block->block_id()];
1402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n",
1403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               block->block_id(),
1404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               side_effects);
1405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* last = block->loop_information()->GetLastBackEdge();
1407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = block->block_id(); j <= last->block_id(); ++j) {
1408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects);
1409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::ProcessLoopBlock(HBasicBlock* block,
1416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            HBasicBlock* loop_header,
1417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            int loop_kills) {
1418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* pre_header = loop_header->predecessors()->at(0);
1419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
1420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n",
1421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           block->block_id(),
1422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           depends_flags);
1423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = block->first();
1424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (instr != NULL) {
1425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* next = instr->next();
1426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (instr->CheckFlag(HValue::kUseGVN) &&
1427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        (instr->flags() & depends_flags) == 0) {
1428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TraceGVN("Checking instruction %d (%s)\n",
1429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               instr->id(),
1430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               instr->Mnemonic());
1431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool inputs_loop_invariant = true;
1432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int i = 0; i < instr->OperandCount(); ++i) {
1433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) {
1434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          inputs_loop_invariant = false;
1435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (inputs_loop_invariant && ShouldMove(instr, loop_header)) {
1439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        TraceGVN("Found loop invariant instruction %d\n", instr->id());
1440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Move the instruction out of the loop.
1441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instr->Unlink();
1442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instr->InsertBefore(pre_header->end());
1443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = next;
1446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Only move instructions that postdominate the loop header (i.e. are
1450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// always executed inside the loop). This is to avoid unnecessary
1451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// deoptimizations assuming the loop is executed at least once.
1452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// TODO(fschneider): Better type feedback should give us information
1453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// about code that was never executed.
1454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
1455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                      HBasicBlock* loop_header) {
1456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!instr->IsChange() &&
1457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      FLAG_aggressive_loop_invariant_motion) return true;
1458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* block = instr->block();
1459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool result = true;
1460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block != loop_header) {
1461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 1; i < loop_header->predecessors()->length(); ++i) {
1462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool found = false;
1463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* pred = loop_header->predecessors()->at(i);
1464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      while (pred != loop_header) {
1465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (pred == block) found = true;
1466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        pred = pred->dominator();
1467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!found) {
1469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        result = false;
1470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        break;
1471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
1475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
1479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TraceGVN("Analyzing block B%d\n", block->block_id());
1480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If this is a loop header kill everything killed by the loop.
1482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (block->IsLoopHeader()) {
1483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    map->Kill(loop_side_effects_[block->block_id()]);
1484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Go through all instructions of the current block.
1487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = block->first();
1488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (instr != NULL) {
1489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* next = instr->next();
1490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int flags = (instr->flags() & HValue::ChangesFlagsMask());
1491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (flags != 0) {
1492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(!instr->CheckFlag(HValue::kUseGVN));
1493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Clear all instructions in the map that are affected by side effects.
1494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      map->Kill(flags);
1495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TraceGVN("Instruction %d kills\n", instr->id());
1496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (instr->CheckFlag(HValue::kUseGVN)) {
1497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* other = map->Lookup(instr);
1498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (other != NULL) {
1499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(instr->Equals(other) && other->Equals(instr));
1500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        TraceGVN("Replacing value %d (%s) with value %d (%s)\n",
1501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 instr->id(),
1502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 instr->Mnemonic(),
1503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 other->id(),
1504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 other->Mnemonic());
1505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instr->ReplaceValue(other);
1506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instr->Delete();
1507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
1508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        map->Add(instr);
1509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = next;
1512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Recursively continue analysis for all immediately dominated blocks.
1515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = block->dominated_blocks()->length();
1516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; ++i) {
1517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* dominated = block->dominated_blocks()->at(i);
1518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // No need to copy the map for the last child in the dominator tree.
1519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValueMap* successor_map = (i == length - 1) ? map : map->Copy();
1520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // If the dominated block is not a successor to this block we have to
1522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // kill everything killed on any path between this block and the
1523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // dominated block.  Note we rely on the block ordering.
1524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool is_successor = false;
1525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int predecessor_count = dominated->predecessors()->length();
1526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; !is_successor && j < predecessor_count; ++j) {
1527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      is_successor = (dominated->predecessors()->at(j) == block);
1528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!is_successor) {
1531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int side_effects = 0;
1532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = block->block_id() + 1; j < dominated->block_id(); ++j) {
1533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        side_effects |= block_side_effects_[j];
1534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      successor_map->Kill(side_effects);
1536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AnalyzeBlock(dominated, successor_map);
1539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HInferRepresentation BASE_EMBEDDED {
1544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
1545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit HInferRepresentation(HGraph* graph)
1546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : graph_(graph), worklist_(8), in_worklist_(graph->GetMaximumValueID()) {}
1547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Analyze();
1549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
1551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation TryChange(HValue* current);
1552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AddToWorklist(HValue* current);
1553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferBasedOnInputs(HValue* current);
1554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void AddDependantsToWorklist(HValue* current);
1555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InferBasedOnUses(HValue* current);
1556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraph* graph_;
1558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HValue*> worklist_;
1559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BitVector in_worklist_;
1560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::AddToWorklist(HValue* current) {
1564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (current->representation().IsSpecialization()) return;
1565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return;
1566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (in_worklist_.Contains(current->id())) return;
1567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  worklist_.Add(current);
1568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  in_worklist_.Add(current->id());
1569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This method tries to specialize the representation type of the value
1573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// given as a parameter. The value is asked to infer its representation type
1574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// based on its inputs. If the inferred type is more specialized, then this
1575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// becomes the new representation type of the node.
1576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::InferBasedOnInputs(HValue* current) {
1577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation r = current->representation();
1578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (r.IsSpecialization()) return;
1579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation));
1580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation inferred = current->InferredRepresentation();
1581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (inferred.IsSpecialization()) {
1582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current->ChangeRepresentation(inferred);
1583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddDependantsToWorklist(current);
1584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::AddDependantsToWorklist(HValue* current) {
1589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < current->uses()->length(); ++i) {
1590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddToWorklist(current->uses()->at(i));
1591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < current->OperandCount(); ++i) {
1593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddToWorklist(current->OperandAt(i));
1594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This method calculates whether specializing the representation of the value
1599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// given as the parameter has a benefit in terms of less necessary type
1600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// conversions. If there is a benefit, then the representation of the value is
1601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// specialized.
1602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::InferBasedOnUses(HValue* current) {
1603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation r = current->representation();
1604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (r.IsSpecialization() || current->HasNoUses()) return;
1605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation));
1606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation new_rep = TryChange(current);
1607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!new_rep.IsNone()) {
1608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!current->representation().Equals(new_rep)) {
1609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current->ChangeRepresentation(new_rep);
1610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddDependantsToWorklist(current);
1611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochRepresentation HInferRepresentation::TryChange(HValue* current) {
1617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Array of use counts for each representation.
1618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int use_count[Representation::kNumRepresentations];
1619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < Representation::kNumRepresentations; i++) {
1620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    use_count[i] = 0;
1621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < current->uses()->length(); ++i) {
1624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* use = current->uses()->at(i);
1625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int index = use->LookupOperandIndex(0, current);
1626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Representation req_rep = use->RequiredInputRepresentation(index);
1627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (req_rep.IsNone()) continue;
1628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (use->IsPhi()) {
1629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = HPhi::cast(use);
1630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->AddIndirectUsesTo(&use_count[0]);
1631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    use_count[req_rep.kind()]++;
1633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int tagged_count = use_count[Representation::kTagged];
1635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int double_count = use_count[Representation::kDouble];
1636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int int32_count = use_count[Representation::kInteger32];
1637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int non_tagged_count = double_count + int32_count;
1638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If a non-loop phi has tagged uses, don't convert it to untagged.
1640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (current->IsPhi() && !current->block()->IsLoopHeader()) {
1641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (tagged_count > 0) return Representation::None();
1642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (non_tagged_count >= tagged_count) {
1645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // More untagged than tagged.
1646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (double_count > 0) {
1647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // There is at least one usage that is a double => guess that the
1648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // correct representation is double.
1649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return Representation::Double();
1650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (int32_count > 0) {
1651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return Representation::Integer32();
1652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Representation::None();
1655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::Analyze() {
1659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Infer representations", graph_);
1660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // (1) Initialize bit vectors and count real uses. Each phi
1662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // gets a bit-vector of length <number of phis>.
1663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<HPhi*>* phi_list = graph_->phi_list();
1664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int num_phis = phi_list->length();
1665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ScopedVector<BitVector*> connected_phis(num_phis);
1666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < num_phis; i++) {
1667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    phi_list->at(i)->InitRealUses(i);
1668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    connected_phis[i] = new BitVector(num_phis);
1669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    connected_phis[i]->Add(i);
1670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // (2) Do a fixed point iteration to find the set of connected phis.
1673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // A phi is connected to another phi if its value is used either
1674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // directly or indirectly through a transitive closure of the def-use
1675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // relation.
1676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool change = true;
1677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (change) {
1678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    change = false;
1679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < num_phis; i++) {
1680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = phi_list->at(i);
1681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < phi->uses()->length(); j++) {
1682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* use = phi->uses()->at(j);
1683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (use->IsPhi()) {
1684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          int phi_use = HPhi::cast(use)->phi_id();
1685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (connected_phis[i]->UnionIsChanged(*connected_phis[phi_use])) {
1686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            change = true;
1687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
1688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // (3) Sum up the non-phi use counts of all connected phis.
1694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Don't include the non-phi uses of the phi itself.
1695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < num_phis; i++) {
1696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = phi_list->at(i);
1697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (BitVector::Iterator it(connected_phis.at(i));
1698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         !it.Done();
1699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         it.Advance()) {
1700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int index = it.Current();
1701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (index != i) {
1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HPhi* it_use = phi_list->at(it.Current());
1703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->AddNonPhiUsesFrom(it_use);
1704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < graph_->blocks()->length(); ++i) {
1709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = graph_->blocks()->at(i);
1710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const ZoneList<HPhi*>* phis = block->phis();
1711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < phis->length(); ++j) {
1712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddToWorklist(phis->at(j));
1713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = block->first();
1716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
1717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddToWorklist(current);
1718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
1719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (!worklist_.is_empty()) {
1723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* current = worklist_.RemoveLast();
1724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    in_worklist_.Remove(current->id());
1725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferBasedOnInputs(current);
1726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InferBasedOnUses(current);
1727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InitializeInferredTypes() {
1732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Inferring types", this);
1733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  InitializeInferredTypes(0, this->blocks_.length() - 1);
1734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InitializeInferredTypes(int from_inclusive, int to_inclusive) {
1738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = from_inclusive; i <= to_inclusive; ++i) {
1739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* block = blocks_[i];
1740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const ZoneList<HPhi*>* phis = block->phis();
1742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < phis->length(); j++) {
1743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phis->at(j)->UpdateInferredType();
1744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = block->first();
1747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
1748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current->UpdateInferredType();
1749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
1750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (block->IsLoopHeader()) {
1753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* last_back_edge =
1754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          block->loop_information()->GetLastBackEdge();
1755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InitializeInferredTypes(i + 1, last_back_edge->block_id());
1756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Skip all blocks already processed by the recursive call.
1757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      i = last_back_edge->block_id();
1758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Update phis of the loop header now after the whole loop body is
1759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // guaranteed to be processed.
1760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ZoneList<HValue*> worklist(block->phis()->length());
1761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < block->phis()->length(); ++j) {
1762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        worklist.Add(block->phis()->at(j));
1763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InferTypes(&worklist);
1765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) {
1771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* current = value;
1772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (current != NULL) {
1773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (visited->Contains(current->id())) return;
1774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // For phis, we must propagate the check to all of its inputs.
1776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->IsPhi()) {
1777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      visited->Add(current->id());
1778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = HPhi::cast(current);
1779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int i = 0; i < phi->OperandCount(); ++i) {
1780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PropagateMinusZeroChecks(phi->OperandAt(i), visited);
1781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
1783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // For multiplication and division, we must propagate to the left and
1786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // the right side.
1787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->IsMul()) {
1788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HMul* mul = HMul::cast(current);
1789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      mul->EnsureAndPropagateNotMinusZero(visited);
1790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(mul->left(), visited);
1791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(mul->right(), visited);
1792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (current->IsDiv()) {
1793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HDiv* div = HDiv::cast(current);
1794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      div->EnsureAndPropagateNotMinusZero(visited);
1795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(div->left(), visited);
1796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PropagateMinusZeroChecks(div->right(), visited);
1797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current = current->EnsureAndPropagateNotMinusZero(visited);
1800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChangeForUse(HValue* value,
1805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                              HValue* use,
1806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                              Representation to,
1807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                              bool is_truncating) {
1808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Propagate flags for negative zero checks upwards from conversions
1809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // int32-to-tagged and int32-to-double.
1810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation from = value->representation();
1811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (from.IsInteger32()) {
1812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(to.IsTagged() || to.IsDouble());
1813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BitVector visited(GetMaximumValueID());
1814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PropagateMinusZeroChecks(value, &visited);
1815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Insert the representation change right before its use. For phi-uses we
1818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // insert at the end of the corresponding predecessor.
1819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* insert_block = use->block();
1820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (use->IsPhi()) {
1821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int index = 0;
1822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (use->OperandAt(index) != value) ++index;
1823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    insert_block = insert_block->predecessors()->at(index);
1824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* next = (insert_block == use->block())
1827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ? HInstruction::cast(use)
1828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : insert_block->end();
1829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // For constants we try to make the representation change at compile
1831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // time. When a representation change is not possible without loss of
1832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // information we treat constants like normal instructions and insert the
1833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // change instructions for them.
1834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* new_value = NULL;
1835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (value->IsConstant()) {
1836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HConstant* constant = HConstant::cast(value);
1837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Try to create a new copy of the constant with the new representation.
1838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_value = is_truncating
1839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ? constant->CopyToTruncatedInt32()
1840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        : constant->CopyToRepresentation(to);
1841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (new_value == NULL) {
1844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_value = new HChange(value, value->representation(), to);
1845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  new_value->InsertBefore(next);
1848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  value->ReplaceFirstAtUse(use, new_value, to);
1849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint CompareConversionUses(HValue* a,
1853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          HValue* b,
1854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          Representation a_rep,
1855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                          Representation b_rep) {
1856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (a_rep.kind() > b_rep.kind()) {
1857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Make sure specializations are separated in the result array.
1858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return 1;
1859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Put truncating conversions before non-truncating conversions.
1861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool a_truncate = a->CheckFlag(HValue::kTruncatingToInt32);
1862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool b_truncate = b->CheckFlag(HValue::kTruncatingToInt32);
1863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (a_truncate != b_truncate) {
1864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return a_truncate ? -1 : 1;
1865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Sort by increasing block ID.
1867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return a->block()->block_id() - b->block()->block_id();
1868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChanges(HValue* current) {
1872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Representation r = current->representation();
1873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (r.IsNone()) return;
1874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (current->uses()->length() == 0) return;
1875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Collect the representation changes in a sorted list.  This allows
1877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // us to avoid duplicate changes without searching the list.
1878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HValue*> to_convert(2);
1879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<Representation> to_convert_reps(2);
1880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < current->uses()->length(); ++i) {
1881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* use = current->uses()->at(i);
1882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // The occurrences index means the index within the operand array of "use"
1883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // at which "current" is used. While iterating through the use array we
1884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // also have to iterate over the different occurrence indices.
1885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int occurrence_index = 0;
1886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (use->UsesMultipleTimes(current)) {
1887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      occurrence_index = current->uses()->CountOccurrences(use, 0, i - 1);
1888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_representation) {
1889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF("Instruction %d is used multiple times at %d; occurrence=%d\n",
1890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               current->id(),
1891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               use->id(),
1892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               occurrence_index);
1893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int operand_index = use->LookupOperandIndex(occurrence_index, current);
1896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Representation req = use->RequiredInputRepresentation(operand_index);
1897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (req.IsNone() || req.Equals(r)) continue;
1898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int index = 0;
1899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (to_convert.length() > index &&
1900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           CompareConversionUses(to_convert[index],
1901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 use,
1902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 to_convert_reps[index],
1903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 req) < 0) {
1904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ++index;
1905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (FLAG_trace_representation) {
1907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintF("Inserting a representation change to %s of %d for use at %d\n",
1908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             req.Mnemonic(),
1909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             current->id(),
1910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             use->id());
1911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    to_convert.InsertAt(index, use);
1913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    to_convert_reps.InsertAt(index, req);
1914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < to_convert.length(); ++i) {
1917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* use = to_convert[i];
1918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Representation r_to = to_convert_reps[i];
1919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32);
1920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InsertRepresentationChangeForUse(current, use, r_to, is_truncating);
1921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (current->uses()->is_empty()) {
1924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(current->IsConstant());
1925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current->Delete();
1926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChanges() {
1931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPhase phase("Insert representation changes", this);
1932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Compute truncation flag for phis: Initially assume that all
1935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // int32-phis allow truncation and iteratively remove the ones that
1936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // are used in an operation that does not allow a truncating
1937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // conversion.
1938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(fschneider): Replace this with a worklist-based iteration.
1939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < phi_list()->length(); i++) {
1940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = phi_list()->at(i);
1941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (phi->representation().IsInteger32()) {
1942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->SetFlag(HValue::kTruncatingToInt32);
1943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool change = true;
1946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (change) {
1947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    change = false;
1948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < phi_list()->length(); i++) {
1949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = phi_list()->at(i);
1950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue;
1951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < phi->uses()->length(); j++) {
1952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* use = phi->uses()->at(j);
1953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (!use->CheckFlag(HValue::kTruncatingToInt32)) {
1954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          phi->ClearFlag(HValue::kTruncatingToInt32);
1955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          change = true;
1956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          break;
1957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
1959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks_.length(); ++i) {
1963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Process phi instructions first.
1964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < blocks_[i]->phis()->length(); j++) {
1965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = blocks_[i]->phis()->at(j);
1966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InsertRepresentationChanges(phi);
1967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Process normal instructions.
1970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* current = blocks_[i]->first();
1971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current != NULL) {
1972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InsertRepresentationChanges(current);
1973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current = current->next();
1974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Implementation of utility classes to represent an expression's context in
1980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the AST.
1981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
1982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : owner_(owner), kind_(kind), outer_(owner->ast_context()) {
1983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner->set_ast_context(this);  // Push.
1984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
19859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  original_length_ = owner->environment()->length();
1986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
1987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAstContext::~AstContext() {
1991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner_->set_ast_context(outer_);  // Pop.
1992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochEffectContext::~EffectContext() {
1996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(owner()->HasStackOverflow() ||
1997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         !owner()->subgraph()->HasExit() ||
19989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block         owner()->environment()->length() == original_length_);
1999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochValueContext::~ValueContext() {
2003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(owner()->HasStackOverflow() ||
2004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         !owner()->subgraph()->HasExit() ||
20059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block         owner()->environment()->length() == original_length_ + 1);
2006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid EffectContext::ReturnValue(HValue* value) {
2010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The value is simply ignored.
2011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid ValueContext::ReturnValue(HValue* value) {
2015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The value is tracked in the bailout environment, and communicated
2016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // through the environment as the result of the expression.
2017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->Push(value);
2018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::ReturnValue(HValue* value) {
2022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BuildBranch(value);
2023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->AddInstruction(instr);
2028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (instr->HasSideEffects()) owner()->AddSimulate(ast_id);
2029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->AddInstruction(instr);
2034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  owner()->Push(instr);
2035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (instr->HasSideEffects()) owner()->AddSimulate(ast_id);
2036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraphBuilder* builder = owner();
2041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  builder->AddInstruction(instr);
2042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We expect a simulate after every expression with side effects, though
2043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // this one isn't actually needed (and wouldn't work if it were targeted).
2044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (instr->HasSideEffects()) {
2045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    builder->Push(instr);
2046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    builder->AddSimulate(ast_id);
2047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    builder->Pop();
2048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BuildBranch(instr);
2050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::BuildBranch(HValue* value) {
2054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We expect the graph to be in edge-split form: there is no edge that
2055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // connects a branch node to a join node.  We conservatively ensure that
2056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // property by always adding an empty block on the outgoing edges of this
2057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // branch.
2058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraphBuilder* builder = owner();
2059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
2061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBranch* branch = new HBranch(empty_true, empty_false, value);
2062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  builder->CurrentBlock()->Finish(branch);
2063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* const no_return_value = NULL;
2065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* true_target = if_true();
2066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (true_target->IsInlineReturnTarget()) {
2067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    empty_true->AddLeaveInlined(no_return_value, true_target);
2068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    empty_true->Goto(true_target);
2070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* false_target = if_false();
2073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (false_target->IsInlineReturnTarget()) {
2074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    empty_false->AddLeaveInlined(no_return_value, false_target);
2075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    empty_false->Goto(false_target);
2077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  builder->subgraph()->set_exit_block(NULL);
2079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// HGraphBuilder infrastructure for bailing out and checking bailouts.
2083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define BAILOUT(reason)                         \
2084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  do {                                          \
2085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Bailout(reason);                            \
2086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;                                     \
2087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } while (false)
2088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define CHECK_BAILOUT                           \
2091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  do {                                          \
2092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (HasStackOverflow()) return;             \
2093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } while (false)
2094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define VISIT_FOR_EFFECT(expr)                  \
2097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  do {                                          \
2098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitForEffect(expr);                       \
2099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (HasStackOverflow()) return;             \
2100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } while (false)
2101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define VISIT_FOR_VALUE(expr)                   \
2104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  do {                                          \
2105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitForValue(expr);                        \
2106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (HasStackOverflow()) return;             \
2107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } while (false)
2108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define VISIT_FOR_CONTROL(expr, true_block, false_block)        \
2111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  do {                                                          \
2112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitForControl(expr, true_block, false_block);             \
2113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (HasStackOverflow()) return;                             \
2114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } while (false)
2115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 'thing' could be an expression, statement, or list of statements.
2118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define ADD_TO_SUBGRAPH(graph, thing)       \
2119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  do {                                      \
2120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddToSubgraph(graph, thing);            \
2121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (HasStackOverflow()) return;         \
2122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } while (false)
2123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HGraphBuilder::SubgraphScope BASE_EMBEDDED {
2126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
2127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SubgraphScope(HGraphBuilder* builder, HSubgraph* new_subgraph)
2128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : builder_(builder) {
2129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    old_subgraph_ = builder_->current_subgraph_;
2130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    subgraph_ = new_subgraph;
2131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    builder_->current_subgraph_ = subgraph_;
2132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ~SubgraphScope() {
2135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    old_subgraph_->AddBreakContinueInfo(subgraph_);
2136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    builder_->current_subgraph_ = old_subgraph_;
2137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* subgraph() const { return subgraph_; }
2140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
2142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HGraphBuilder* builder_;
2143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* old_subgraph_;
2144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* subgraph_;
2145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
2146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::Bailout(const char* reason) {
2149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_bailout) {
2150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SmartPointer<char> debug_name = graph()->debug_name()->ToCString();
2151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *debug_name, reason);
2152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetStackOverflow();
2154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForEffect(Expression* expr) {
2158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EffectContext for_effect(this);
2159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Visit(expr);
2160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForValue(Expression* expr) {
2164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ValueContext for_value(this);
2165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Visit(expr);
2166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForControl(Expression* expr,
2170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    HBasicBlock* true_block,
2171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    HBasicBlock* false_block) {
2172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TestContext for_test(this, true_block, false_block);
2173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Visit(expr);
2174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHValue* HGraphBuilder::VisitArgument(Expression* expr) {
2178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForValue(expr);
2179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (HasStackOverflow() || !subgraph()->HasExit()) return NULL;
2180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return environment()->Top();
2181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) {
2185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < arguments->length(); i++) {
2186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitArgument(arguments->at(i));
2187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (HasStackOverflow() || !current_subgraph_->HasExit()) return;
2188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHGraph* HGraphBuilder::CreateGraph(CompilationInfo* info) {
2193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(current_subgraph_ == NULL);
2194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_ = new HGraph(info);
2195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
2197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhase phase("Block building");
2198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    graph_->Initialize(CreateBasicBlock(graph_->start_environment()));
2199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current_subgraph_ = graph_;
2200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Scope* scope = info->scope();
2202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetupScope(scope);
2203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitDeclarations(scope->declarations());
2204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(new HStackCheck());
2206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ZoneList<Statement*>* stmts = info->function()->body();
2208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HSubgraph* body = CreateGotoSubgraph(environment());
2209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddToSubgraph(body, stmts);
2210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (HasStackOverflow()) return NULL;
2211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current_subgraph_->Append(body, NULL);
2212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    body->entry_block()->SetJoinId(info->function()->id());
2213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (graph_->HasExit()) {
2215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      graph_->FinishExit(new HReturn(graph_->GetConstantUndefined()));
2216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_->OrderBlocks();
2220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_->AssignDominators();
2221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_->EliminateRedundantPhis();
2222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!graph_->CollectPhis()) {
2223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Bailout("Phi-use of arguments object");
2224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return NULL;
2225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInferRepresentation rep(graph_);
2228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  rep.Analyze();
2229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_use_range) {
2231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HRangeAnalysis rangeAnalysis(graph_);
2232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    rangeAnalysis.Analyze();
2233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_->InitializeInferredTypes();
2236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_->Canonicalize();
2237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_->InsertRepresentationChanges();
2238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Eliminate redundant stack checks on backwards branches.
2240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HStackCheckEliminator sce(graph_);
2241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  sce.Process();
2242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Perform common subexpression elimination and loop-invariant code motion.
2244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_use_gvn) {
2245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhase phase("Global value numbering", graph_);
2246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HGlobalValueNumberer gvn(graph_);
2247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    gvn.Analyze();
2248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return graph_;
2251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddToSubgraph(HSubgraph* graph, Statement* stmt) {
2255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SubgraphScope scope(this, graph);
2256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Visit(stmt);
2257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddToSubgraph(HSubgraph* graph, Expression* expr) {
2261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SubgraphScope scope(this, graph);
2262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForValue(expr);
2263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddToSubgraph(HSubgraph* graph,
2267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                  ZoneList<Statement*>* stmts) {
2268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SubgraphScope scope(this, graph);
2269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitStatements(stmts);
2270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
2274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(current_subgraph_->HasExit());
2275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  current_subgraph_->exit_block()->AddInstruction(instr);
2276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
2277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddSimulate(int id) {
2281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(current_subgraph_->HasExit());
2282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  current_subgraph_->exit_block()->AddSimulate(id);
2283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddPhi(HPhi* instr) {
2287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(current_subgraph_->HasExit());
2288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  current_subgraph_->exit_block()->AddPhi(instr);
2289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::PushAndAdd(HInstruction* instr) {
2293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Push(instr);
2294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(instr);
2295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::PushArgumentsForStubCall(int argument_count) {
2299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const int kMaxStubArguments = 4;
2300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT_GE(kMaxStubArguments, argument_count);
2301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Push the arguments on the stack.
2302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* arguments[kMaxStubArguments];
2303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = argument_count - 1; i >= 0; i--) {
2304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    arguments[i] = Pop();
2305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < argument_count; i++) {
2307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(new HPushArgument(arguments[i]));
2308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::ProcessCall(HCall* call) {
2313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = call->argument_count() - 1; i >= 0; --i) {
2314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = Pop();
2315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPushArgument* push = new HPushArgument(value);
2316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    call->SetArgumentAt(i, push);
2317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < call->argument_count(); ++i) {
2320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(call->PushArgumentAt(i));
2321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::SetupScope(Scope* scope) {
2326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We don't yet handle the function name for named function expressions.
2327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (scope->function() != NULL) BAILOUT("named function expression");
2328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We can't handle heap-allocated locals.
2330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals");
2331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HConstant* undefined_constant =
2333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new HConstant(Factory::undefined_value(), Representation::Tagged());
2334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(undefined_constant);
2335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_->set_undefined_constant(undefined_constant);
2336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Set the initial values of parameters including "this".  "This" has
2338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // parameter index 0.
2339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int count = scope->num_parameters() + 1;
2340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < count; ++i) {
2341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* parameter = AddInstruction(new HParameter(i));
2342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    environment()->Bind(i, parameter);
2343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Set the initial values of stack-allocated locals.
23469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  for (int i = count; i < environment()->length(); ++i) {
2347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    environment()->Bind(i, undefined_constant);
2348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Handle the arguments and arguments shadow variables specially (they do
2351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // not have declarations).
2352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (scope->arguments() != NULL) {
2353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HArgumentsObject* object = new HArgumentsObject;
2354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(object);
2355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    graph()->SetArgumentsObject(object);
2356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    environment()->Bind(scope->arguments(), object);
2357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    environment()->Bind(scope->arguments_shadow(), object);
2358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
2363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < statements->length(); i++) {
2364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Visit(statements->at(i));
2365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (HasStackOverflow() || !current_subgraph_->HasExit()) break;
2366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
2371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* b = graph()->CreateBasicBlock();
2372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  b->SetInitialEnvironment(env);
2373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return b;
2374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHSubgraph* HGraphBuilder::CreateInlinedSubgraph(HEnvironment* outer,
2378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                Handle<JSFunction> target,
2379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                FunctionLiteral* function) {
2380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HConstant* undefined = graph()->GetConstantUndefined();
2381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* inner =
2382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer->CopyForInlining(target, function, true, undefined);
2383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* subgraph = new HSubgraph(graph());
2384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  subgraph->Initialize(CreateBasicBlock(inner));
2385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return subgraph;
2386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHSubgraph* HGraphBuilder::CreateGotoSubgraph(HEnvironment* env) {
2390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* subgraph = new HSubgraph(graph());
2391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* new_env = env->CopyWithoutHistory();
2392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  subgraph->Initialize(CreateBasicBlock(new_env));
2393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return subgraph;
2394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHSubgraph* HGraphBuilder::CreateEmptySubgraph() {
2398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* subgraph = new HSubgraph(graph());
2399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  subgraph->Initialize(graph()->CreateBasicBlock());
2400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return subgraph;
2401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHSubgraph* HGraphBuilder::CreateBranchSubgraph(HEnvironment* env) {
2405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* subgraph = new HSubgraph(graph());
2406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* new_env = env->Copy();
2407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  subgraph->Initialize(CreateBasicBlock(new_env));
2408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return subgraph;
2409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHSubgraph* HGraphBuilder::CreateLoopHeaderSubgraph(HEnvironment* env) {
2413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* subgraph = new HSubgraph(graph());
2414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* block = graph()->CreateBasicBlock();
2415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* new_env = env->CopyAsLoopHeader(block);
2416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  block->SetInitialEnvironment(new_env);
2417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  subgraph->Initialize(block);
2418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  subgraph->entry_block()->AttachLoopInformation();
2419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return subgraph;
2420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBlock(Block* stmt) {
2424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (stmt->labels() != NULL) {
2425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HSubgraph* block_graph = CreateGotoSubgraph(environment());
2426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ADD_TO_SUBGRAPH(block_graph, stmt->statements());
2427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current_subgraph_->Append(block_graph, stmt);
2428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitStatements(stmt->statements());
2430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
2435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForEffect(stmt->expression());
2436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
2440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitIfStatement(IfStatement* stmt) {
2444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (stmt->condition()->ToBooleanIsTrue()) {
2445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddSimulate(stmt->ThenId());
2446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Visit(stmt->then_statement());
2447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (stmt->condition()->ToBooleanIsFalse()) {
2448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddSimulate(stmt->ElseId());
2449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Visit(stmt->else_statement());
2450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HSubgraph* then_graph = CreateEmptySubgraph();
2452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HSubgraph* else_graph = CreateEmptySubgraph();
2453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_CONTROL(stmt->condition(),
2454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      then_graph->entry_block(),
2455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      else_graph->entry_block());
2456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    then_graph->entry_block()->SetJoinId(stmt->ThenId());
2458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ADD_TO_SUBGRAPH(then_graph, stmt->then_statement());
2459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    else_graph->entry_block()->SetJoinId(stmt->ElseId());
2461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ADD_TO_SUBGRAPH(else_graph, stmt->else_statement());
2462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current_subgraph_->AppendJoin(then_graph, else_graph, stmt);
2464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
2469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  current_subgraph_->FinishBreakContinue(stmt->target(), true);
2470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
2474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  current_subgraph_->FinishBreakContinue(stmt->target(), false);
2475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
2479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AstContext* context = call_context();
2480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (context == NULL) {
2481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Not an inlined return, so an actual one.
2482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_VALUE(stmt->expression());
2483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* result = environment()->Pop();
2484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    subgraph()->FinishExit(new HReturn(result));
2485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Return from an inlined function, visit the subexpression in the
2487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // expression context of the call.
2488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (context->IsTest()) {
2489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TestContext* test = TestContext::cast(context);
2490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VisitForControl(stmt->expression(),
2491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      test->if_true(),
2492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      test->if_false());
2493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
2494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* return_value = NULL;
2495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (context->IsEffect()) {
2496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        VISIT_FOR_EFFECT(stmt->expression());
2497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return_value = graph()->GetConstantUndefined();
2498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
2499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(context->IsValue());
2500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        VISIT_FOR_VALUE(stmt->expression());
2501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return_value = environment()->Pop();
2502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
2503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      subgraph()->exit_block()->AddLeaveInlined(return_value,
2504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                function_return_);
2505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      subgraph()->set_exit_block(NULL);
2506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
2512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("WithEnterStatement");
2513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
2517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("WithExitStatement");
2518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHCompare* HGraphBuilder::BuildSwitchCompare(HSubgraph* subgraph,
2522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            HValue* switch_value,
2523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            CaseClause* clause) {
2524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddToSubgraph(subgraph, clause->label());
2525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (HasStackOverflow()) return NULL;
2526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* clause_value = subgraph->environment()->Pop();
2527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCompare* compare = new HCompare(switch_value,
2528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                   clause_value,
2529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                   Token::EQ_STRICT);
2530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  compare->SetInputRepresentation(Representation::Integer32());
2531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  subgraph->exit_block()->AddInstruction(compare);
2532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return compare;
2533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
2537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VISIT_FOR_VALUE(stmt->tag());
2538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(3168478): simulate added for tag should be enough.
2539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddSimulate(stmt->EntryId());
2540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* switch_value = Pop();
2541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<CaseClause*>* clauses = stmt->cases();
2543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int num_clauses = clauses->length();
2544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (num_clauses == 0) return;
2545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (num_clauses > 128) BAILOUT("SwitchStatement: too many clauses");
2546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int num_smi_clauses = num_clauses;
2548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < num_clauses; i++) {
2549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CaseClause* clause = clauses->at(i);
2550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (clause->is_default()) continue;
2551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    clause->RecordTypeFeedback(oracle());
2552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!clause->IsSmiCompare()) {
2553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (i == 0) BAILOUT("SwitchStatement: no smi compares");
2554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // We will deoptimize if the first non-smi compare is reached.
2555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      num_smi_clauses = i;
2556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
2557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!clause->label()->IsSmiLiteral()) {
2559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      BAILOUT("SwitchStatement: non-literal switch label");
2560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The single exit block of the whole switch statement.
2564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* single_exit_block = graph_->CreateBasicBlock();
2565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Build a series of empty subgraphs for the comparisons.
2567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The default clause does not have a comparison subgraph.
2568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HSubgraph*> compare_graphs(num_smi_clauses);
2569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < num_smi_clauses; i++) {
2570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (clauses->at(i)->is_default()) {
2571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      compare_graphs.Add(NULL);
2572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
2573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      compare_graphs.Add(CreateEmptySubgraph());
2574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* prev_graph = current_subgraph_;
2578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCompare* prev_compare_inst = NULL;
2579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < num_smi_clauses; i++) {
2580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CaseClause* clause = clauses->at(i);
2581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (clause->is_default()) continue;
2582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Finish the previous graph by connecting it to the current.
2584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HSubgraph* subgraph = compare_graphs.at(i);
2585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (prev_compare_inst == NULL) {
2586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(prev_graph == current_subgraph_);
2587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block()));
2588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
2589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* empty = graph()->CreateBasicBlock();
2590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      prev_graph->exit_block()->Finish(new HBranch(empty,
2591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   subgraph->entry_block(),
2592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   prev_compare_inst));
2593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Build instructions for current subgraph.
2596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(clause->IsSmiCompare());
2597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause);
2598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (HasStackOverflow()) return;
2599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    prev_graph = subgraph;
2601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Finish last comparison if there was at least one comparison.
2604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // last_false_block is the (empty) false-block of the last comparison. If
2605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // there are no comparisons at all (a single default clause), it is just
2606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the last block of the current subgraph.
2607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* last_false_block = current_subgraph_->exit_block();
2608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (prev_graph != current_subgraph_) {
2609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    last_false_block = graph()->CreateBasicBlock();
2610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* empty = graph()->CreateBasicBlock();
2611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    prev_graph->exit_block()->Finish(new HBranch(empty,
2612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                 last_false_block,
2613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                 prev_compare_inst));
2614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If we have a non-smi compare clause, we deoptimize after trying
2617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // all the previous compares.
2618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (num_smi_clauses < num_clauses) {
2619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    last_false_block->Finish(new HDeoptimize);
2620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Build statement blocks, connect them to their comparison block and
2623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // to the previous statement block, if there is a fall-through.
2624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* previous_subgraph = NULL;
2625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < num_clauses; i++) {
2626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CaseClause* clause = clauses->at(i);
2627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Subgraph for the statements of the clause is only created when
2628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // it's reachable either from the corresponding compare or as a
2629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // fall-through from previous statements.
2630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HSubgraph* subgraph = NULL;
2631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (i < num_smi_clauses) {
2633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (clause->is_default()) {
2634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (!last_false_block->IsFinished()) {
2635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          // Default clause: Connect it to the last false block.
2636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          subgraph = CreateEmptySubgraph();
2637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          last_false_block->Finish(new HGoto(subgraph->entry_block()));
2638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
2639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
2640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(clause->IsSmiCompare());
2641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Connect with the corresponding comparison.
2642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        subgraph = CreateEmptySubgraph();
2643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HBasicBlock* empty =
2644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            compare_graphs.at(i)->exit_block()->end()->FirstSuccessor();
2645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        empty->Finish(new HGoto(subgraph->entry_block()));
2646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
2647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Check for fall-through from previous statement block.
2650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (previous_subgraph != NULL && previous_subgraph->HasExit()) {
2651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (subgraph == NULL) subgraph = CreateEmptySubgraph();
2652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      previous_subgraph->exit_block()->
2653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          Finish(new HGoto(subgraph->entry_block()));
2654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (subgraph != NULL) {
2657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ADD_TO_SUBGRAPH(subgraph, clause->statements());
2658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* break_block = subgraph->BundleBreak(stmt);
2659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (break_block != NULL) {
2660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        break_block->Finish(new HGoto(single_exit_block));
2661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
2662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    previous_subgraph = subgraph;
2665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If the last statement block has a fall-through, connect it to the
2668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // single exit block.
2669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (previous_subgraph != NULL && previous_subgraph->HasExit()) {
2670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block));
2671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If there is no default clause finish the last comparison's false target.
2674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!last_false_block->IsFinished()) {
2675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    last_false_block->Finish(new HGoto(single_exit_block));
2676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (single_exit_block->HasPredecessor()) {
2679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current_subgraph_->set_exit_block(single_exit_block);
2680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current_subgraph_->set_exit_block(NULL);
2682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraph::HasOsrEntryAt(IterationStatement* statement) {
2686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return statement->OsrEntryId() == info()->osr_ast_id();
2687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::PreProcessOsrEntry(IterationStatement* statement) {
2691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!graph()->HasOsrEntryAt(statement)) return;
2692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
2694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* osr_entry = graph()->CreateBasicBlock();
2695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* true_value = graph()->GetConstantTrue();
2696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBranch* branch = new HBranch(non_osr_entry, osr_entry, true_value);
2697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  exit_block()->Finish(branch);
2698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
2700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  non_osr_entry->Goto(loop_predecessor);
2701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int osr_entry_id = statement->OsrEntryId();
2703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We want the correct environment at the OsrEntry instruction.  Build
2704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // it explicitly.  The expression stack should be empty.
27059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  int count = osr_entry->last_environment()->length();
2706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(count == (osr_entry->last_environment()->parameter_count() +
2707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   osr_entry->last_environment()->local_count()));
2708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < count; ++i) {
2709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HUnknownOSRValue* unknown = new HUnknownOSRValue;
2710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    osr_entry->AddInstruction(unknown);
2711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    osr_entry->last_environment()->Bind(i, unknown);
2712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  osr_entry->AddSimulate(osr_entry_id);
2715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  osr_entry->AddInstruction(new HOsrEntry(osr_entry_id));
2716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  osr_entry->Goto(loop_predecessor);
2717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  loop_predecessor->SetJoinId(statement->EntryId());
2718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  set_exit_block(loop_predecessor);
2719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
2723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(subgraph()->HasExit());
2724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  subgraph()->PreProcessOsrEntry(stmt);
2725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment());
2727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ADD_TO_SUBGRAPH(body_graph, stmt->body());
2728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  body_graph->ResolveContinue(stmt);
2729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) {
2731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current_subgraph_->AppendEndless(body_graph, stmt);
2732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HSubgraph* go_back = CreateEmptySubgraph();
2734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HSubgraph* exit = CreateEmptySubgraph();
2735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    {
2736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SubgraphScope scope(this, body_graph);
2737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_CONTROL(stmt->cond(),
2738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        go_back->entry_block(),
2739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        exit->entry_block());
2740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      go_back->entry_block()->SetJoinId(stmt->BackEdgeId());
2741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      exit->entry_block()->SetJoinId(stmt->ExitId());
2742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current_subgraph_->AppendDoWhile(body_graph, stmt, go_back, exit);
2744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) {
2749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return FLAG_use_peeling;
2750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
2754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(subgraph()->HasExit());
2755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  subgraph()->PreProcessOsrEntry(stmt);
2756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* cond_graph = NULL;
2758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* body_graph = NULL;
2759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* exit_graph = NULL;
2760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If the condition is constant true, do not generate a condition subgraph.
2762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (stmt->cond()->ToBooleanIsTrue()) {
2763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    body_graph = CreateLoopHeaderSubgraph(environment());
2764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ADD_TO_SUBGRAPH(body_graph, stmt->body());
2765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    cond_graph = CreateLoopHeaderSubgraph(environment());
2767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    body_graph = CreateEmptySubgraph();
2768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    exit_graph = CreateEmptySubgraph();
2769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    {
2770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SubgraphScope scope(this, cond_graph);
2771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_CONTROL(stmt->cond(),
2772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        body_graph->entry_block(),
2773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        exit_graph->entry_block());
2774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      body_graph->entry_block()->SetJoinId(stmt->BodyId());
2775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      exit_graph->entry_block()->SetJoinId(stmt->ExitId());
2776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ADD_TO_SUBGRAPH(body_graph, stmt->body());
2778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  body_graph->ResolveContinue(stmt);
2781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (cond_graph != NULL) {
2783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph);
2784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // TODO(fschneider): Implement peeling for endless loops as well.
2786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current_subgraph_->AppendEndless(body_graph, stmt);
2787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt,
2792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                      HSubgraph* cond_graph,
2793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                      HSubgraph* body_graph,
2794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                      HSubgraph* exit_graph) {
2795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* loop = NULL;
2796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (body_graph->HasExit() && stmt != peeled_statement_ &&
2797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ShouldPeel(cond_graph, body_graph)) {
2798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Save the last peeled iteration statement to prevent infinite recursion.
2799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    IterationStatement* outer_peeled_statement = peeled_statement_;
2800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    peeled_statement_ = stmt;
2801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    loop = CreateGotoSubgraph(body_graph->environment());
2802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ADD_TO_SUBGRAPH(loop, stmt);
2803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    peeled_statement_ = outer_peeled_statement;
2804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  current_subgraph_->AppendWhile(cond_graph, body_graph, stmt, loop,
2806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 exit_graph);
2807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForStatement(ForStatement* stmt) {
2811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Only visit the init statement in the peeled part of the loop.
2812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (stmt->init() != NULL && peeled_statement_ != stmt) {
2813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Visit(stmt->init());
2814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_BAILOUT;
2815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(subgraph()->HasExit());
2817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  subgraph()->PreProcessOsrEntry(stmt);
2818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* cond_graph = NULL;
2820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* body_graph = NULL;
2821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* exit_graph = NULL;
2822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (stmt->cond() != NULL) {
2823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    cond_graph = CreateLoopHeaderSubgraph(environment());
2824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    body_graph = CreateEmptySubgraph();
2825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    exit_graph = CreateEmptySubgraph();
2826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    {
2827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SubgraphScope scope(this, cond_graph);
2828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_CONTROL(stmt->cond(),
2829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        body_graph->entry_block(),
2830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        exit_graph->entry_block());
2831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      body_graph->entry_block()->SetJoinId(stmt->BodyId());
2832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      exit_graph->entry_block()->SetJoinId(stmt->ExitId());
2833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    body_graph = CreateLoopHeaderSubgraph(environment());
2836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ADD_TO_SUBGRAPH(body_graph, stmt->body());
2838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* next_graph = NULL;
2840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  body_graph->ResolveContinue(stmt);
2841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (stmt->next() != NULL && body_graph->HasExit()) {
2843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    next_graph = CreateGotoSubgraph(body_graph->environment());
2844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ADD_TO_SUBGRAPH(next_graph, stmt->next());
2845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    body_graph->Append(next_graph, NULL);
2846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    next_graph->entry_block()->SetJoinId(stmt->ContinueId());
2847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (cond_graph != NULL) {
2850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph);
2851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current_subgraph_->AppendEndless(body_graph, stmt);
2853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
2858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("ForInStatement");
2859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
2863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("TryCatchStatement");
2864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
2868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("TryFinallyStatement");
2869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
2873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("DebuggerStatement");
2874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
2878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<SharedFunctionInfo> shared_info =
2879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Compiler::BuildFunctionInfo(expr, graph_->info()->script());
2880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_BAILOUT;
2881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HFunctionLiteral* instr =
2882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new HFunctionLiteral(shared_info, expr->pretenure());
2883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(instr, expr->id());
2884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitSharedFunctionInfoLiteral(
2888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SharedFunctionInfoLiteral* expr) {
2889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("SharedFunctionInfoLiteral");
2890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitConditional(Conditional* expr) {
2894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* then_graph = CreateEmptySubgraph();
2895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* else_graph = CreateEmptySubgraph();
2896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VISIT_FOR_CONTROL(expr->condition(),
2897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    then_graph->entry_block(),
2898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    else_graph->entry_block());
2899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  then_graph->entry_block()->SetJoinId(expr->ThenId());
2901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ADD_TO_SUBGRAPH(then_graph, expr->then_expression());
2902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  else_graph->entry_block()->SetJoinId(expr->ElseId());
2904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ADD_TO_SUBGRAPH(else_graph, expr->else_expression());
2905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  current_subgraph_->AppendJoin(then_graph, else_graph, expr);
2907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnValue(Pop());
2908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::LookupGlobalPropertyCell(Variable* var,
2912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             LookupResult* lookup,
2913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             bool is_store) {
2914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (var->is_this()) {
2915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BAILOUT("global this reference");
2916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!graph()->info()->has_global_object()) {
2918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BAILOUT("no global object to optimize VariableProxy");
2919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<GlobalObject> global(graph()->info()->global_object());
2921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  global->Lookup(*var->name(), lookup);
2922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!lookup->IsProperty()) {
2923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BAILOUT("global variable cell not yet introduced");
2924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup->type() != NORMAL) {
2926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BAILOUT("global variable has accessors");
2927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (is_store && lookup->IsReadOnly()) {
2929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BAILOUT("read-only global variable");
2930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
2935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Variable* variable = expr->AsVariable();
2936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (variable == NULL) {
2937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BAILOUT("reference to rewritten variable");
2938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (variable->IsStackAllocated()) {
2939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) {
2940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      BAILOUT("unsupported context for arguments object");
2941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnValue(environment()->Lookup(variable));
2943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (variable->is_global()) {
2944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LookupResult lookup;
2945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LookupGlobalPropertyCell(variable, &lookup, false);
2946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_BAILOUT;
2947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<GlobalObject> global(graph()->info()->global_object());
2949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // TODO(3039103): Handle global property load through an IC call when access
2950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // checks are enabled.
2951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (global->IsAccessCheckNeeded()) {
2952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      BAILOUT("global object requires access check");
2953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
2954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
2955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
2956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HLoadGlobal* instr = new HLoadGlobal(cell, check_hole);
2957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnInstruction(instr, expr->id());
2958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BAILOUT("reference to non-stack-allocated/non-global variable");
2960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitLiteral(Literal* expr) {
2965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HConstant* instr = new HConstant(expr->handle(), Representation::Tagged());
2966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(instr, expr->id());
2967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
2971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HRegExpLiteral* instr = new HRegExpLiteral(expr->pattern(),
2972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             expr->flags(),
2973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             expr->literal_index());
2974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(instr, expr->id());
2975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
2979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HObjectLiteral* literal = (new HObjectLiteral(expr->constant_properties(),
2980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                expr->fast_elements(),
2981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                expr->literal_index(),
2982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                expr->depth()));
2983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The object is expected in the bailout environment during computation
2984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // of the property values and is the value of the entire expression.
2985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushAndAdd(literal);
2986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->CalculateEmitStore();
2988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < expr->properties()->length(); i++) {
2990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ObjectLiteral::Property* property = expr->properties()->at(i);
2991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (property->IsCompileTimeValue()) continue;
2992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Literal* key = property->key();
2994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Expression* value = property->value();
2995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    switch (property->kind()) {
2997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
2998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
2999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Fall through.
3000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::COMPUTED:
3001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (key->handle()->IsSymbol()) {
3002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (property->emit_store()) {
3003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            VISIT_FOR_VALUE(value);
3004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HValue* value = Pop();
3005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            Handle<String> name = Handle<String>::cast(key->handle());
3006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AddInstruction(new HStoreNamedGeneric(literal, name, value));
3007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AddSimulate(key->id());
3008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else {
3009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            VISIT_FOR_EFFECT(value);
3010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
3011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          break;
3012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
3013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Fall through.
3014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::PROTOTYPE:
3015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::SETTER:
3016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case ObjectLiteral::Property::GETTER:
3017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        BAILOUT("Object literal with complex property");
3018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      default: UNREACHABLE();
3019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnValue(Pop());
3022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
3026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<Expression*>* subexprs = expr->values();
3027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = subexprs->length();
3028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HArrayLiteral* literal = new HArrayLiteral(expr->constant_elements(),
3030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             length,
3031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             expr->literal_index(),
3032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             expr->depth());
3033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The array is expected in the bailout environment during computation
3034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // of the property values and is the value of the entire expression.
3035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushAndAdd(literal);
3036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HLoadElements* elements = NULL;
3038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; i++) {
3040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Expression* subexpr = subexprs->at(i);
3041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // If the subexpression is a literal or a simple materialized literal it
3042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // is already set in the cloned array.
3043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
3044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_VALUE(subexpr);
3046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = Pop();
3047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!Smi::IsValid(i)) BAILOUT("Non-smi key in array literal");
3048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Load the elements array before the first store.
3050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (elements == NULL)  {
3051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch     elements = new HLoadElements(literal);
3052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch     AddInstruction(elements);
3053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* key = AddInstruction(new HConstant(Handle<Object>(Smi::FromInt(i)),
3056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                               Representation::Integer32()));
3057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(new HStoreKeyedFastElement(elements, key, value));
3058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddSimulate(expr->GetIdForElement(i));
3059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnValue(Pop());
3061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
3065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("CatchExtensionObject");
3066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps,
3070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            ZoneList<HSubgraph*>* subgraphs,
3071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            HValue* receiver,
3072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            int join_id) {
3073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(subgraphs->length() == (maps->length() + 1));
3074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Build map compare subgraphs for all but the first map.
3076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HSubgraph*> map_compare_subgraphs(maps->length() - 1);
3077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = maps->length() - 1; i > 0; --i) {
3078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HSubgraph* subgraph = CreateBranchSubgraph(environment());
3079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SubgraphScope scope(this, subgraph);
3080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HSubgraph* else_subgraph =
3081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        (i == (maps->length() - 1))
3082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ? subgraphs->last()
3083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        : map_compare_subgraphs.last();
3084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current_subgraph_->exit_block()->Finish(
3085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        new HCompareMapAndBranch(receiver,
3086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 maps->at(i),
3087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 subgraphs->at(i)->entry_block(),
3088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 else_subgraph->entry_block()));
3089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    map_compare_subgraphs.Add(subgraph);
3090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Generate first map check to end the current block.
3093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(new HCheckNonSmi(receiver));
3094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* else_subgraph =
3095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      (maps->length() == 1) ? subgraphs->at(1) : map_compare_subgraphs.last();
3096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  current_subgraph_->exit_block()->Finish(
3097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new HCompareMapAndBranch(receiver,
3098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               Handle<Map>(maps->first()),
3099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               subgraphs->first()->entry_block(),
3100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               else_subgraph->entry_block()));
3101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Join all the call subgraphs in a new basic block and make
3103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // this basic block the current basic block.
3104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* join_block = graph_->CreateBasicBlock();
3105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < subgraphs->length(); ++i) {
31069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    HSubgraph* subgraph = subgraphs->at(i);
31079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    if (subgraph->HasExit()) {
31089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // In an effect context the value of the type switch is not needed.
31099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // There is no need to merge it at the join block only to discard it.
31109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      HBasicBlock* subgraph_exit = subgraph->exit_block();
31119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      if (ast_context()->IsEffect()) {
31129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        subgraph_exit->last_environment()->Drop(1);
31139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      }
31149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      subgraph_exit->Goto(join_block);
3115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (join_block->predecessors()->is_empty()) return NULL;
3119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  join_block->SetJoinId(join_id);
3120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return join_block;
3121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Sets the lookup result and returns true if the store can be inlined.
3125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool ComputeStoredField(Handle<Map> type,
3126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               Handle<String> name,
3127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               LookupResult* lookup) {
3128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  type->LookupInDescriptors(NULL, *name, lookup);
3129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!lookup->IsPropertyOrTransition()) return false;
3130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup->type() == FIELD) return true;
3131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return (lookup->type() == MAP_TRANSITION) &&
3132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      (type->unused_property_fields() > 0);
3133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic int ComputeStoredFieldIndex(Handle<Map> type,
3137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                   Handle<String> name,
3138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                   LookupResult* lookup) {
3139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(lookup->type() == FIELD || lookup->type() == MAP_TRANSITION);
3140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup->type() == FIELD) {
3141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return lookup->GetLocalFieldIndexFromMap(*type);
3142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Map* transition = lookup->GetTransitionMapFromMap(*type);
3144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return transition->PropertyIndexFor(*name) - type->inobject_properties();
3145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
3150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  Handle<String> name,
3151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  HValue* value,
3152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  Handle<Map> type,
3153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  LookupResult* lookup,
3154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  bool smi_and_map_check) {
3155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (smi_and_map_check) {
3156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(new HCheckNonSmi(object));
3157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(new HCheckMap(object, type));
3158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = ComputeStoredFieldIndex(type, name, lookup);
3161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_in_object = index < 0;
3162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int offset = index * kPointerSize;
3163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (index < 0) {
3164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Negative property indices are in-object properties, indexed
3165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // from the end of the fixed part of the object.
3166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset += type->instance_size();
3167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset += FixedArray::kHeaderSize;
3169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HStoreNamedField* instr =
3171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new HStoreNamedField(object, name, value, is_in_object, offset);
3172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup->type() == MAP_TRANSITION) {
3173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Map> transition(lookup->GetTransitionMapFromMap(*type));
3174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_transition(transition);
3175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // TODO(fschneider): Record the new map type of the object in the IR to
3176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // enable elimination of redundant checks after the transition store.
3177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->SetFlag(HValue::kChangesMaps);
3178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
3180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
3184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    Handle<String> name,
3185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    HValue* value) {
3186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return new HStoreNamedGeneric(object, name, value);
3187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
3191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             HValue* value,
3192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             Expression* expr) {
3193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = (expr->AsProperty() != NULL)
3194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ? expr->AsProperty()
3195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : expr->AsAssignment()->target()->AsProperty();
3196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Literal* key = prop->key()->AsLiteral();
3197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<String> name = Handle<String>::cast(key->handle());
3198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!name.is_null());
3199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LookupResult lookup;
3201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneMapList* types = expr->GetReceiverTypes();
3202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_monomorphic = expr->IsMonomorphic() &&
3203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ComputeStoredField(types->first(), name, &lookup);
3204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return is_monomorphic
3206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ? BuildStoreNamedField(object, name, value, types->first(), &lookup,
3207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             true)  // Needs smi and map check.
3208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : BuildStoreNamedGeneric(object, name, value);
3209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
3213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     HValue* object,
3214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     HValue* value,
3215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     ZoneMapList* types,
3216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Handle<String> name) {
3217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int number_of_types = Min(types->length(), kMaxStorePolymorphism);
3218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneMapList maps(number_of_types);
3219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HSubgraph*> subgraphs(number_of_types + 1);
3220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool needs_generic = (types->length() > kMaxStorePolymorphism);
3221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Build subgraphs for each of the specific maps.
3223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //
3224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(ager): We should recognize when the prototype chains for
3225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // different maps are identical. In that case we can avoid
3226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // repeatedly generating the same prototype map checks.
3227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < number_of_types; ++i) {
3228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Map> map = types->at(i);
3229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LookupResult lookup;
3230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (ComputeStoredField(map, name, &lookup)) {
3231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      maps.Add(map);
3232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HSubgraph* subgraph = CreateBranchSubgraph(environment());
3233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SubgraphScope scope(this, subgraph);
3234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instr =
3235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          BuildStoreNamedField(object, name, value, map, &lookup, false);
3236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(value);
3237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr->set_position(expr->position());
3238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(instr);
3239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      subgraphs.Add(subgraph);
3240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
3241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      needs_generic = true;
3242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If none of the properties were named fields we generate a
3246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // generic store.
3247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (maps.length() == 0) {
3248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* instr = new HStoreNamedGeneric(object, name, value);
3249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Push(value);
3250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_position(expr->position());
3251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(instr);
32529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
32539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    ast_context()->ReturnValue(Pop());
3254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Build subgraph for generic store through IC.
3256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    {
3257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HSubgraph* subgraph = CreateBranchSubgraph(environment());
3258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SubgraphScope scope(this, subgraph);
3259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        subgraph->FinishExit(new HDeoptimize());
3261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
3262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HInstruction* instr = new HStoreNamedGeneric(object, name, value);
3263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Push(value);
3264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instr->set_position(expr->position());
3265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        AddInstruction(instr);
3266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
3267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      subgraphs.Add(subgraph);
3268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* new_exit_block =
32719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
3272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    subgraph()->set_exit_block(new_exit_block);
32739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // In an effect context, we did not materialized the value in the
32749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // predecessor environments so there's no need to handle it here.
32759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    if (subgraph()->HasExit() && !ast_context()->IsEffect()) {
32769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ast_context()->ReturnValue(Pop());
32779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
3278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
3283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = expr->target()->AsProperty();
3284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(prop != NULL);
3285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->RecordTypeFeedback(oracle());
3286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VISIT_FOR_VALUE(prop->obj());
3287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = NULL;
3289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = NULL;
3290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (prop->key()->IsPropertyName()) {
3292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Named store.
3293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_VALUE(expr->value());
3294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    value = Pop();
3295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* object = Pop();
3296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Literal* key = prop->key()->AsLiteral();
3298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = Handle<String>::cast(key->handle());
3299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!name.is_null());
3300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ZoneMapList* types = expr->GetReceiverTypes();
3302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LookupResult lookup;
3303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (expr->IsMonomorphic()) {
3305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = BuildStoreNamed(object, value, expr);
3306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (types != NULL && types->length() > 1) {
3308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandlePolymorphicStoreNamedField(expr, object, value, types, name);
3309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
3310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
3312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = new HStoreNamedGeneric(object, name, value);
3313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Keyed store.
3317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_VALUE(prop->key());
3318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_VALUE(expr->value());
3319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    value = Pop();
3320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* key = Pop();
3321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* object = Pop();
3322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool is_fast_elements = expr->IsMonomorphic() &&
3324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        expr->GetMonomorphicReceiverType()->has_fast_elements();
3325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = is_fast_elements
3327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ? BuildStoreKeyedFastElement(object, key, value, expr)
3328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        : BuildStoreKeyedGeneric(object, key, value);
3329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Push(value);
3332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(expr->position());
3333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(instr);
3334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnValue(Pop());
3336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Because not every expression has a position and there is not common
3340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// superclass of Assignment and CountOperation, we cannot just pass the
3341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// owning expression instead of position and ast_id separately.
3342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
3343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   HValue* value,
3344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   int position,
3345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   int ast_id) {
3346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LookupResult lookup;
3347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LookupGlobalPropertyCell(var, &lookup, true);
3348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_BAILOUT;
3349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<GlobalObject> global(graph()->info()->global_object());
3351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = new HStoreGlobal(value, cell);
3353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(position);
3354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(instr);
3355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (instr->HasSideEffects()) AddSimulate(ast_id);
3356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Expression* target = expr->target();
3361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = target->AsVariableProxy();
3362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Variable* var = proxy->AsVariable();
3363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = target->AsProperty();
3364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(var == NULL || prop == NULL);
3365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We have a second position recorded in the FullCodeGenerator to have
3367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // type feedback for the binary operation.
3368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BinaryOperation* operation = expr->binary_operation();
3369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  operation->RecordTypeFeedback(oracle());
3370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (var != NULL) {
3372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!var->is_global() && !var->IsStackAllocated()) {
3373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      BAILOUT("non-stack/non-global in compound assignment");
3374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_VALUE(operation);
3377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (var->is_global()) {
3379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandleGlobalVariableAssignment(var,
3380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     Top(),
3381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     expr->position(),
3382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     expr->AssignmentId());
3383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
3384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Bind(var, Top());
3385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnValue(Pop());
3387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (prop != NULL) {
3389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    prop->RecordTypeFeedback(oracle());
3390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (prop->key()->IsPropertyName()) {
3392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Named property.
3393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_VALUE(prop->obj());
3394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = Top();
3395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* load = NULL;
3397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (prop->IsMonomorphic()) {
3398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
3399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<Map> map = prop->GetReceiverTypes()->first();
3400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamed(obj, prop, map, name);
3401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
3402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamedGeneric(obj, prop);
3403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
3404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(load);
3405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId());
3406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_VALUE(expr->value());
3408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* right = Pop();
3409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* left = Pop();
3410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instr = BuildBinaryOperation(operation, left, right);
3412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(instr);
3413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (instr->HasSideEffects()) AddSimulate(operation->id());
3414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* store = BuildStoreNamed(obj, instr, prop);
3416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(store);
3417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Drop the simulated receiver and value.  Return the value.
3418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(2);
3419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(instr);
3420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
3421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(Pop());
3422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
3424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Keyed property.
3425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_VALUE(prop->obj());
3426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_VALUE(prop->key());
3427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = environment()->ExpressionStackAt(1);
3428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* key = environment()->ExpressionStackAt(0);
3429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool is_fast_elements = prop->IsMonomorphic() &&
3431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          prop->GetMonomorphicReceiverType()->has_fast_elements();
3432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* load = is_fast_elements
3434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          ? BuildLoadKeyedFastElement(obj, key, prop)
3435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          : BuildLoadKeyedGeneric(obj, key);
3436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(load);
3437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId());
3438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_VALUE(expr->value());
3440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* right = Pop();
3441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* left = Pop();
3442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instr = BuildBinaryOperation(operation, left, right);
3444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(instr);
3445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (instr->HasSideEffects()) AddSimulate(operation->id());
3446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* store = is_fast_elements
3448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          ? BuildStoreKeyedFastElement(obj, key, instr, prop)
3449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          : BuildStoreKeyedGeneric(obj, key, instr);
3450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(store);
3451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Drop the simulated receiver, key, and value.  Return the value.
3452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(3);
3453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(instr);
3454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
3455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(Pop());
3456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BAILOUT("invalid lhs in compound assignment");
3460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitAssignment(Assignment* expr) {
3465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = expr->target()->AsVariableProxy();
3466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Variable* var = proxy->AsVariable();
3467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = expr->target()->AsProperty();
3468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(var == NULL || prop == NULL);
3469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->is_compound()) {
3471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HandleCompoundAssignment(expr);
3472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
3473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (var != NULL) {
3476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (proxy->IsArguments()) BAILOUT("assignment to arguments");
3477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Handle the assignment.
3479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (var->is_global()) {
3480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_VALUE(expr->value());
3481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandleGlobalVariableAssignment(var,
3482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     Top(),
3483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     expr->position(),
3484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     expr->AssignmentId());
3485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
3486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // We allow reference to the arguments object only in assignemtns
3487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // to local variables to make sure that the arguments object does
3488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // not escape and is not modified.
3489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VariableProxy* rhs = expr->value()->AsVariableProxy();
3490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (rhs != NULL &&
3491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          rhs->var()->IsStackAllocated() &&
3492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          environment()->Lookup(rhs->var())->CheckFlag(HValue::kIsArguments)) {
3493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Push(environment()->Lookup(rhs->var()));
3494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
3495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        VISIT_FOR_VALUE(expr->value());
3496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
3497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Bind(proxy->var(), Top());
3498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Return the value.
3500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnValue(Pop());
3501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (prop != NULL) {
3503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HandlePropertyAssignment(expr);
3504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BAILOUT("unsupported invalid lhs");
3506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThrow(Throw* expr) {
3511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We don't optimize functions with invalid left-hand sides in
3512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // assignments, count operations, or for-in.  Consequently throw can
3513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // currently only occur in an effect context.
3514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(ast_context()->IsEffect());
3515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VISIT_FOR_VALUE(expr->exception());
3516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = environment()->Pop();
3518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HControlInstruction* instr = new HThrow(value);
3519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(expr->position());
3520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  current_subgraph_->FinishExit(instr);
3521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
3525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    HValue* object,
3526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    ZoneMapList* types,
3527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    Handle<String> name) {
3528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int number_of_types = Min(types->length(), kMaxLoadPolymorphism);
3529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneMapList maps(number_of_types);
3530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HSubgraph*> subgraphs(number_of_types + 1);
3531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool needs_generic = (types->length() > kMaxLoadPolymorphism);
3532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Build subgraphs for each of the specific maps.
3534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //
3535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(ager): We should recognize when the prototype chains for
3536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // different maps are identical. In that case we can avoid
3537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // repeatedly generating the same prototype map checks.
3538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < number_of_types; ++i) {
3539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Map> map = types->at(i);
3540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LookupResult lookup;
3541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    map->LookupInDescriptors(NULL, *name, &lookup);
3542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (lookup.IsProperty() && lookup.type() == FIELD) {
3543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      maps.Add(map);
3544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HSubgraph* subgraph = CreateBranchSubgraph(environment());
3545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SubgraphScope scope(this, subgraph);
3546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HLoadNamedField* instr =
3547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          BuildLoadNamedField(object, expr, map, &lookup, false);
3548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr->set_position(expr->position());
3549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr->ClearFlag(HValue::kUseGVN);  // Don't do GVN on polymorphic loads.
3550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(instr);
3551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      subgraphs.Add(subgraph);
3552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
3553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      needs_generic = true;
3554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If none of the properties were named fields we generate a
3558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // generic load.
3559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (maps.length() == 0) {
3560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_position(expr->position());
35629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    ast_context()->ReturnInstruction(instr, expr->id());
3563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Build subgraph for generic load through IC.
3565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    {
3566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HSubgraph* subgraph = CreateBranchSubgraph(environment());
3567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SubgraphScope scope(this, subgraph);
3568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        subgraph->FinishExit(new HDeoptimize());
3570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
3571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instr->set_position(expr->position());
3573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PushAndAdd(instr);
3574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
3575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      subgraphs.Add(subgraph);
3576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* new_exit_block =
3579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
3580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    subgraph()->set_exit_block(new_exit_block);
35819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // In an effect context, we did not materialized the value in the
35829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // predecessor environments so there's no need to handle it here.
35839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    if (subgraph()->HasExit() && !ast_context()->IsEffect()) {
35849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ast_context()->ReturnValue(Pop());
35859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
3586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
3591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    Property* expr,
3592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    Handle<Map> type,
3593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    LookupResult* lookup,
3594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    bool smi_and_map_check) {
3595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (smi_and_map_check) {
3596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(new HCheckNonSmi(object));
3597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(new HCheckMap(object, type));
3598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int index = lookup->GetLocalFieldIndexFromMap(*type);
3601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (index < 0) {
3602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Negative property indices are in-object properties, indexed
3603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // from the end of the fixed part of the object.
3604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int offset = (index * kPointerSize) + type->instance_size();
3605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return new HLoadNamedField(object, true, offset);
3606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Non-negative property indices are in the properties array.
3608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
3609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return new HLoadNamedField(object, false, offset);
3610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj,
3615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   Property* expr) {
3616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(expr->key()->IsPropertyName());
3617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Object> name = expr->key()->AsLiteral()->handle();
3618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return new HLoadNamedGeneric(obj, name);
3619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj,
3623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            Property* expr,
3624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            Handle<Map> map,
3625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            Handle<String> name) {
3626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LookupResult lookup;
3627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  map->LookupInDescriptors(NULL, *name, &lookup);
3628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (lookup.IsProperty() && lookup.type() == FIELD) {
3629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return BuildLoadNamedField(obj,
3630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               expr,
3631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               map,
3632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               &lookup,
3633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               true);
3634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
3635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(new HCheckNonSmi(obj));
3636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(new HCheckMap(obj, map));
3637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map));
3638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return new HConstant(function, Representation::Tagged());
3639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return BuildLoadNamedGeneric(obj, expr);
3641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
3646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                   HValue* key) {
3647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return new HLoadKeyedGeneric(object, key);
3648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object,
3652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                       HValue* key,
3653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                       Property* expr) {
3654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic());
3655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(new HCheckNonSmi(object));
3656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Map> map = expr->GetMonomorphicReceiverType();
3657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(map->has_fast_elements());
3658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(new HCheckMap(object, map));
36599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
36609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  HLoadElements* elements = new HLoadElements(object);
36619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  HInstruction* length = NULL;
36629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (is_array) {
36639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    length = AddInstruction(new HJSArrayLength(object));
36649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    AddInstruction(new HBoundsCheck(key, length));
36659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    AddInstruction(elements);
36669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
36679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    AddInstruction(elements);
36689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    length = AddInstruction(new HFixedArrayLength(elements));
36699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    AddInstruction(new HBoundsCheck(key, length));
36709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
3671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return new HLoadKeyedFastElement(elements, key);
3672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
3676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    HValue* key,
3677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                    HValue* value) {
3678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return new HStoreKeyedGeneric(object, key, value);
3679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object,
3683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                        HValue* key,
3684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                        HValue* val,
3685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                        Expression* expr) {
3686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(expr->IsMonomorphic());
3687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(new HCheckNonSmi(object));
3688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Map> map = expr->GetMonomorphicReceiverType();
3689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(map->has_fast_elements());
3690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(new HCheckMap(object, map));
3691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* elements = AddInstruction(new HLoadElements(object));
3692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(new HCheckMap(elements, Factory::fixed_array_map()));
3693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
3694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* length = NULL;
3695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (is_array) {
36969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    length = AddInstruction(new HJSArrayLength(object));
3697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
36989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    length = AddInstruction(new HFixedArrayLength(elements));
3699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(new HBoundsCheck(key, length));
3701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return new HStoreKeyedFastElement(elements, key, val);
3702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryArgumentsAccess(Property* expr) {
3706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = expr->obj()->AsVariableProxy();
3707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (proxy == NULL) return false;
3708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!proxy->var()->IsStackAllocated()) return false;
3709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
3710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
3711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* result = NULL;
3714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->key()->IsPropertyName()) {
3715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
3716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!name->IsEqualTo(CStrVector("length"))) return false;
3717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* elements = AddInstruction(new HArgumentsElements);
3718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    result = new HArgumentsLength(elements);
3719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitForValue(expr->key());
3721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (HasStackOverflow()) return false;
3722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* key = Pop();
3723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* elements = AddInstruction(new HArgumentsElements);
3724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* length = AddInstruction(new HArgumentsLength(elements));
3725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(new HBoundsCheck(key, length));
3726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    result = new HAccessArgumentsAt(elements, length, key);
3727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, expr->id());
3729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
3730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitProperty(Property* expr) {
3734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->RecordTypeFeedback(oracle());
3735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (TryArgumentsAccess(expr)) return;
3737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_BAILOUT;
3738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VISIT_FOR_VALUE(expr->obj());
3740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = NULL;
3742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->IsArrayLength()) {
3743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* array = Pop();
3744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(new HCheckNonSmi(array));
37459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    AddInstruction(new HCheckInstanceType(array, JS_ARRAY_TYPE, JS_ARRAY_TYPE));
37469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    instr = new HJSArrayLength(array);
37479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
37489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else if (expr->IsFunctionPrototype()) {
37499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    HValue* function = Pop();
37509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    AddInstruction(new HCheckNonSmi(function));
37519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    instr = new HLoadFunctionPrototype(function);
3752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (expr->key()->IsPropertyName()) {
3754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
3755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ZoneMapList* types = expr->GetReceiverTypes();
3756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* obj = Pop();
3758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (expr->IsMonomorphic()) {
3759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = BuildLoadNamed(obj, expr, types->first(), name);
3760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (types != NULL && types->length() > 1) {
3761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandlePolymorphicLoadNamedField(expr, obj, types, name);
3762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
3763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
3765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = BuildLoadNamedGeneric(obj, expr);
3766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_VALUE(expr->key());
3770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* key = Pop();
3772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* obj = Pop();
3773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool is_fast_elements = expr->IsMonomorphic() &&
3775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        expr->GetMonomorphicReceiverType()->has_fast_elements();
3776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = is_fast_elements
3778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ? BuildLoadKeyedFastElement(obj, key, expr)
3779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        : BuildLoadKeyedGeneric(obj, key);
3780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(expr->position());
3782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(instr, expr->id());
3783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddCheckConstantFunction(Call* expr,
3787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             HValue* receiver,
3788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             Handle<Map> receiver_map,
3789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             bool smi_and_map_check) {
3790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Constant functions have the nice property that the map will change if they
3791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // are overwritten.  Therefore it is enough to check the map of the holder and
3792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // its prototypes.
3793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (smi_and_map_check) {
3794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(new HCheckNonSmi(receiver));
3795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(new HCheckMap(receiver, receiver_map));
3796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!expr->holder().is_null()) {
3798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(new HCheckPrototypeMaps(receiver,
3799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                           expr->holder(),
3800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                           receiver_map));
3801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
3806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                               HValue* receiver,
3807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                               ZoneMapList* types,
3808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                               Handle<String> name) {
3809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
3810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int number_of_types = Min(types->length(), kMaxCallPolymorphism);
3811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneMapList maps(number_of_types);
3812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<HSubgraph*> subgraphs(number_of_types + 1);
3813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool needs_generic = (types->length() > kMaxCallPolymorphism);
3814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Build subgraphs for each of the specific maps.
3816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //
3817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(ager): We should recognize when the prototype chains for different
3818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // maps are identical. In that case we can avoid repeatedly generating the
3819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // same prototype map checks.
3820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < number_of_types; ++i) {
3821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Map> map = types->at(i);
3822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (expr->ComputeTarget(map, name)) {
3823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      maps.Add(map);
3824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HSubgraph* subgraph = CreateBranchSubgraph(environment());
3825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SubgraphScope scope(this, subgraph);
3826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddCheckConstantFunction(expr, receiver, map, false);
3827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
3828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF("Trying to inline the polymorphic call to %s\n",
3829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               *name->ToCString());
3830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
3831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!FLAG_polymorphic_inlining || !TryInline(expr)) {
3832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Check for bailout, as trying to inline might fail due to bailout
3833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // during hydrogen processing.
3834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        CHECK_BAILOUT;
3835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HCall* call = new HCallConstantFunction(expr->target(), argument_count);
3836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        call->set_position(expr->position());
3837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ProcessCall(call);
3838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PushAndAdd(call);
3839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
3840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      subgraphs.Add(subgraph);
3841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
3842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      needs_generic = true;
3843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If we couldn't compute the target for any of the maps just perform an
3847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // IC call.
3848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (maps.length() == 0) {
3849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HCall* call = new HCallNamed(name, argument_count);
3850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    call->set_position(expr->position());
3851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ProcessCall(call);
3852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnInstruction(call, expr->id());
3853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Build subgraph for generic call through IC.
3855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    {
3856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HSubgraph* subgraph = CreateBranchSubgraph(environment());
3857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SubgraphScope scope(this, subgraph);
3858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        subgraph->FinishExit(new HDeoptimize());
3860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
3861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HCall* call = new HCallNamed(name, argument_count);
3862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        call->set_position(expr->position());
3863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ProcessCall(call);
3864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PushAndAdd(call);
3865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
3866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      subgraphs.Add(subgraph);
3867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
3868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* new_exit_block =
3870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id());
3871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    subgraph()->set_exit_block(new_exit_block);
38729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // In an effect context, we did not materialized the value in the
38739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // predecessor environments so there's no need to handle it here.
38749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    if (new_exit_block != NULL && !ast_context()->IsEffect()) {
38759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ast_context()->ReturnValue(Pop());
38769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
3877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) {
3882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SmartPointer<char> callee = target->shared()->DebugName()->ToCString();
3883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SmartPointer<char> caller =
3884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      graph()->info()->function()->debug_name()->ToCString();
3885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (result) {
3886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("Inlined %s called from %s.\n", *callee, *caller);
3887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("Do not inline %s called from %s.\n", *callee, *caller);
3889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryInline(Call* expr) {
3894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!FLAG_use_inlining) return false;
3895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Precondition: call is monomorphic and we have found a target with the
3897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // appropriate arity.
3898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<JSFunction> target = expr->target();
3899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Do a quick check on source code length to avoid parsing large
3901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // inlining candidates.
3902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) {
3903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (FLAG_trace_inlining) TraceInline(target, false);
3904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
3905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Target must be inlineable.
3908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!target->IsInlineable()) return false;
3909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // No context change required.
3911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompilationInfo* outer_info = graph()->info();
3912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (target->context() != outer_info->closure()->context() ||
3913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_info->scope()->contains_with() ||
3914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_info->scope()->num_heap_slots() > 0) {
3915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
3916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Don't inline deeper than two calls.
3919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* env = environment();
3920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (env->outer() != NULL && env->outer()->outer() != NULL) return false;
3921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Don't inline recursive functions.
3923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (target->shared() == outer_info->closure()->shared()) return false;
3924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We don't want to add more than a certain number of nodes from inlining.
3926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) {
3927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (FLAG_trace_inlining) TraceInline(target, false);
3928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
3929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int count_before = AstNode::Count();
3932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Parse and allocate variables.
3934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<SharedFunctionInfo> shared(target->shared());
3935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompilationInfo inner_info(shared);
3936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!ParserApi::Parse(&inner_info) ||
3937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      !Scope::Analyze(&inner_info)) {
3938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
3939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  FunctionLiteral* function = inner_info.function();
3941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Count the number of AST nodes added by inlining this call.
3943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int nodes_added = AstNode::Count() - count_before;
3944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) {
3945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (FLAG_trace_inlining) TraceInline(target, false);
3946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
3947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check if we can handle all declarations in the inlined functions.
3950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitDeclarations(inner_info.scope()->declarations());
3951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (HasStackOverflow()) {
3952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ClearStackOverflow();
3953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
3954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Don't inline functions that uses the arguments object or that
3957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // have a mismatching number of parameters.
3958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int arity = expr->arguments()->length();
3959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (function->scope()->arguments() != NULL ||
3960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      arity != target->shared()->formal_parameter_count()) {
3961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
3962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // All statements in the body must be inlineable.
3965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0, count = function->body()->length(); i < count; ++i) {
3966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!function->body()->at(i)->IsInlineable()) return false;
3967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Generate the deoptimization data for the unoptimized version of
3970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the target function if we don't already have it.
3971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!shared->has_deoptimization_support()) {
3972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Note that we compile here using the same AST that we will use for
3973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // generating the optimized inline code.
3974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    inner_info.EnableDeoptimizationSupport();
3975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!FullCodeGenerator::MakeCode(&inner_info)) return false;
3976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    shared->EnableDeoptimizationSupport(*inner_info.code());
3977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Compiler::RecordFunctionCompilation(
3978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Logger::FUNCTION_TAG,
3979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<String>(shared->DebugName()),
3980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        shared->start_position(),
3981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        &inner_info);
3982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Save the pending call context and type feedback oracle. Set up new ones
3985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // for the inlined function.
3986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(shared->has_deoptimization_support());
3987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AstContext* saved_call_context = call_context();
3988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HBasicBlock* saved_function_return = function_return();
3989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TypeFeedbackOracle* saved_oracle = oracle();
3990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // On-stack replacement cannot target inlined functions.  Since we don't
3991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // use a separate CompilationInfo structure for the inlined function, we
3992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // save and restore the AST ID in the original compilation info.
3993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int saved_osr_ast_id = graph()->info()->osr_ast_id();
3994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TestContext* test_context = NULL;
3996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (ast_context()->IsTest()) {
3997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Inlined body is treated as if it occurs in an 'inlined' call context
3998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // with true and false blocks that will forward to the real ones.
3999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* if_true = graph()->CreateBasicBlock();
4000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* if_false = graph()->CreateBasicBlock();
4001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if_true->MarkAsInlineReturnTarget();
4002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if_false->MarkAsInlineReturnTarget();
4003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // AstContext constructor pushes on the context stack.
4004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    test_context = new TestContext(this, if_true, if_false);
4005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    function_return_ = NULL;
4006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Inlined body is treated as if it occurs in the original call context.
4008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    function_return_ = graph()->CreateBasicBlock();
4009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    function_return_->MarkAsInlineReturnTarget();
4010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  call_context_ = ast_context();
4012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TypeFeedbackOracle new_oracle(Handle<Code>(shared->code()));
4013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  oracle_ = &new_oracle;
4014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph()->info()->SetOsrAstId(AstNode::kNoNumber);
4015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HSubgraph* body = CreateInlinedSubgraph(env, target, function);
4017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  body->exit_block()->AddInstruction(new HEnterInlined(target, function));
4018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddToSubgraph(body, function->body());
4019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (HasStackOverflow()) {
4020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Bail out if the inline function did, as we cannot residualize a call
4021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // instead.
4022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    delete test_context;
4023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    call_context_ = saved_call_context;
4024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    function_return_ = saved_function_return;
4025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    oracle_ = saved_oracle;
4026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    graph()->info()->SetOsrAstId(saved_osr_ast_id);
4027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return false;
4028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Update inlined nodes count.
4031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  inlined_count_ += nodes_added;
4032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_inlining) TraceInline(target, true);
4034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (body->HasExit()) {
4036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Add a return of undefined if control can fall off the body.  In a
4037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // test context, undefined is false.
4038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* return_value = graph()->GetConstantUndefined();
4039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (test_context == NULL) {
4040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(function_return_ != NULL);
4041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      body->exit_block()->AddLeaveInlined(return_value, function_return_);
4042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
4043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // The graph builder assumes control can reach both branches of a
4044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // test, so we materialize the undefined value and test it rather than
4045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // simply jumping to the false target.
4046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      //
4047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // TODO(3168478): refactor to avoid this.
4048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* empty_true = graph()->CreateBasicBlock();
4049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* empty_false = graph()->CreateBasicBlock();
4050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBranch* branch =
4051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          new HBranch(empty_true, empty_false, return_value);
4052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      body->exit_block()->Finish(branch);
4053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* const no_return_value = NULL;
4055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      empty_true->AddLeaveInlined(no_return_value, test_context->if_true());
4056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      empty_false->AddLeaveInlined(no_return_value, test_context->if_false());
4057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    body->set_exit_block(NULL);
4059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Record the environment at the inlined function call.
4062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddSimulate(expr->ReturnId());
4063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Jump to the function entry (without re-recording the environment).
4065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  subgraph()->exit_block()->Finish(new HGoto(body->entry_block()));
4066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Fix up the function exits.
4068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (test_context != NULL) {
4069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* if_true = test_context->if_true();
4070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* if_false = test_context->if_false();
4071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if_true->SetJoinId(expr->id());
4072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if_false->SetJoinId(expr->id());
4073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(ast_context() == test_context);
4074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    delete test_context;  // Destructor pops from expression context stack.
4075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Forward to the real test context.
4077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* const no_return_value = NULL;
4078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_target->IsInlineReturnTarget()) {
4080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if_true->AddLeaveInlined(no_return_value, true_target);
4081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
4082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if_true->Goto(true_target);
4083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
4086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_target->IsInlineReturnTarget()) {
4087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if_false->AddLeaveInlined(no_return_value, false_target);
4088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
4089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if_false->Goto(false_target);
4090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // TODO(kmillikin): Come up with a better way to handle this. It is too
4093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // subtle. NULL here indicates that the enclosing context has no control
4094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // flow to handle.
4095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    subgraph()->set_exit_block(NULL);
4096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    function_return_->SetJoinId(expr->id());
4099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    subgraph()->set_exit_block(function_return_);
4100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  call_context_ = saved_call_context;
4103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  function_return_ = saved_function_return;
4104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  oracle_ = saved_oracle;
4105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph()->info()->SetOsrAstId(saved_osr_ast_id);
4106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
4108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
4112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(target->IsInlineReturnTarget());
4113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddInstruction(new HLeaveInlined);
4114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* outer = last_environment()->outer();
4115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (return_value != NULL) outer->Push(return_value);
4116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UpdateEnvironment(outer);
4117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Goto(target);
4118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryMathFunctionInline(Call* expr) {
4122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Try to inline calls like Math.* as operations in the calling function.
4123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!expr->target()->shared()->IsBuiltinMathFunction()) return false;
4124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
4125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
4126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (id) {
4127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathRound:
4128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathFloor:
4129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathAbs:
4130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathSqrt:
4131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathLog:
4132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathSin:
4133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathCos:
4134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (argument_count == 2) {
4135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* argument = Pop();
4136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Drop(1);  // Receiver.
4137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HUnaryMathOperation* op = new HUnaryMathOperation(argument, id);
4138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        op->set_position(expr->position());
4139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ast_context()->ReturnInstruction(op, expr->id());
4140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return true;
4141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
4142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case kMathPow:
4144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (argument_count == 3) {
4145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* right = Pop();
4146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* left = Pop();
4147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Pop();  // Pop receiver.
4148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HInstruction* result = NULL;
4149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Use sqrt() if exponent is 0.5 or -0.5.
4150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
4151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          double exponent = HConstant::cast(right)->DoubleValue();
4152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (exponent == 0.5) {
4153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            result = new HUnaryMathOperation(left, kMathPowHalf);
4154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            ast_context()->ReturnInstruction(result, expr->id());
4155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            return true;
4156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (exponent == -0.5) {
4157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HConstant* double_one =
4158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                new HConstant(Handle<Object>(Smi::FromInt(1)),
4159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              Representation::Double());
4160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AddInstruction(double_one);
4161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HUnaryMathOperation* square_root =
4162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                new HUnaryMathOperation(left, kMathPowHalf);
4163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AddInstruction(square_root);
4164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // MathPowHalf doesn't have side effects so there's no need for
4165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // an environment simulation here.
4166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            ASSERT(!square_root->HasSideEffects());
4167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            result = new HDiv(double_one, square_root);
4168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            ast_context()->ReturnInstruction(result, expr->id());
4169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            return true;
4170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (exponent == 2.0) {
4171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            result = new HMul(left, left);
4172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            ast_context()->ReturnInstruction(result, expr->id());
4173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            return true;
4174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
4175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else if (right->IsConstant() &&
4176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HConstant::cast(right)->HasInteger32Value() &&
4177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HConstant::cast(right)->Integer32Value() == 2) {
4178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          result = new HMul(left, left);
4179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          ast_context()->ReturnInstruction(result, expr->id());
4180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          return true;
4181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
4182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        result = new HPower(left, right);
4184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ast_context()->ReturnInstruction(result, expr->id());
4185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return true;
4186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
4187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    default:
4189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Not yet supported for inlining.
4190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return false;
4193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryCallApply(Call* expr) {
4197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Expression* callee = expr->expression();
4198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = callee->AsProperty();
4199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(prop != NULL);
4200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (graph()->info()->scope()->arguments() == NULL) return false;
4202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!name->IsEqualTo(CStrVector("apply"))) return false;
4205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ZoneList<Expression*>* args = expr->arguments();
4207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (args->length() != 2) return false;
4208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* arg_two = args->at(1)->AsVariableProxy();
4210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
4211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* arg_two_value = environment()->Lookup(arg_two->var());
4212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
4213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!expr->IsMonomorphic()) return false;
4215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Found pattern f.apply(receiver, arguments).
4217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForValue(prop->obj());
4218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (HasStackOverflow()) return false;
4219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* function = Pop();
4220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForValue(args->at(0));
4221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (HasStackOverflow()) return false;
4222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* receiver = Pop();
4223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* elements = AddInstruction(new HArgumentsElements);
4224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* length = AddInstruction(new HArgumentsLength(elements));
4225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AddCheckConstantFunction(expr,
4226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           function,
4227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           expr->GetReceiverTypes()->first(),
4228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           true);
4229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* result =
4230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new HApplyArguments(function, receiver, length, elements);
4231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->set_position(expr->position());
4232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, expr->id());
4233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
4234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCall(Call* expr) {
4238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Expression* callee = expr->expression();
4239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
4240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCall* call = NULL;
4241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = callee->AsProperty();
4243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (prop != NULL) {
4244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!prop->key()->IsPropertyName()) {
4245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Keyed function call.
4246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VisitArgument(prop->obj());
4247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK_BAILOUT;
4248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_VALUE(prop->key());
4250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Push receiver and key like the non-optimized code generator expects it.
4251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* key = Pop();
4252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* receiver = Pop();
4253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(key);
4254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Push(receiver);
4255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VisitArgumentList(expr->arguments());
4257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK_BAILOUT;
4258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      call = new HCallKeyed(key, argument_count);
4260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      call->set_position(expr->position());
4261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ProcessCall(call);
4262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(1);  // Key.
4263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnInstruction(call, expr->id());
4264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
4265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Named function call.
4268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    expr->RecordTypeFeedback(oracle());
4269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (TryCallApply(expr)) return;
4271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_BAILOUT;
4272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* receiver = VisitArgument(prop->obj());
4274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_BAILOUT;
4275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitArgumentList(expr->arguments());
4276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_BAILOUT;
4277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    expr->RecordTypeFeedback(oracle());
4281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ZoneMapList* types = expr->GetReceiverTypes();
4282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (expr->IsMonomorphic()) {
4284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddCheckConstantFunction(expr, receiver, types->first(), true);
4285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (TryMathFunctionInline(expr)) {
4287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return;
4288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else if (TryInline(expr)) {
4289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (subgraph()->HasExit()) {
4290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          HValue* return_value = Pop();
4291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          // If we inlined a function in a test context then we need to emit
4292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          // a simulate here to shadow the ones at the end of the
4293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          // predecessor blocks.  Those environments contain the return
4294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          // value on top and do not correspond to any actual state of the
4295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          // unoptimized code.
4296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (ast_context()->IsEffect()) AddSimulate(expr->id());
4297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          ast_context()->ReturnValue(return_value);
4298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
4299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return;
4300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
4301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Check for bailout, as the TryInline call in the if condition above
4302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // might return false due to bailout during hydrogen processing.
4303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        CHECK_BAILOUT;
4304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        call = new HCallConstantFunction(expr->target(), argument_count);
4305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
4306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (types != NULL && types->length() > 1) {
4308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandlePolymorphicCallNamed(expr, receiver, types, name);
4309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
4310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
4312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      call = new HCallNamed(name, argument_count);
4313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool global_call = (var != NULL) && var->is_global() && !var->is_this();
4318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!global_call) {
4320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ++argument_count;
4321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VisitArgument(expr->expression());
4322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK_BAILOUT;
4323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (global_call) {
4326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // If there is a global property cell for the name at compile time and
4327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // access check is not enabled we assume that the function will not change
4328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // and generate optimized code for calling the function.
4329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CompilationInfo* info = graph()->info();
4330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool known_global_function = info->has_global_object() &&
4331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          !info->global_object()->IsAccessCheckNeeded() &&
4332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          expr->ComputeGlobalTarget(Handle<GlobalObject>(info->global_object()),
4333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    var->name());
4334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (known_global_function) {
4335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Push the global object instead of the global receiver because
4336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // code generated by the full code generator expects it.
4337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PushAndAdd(new HGlobalObject);
4338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        VisitArgumentList(expr->arguments());
4339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        CHECK_BAILOUT;
4340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        VISIT_FOR_VALUE(expr->expression());
4342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HValue* function = Pop();
4343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        AddInstruction(new HCheckFunction(function, expr->target()));
4344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Replace the global object with the global receiver.
4346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HGlobalReceiver* global_receiver = new HGlobalReceiver;
4347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Index of the receiver from the top of the expression stack.
4348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        const int receiver_index = argument_count - 1;
4349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        AddInstruction(global_receiver);
4350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(environment()->ExpressionStackAt(receiver_index)->
4351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               IsGlobalObject());
4352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        environment()->SetExpressionStackAt(receiver_index, global_receiver);
4353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (TryInline(expr)) {
4355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (subgraph()->HasExit()) {
4356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            HValue* return_value = Pop();
4357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // If we inlined a function in a test context then we need to
4358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // emit a simulate here to shadow the ones at the end of the
4359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // predecessor blocks.  Those environments contain the return
4360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // value on top and do not correspond to any actual state of the
4361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // unoptimized code.
4362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            if (ast_context()->IsEffect()) AddSimulate(expr->id());
4363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            ast_context()->ReturnValue(return_value);
4364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
4365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          return;
4366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
4367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Check for bailout, as trying to inline might fail due to bailout
4368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // during hydrogen processing.
4369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        CHECK_BAILOUT;
4370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        call = new HCallKnownGlobal(expr->target(), argument_count);
4372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
4373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PushAndAdd(new HGlobalObject);
4374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        VisitArgumentList(expr->arguments());
4375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        CHECK_BAILOUT;
4376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        call = new HCallGlobal(var->name(), argument_count);
4378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
4379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
4381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(new HGlobalReceiver);
4382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VisitArgumentList(expr->arguments());
4383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK_BAILOUT;
4384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      call = new HCallFunction(argument_count);
4386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  call->set_position(expr->position());
4390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ProcessCall(call);
4391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(call, expr->id());
4392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallNew(CallNew* expr) {
4396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The constructor function is also used as the receiver argument to the
4397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // JS construct call builtin.
4398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitArgument(expr->expression());
4399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_BAILOUT;
4400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitArgumentList(expr->arguments());
4401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_BAILOUT;
4402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int argument_count = expr->arguments()->length() + 1;  // Plus constructor.
4404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCall* call = new HCallNew(argument_count);
4405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  call->set_position(expr->position());
4406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ProcessCall(call);
4407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(call, expr->id());
4408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for generating inlined runtime functions.
4412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Lookup table for generators for runtime calls that are  generated inline.
4414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Elements of the table are member pointers to functions of HGraphBuilder.
4415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize)  \
4416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    &HGraphBuilder::Generate##Name,
4417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst HGraphBuilder::InlineFunctionGenerator
4419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HGraphBuilder::kInlineFunctionGenerators[] = {
4420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
4421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
4422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
4423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef INLINE_FUNCTION_GENERATOR_ADDRESS
4424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
4427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<String> name = expr->name();
4428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (name->IsEqualTo(CStrVector("_Log"))) {
4429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnValue(graph()->GetConstantUndefined());
4430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
4431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Runtime::Function* function = expr->function();
4434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->is_jsruntime()) {
4435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BAILOUT("call to a JavaScript runtime function");
4436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(function != NULL);
4438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitArgumentList(expr->arguments());
4440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_BAILOUT;
4441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int argument_count = expr->arguments()->length();
4443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (function->intrinsic_type == Runtime::INLINE) {
4444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(name->length() > 0);
4445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(name->Get(0) == '_');
4446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Call to an inline function.
4447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int lookup_index = static_cast<int>(function->function_id) -
4448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        static_cast<int>(Runtime::kFirstInlineFunction);
4449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(lookup_index >= 0);
4450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(static_cast<size_t>(lookup_index) <
4451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           ARRAY_SIZE(kInlineFunctionGenerators));
4452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
4453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Call the inline code generator using the pointer-to-member.
4455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    (this->*generator)(argument_count, expr->id());
4456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(function->intrinsic_type == Runtime::RUNTIME);
4458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HCall* call = new HCallRuntime(name, expr->function(), argument_count);
4459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    call->set_position(RelocInfo::kNoPosition);
4460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ProcessCall(call);
4461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnInstruction(call, expr->id());
4462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
4467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Token::Value op = expr->op();
4468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (op == Token::VOID) {
4469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_EFFECT(expr->expression());
4470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnValue(graph()->GetConstantUndefined());
4471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::DELETE) {
4472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Property* prop = expr->expression()->AsProperty();
4473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (prop == NULL && var == NULL) {
4475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Result of deleting non-property, non-variable reference is true.
4476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Evaluate the subexpression for side effects.
4477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_EFFECT(expr->expression());
4478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(graph()->GetConstantTrue());
4479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (var != NULL &&
4480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               !var->is_global() &&
4481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               var->AsSlot() != NULL &&
4482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               var->AsSlot()->type() != Slot::LOOKUP) {
4483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Result of deleting non-global, non-dynamic variables is false.
4484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // The subexpression does not have side effects.
4485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(graph()->GetConstantFalse());
4486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (prop != NULL) {
4487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_VALUE(prop->obj());
4488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_VALUE(prop->key());
4489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* key = Pop();
4490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = Pop();
4491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnInstruction(new HDeleteProperty(obj, key),
4492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                       expr->id());
4493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (var->is_global()) {
4494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      BAILOUT("delete with global variable");
4495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
4496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      BAILOUT("delete with non-global variable");
4497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::NOT) {
4499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (ast_context()->IsTest()) {
4500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TestContext* context = TestContext::cast(ast_context());
4501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VisitForControl(expr->expression(),
4502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      context->if_false(),
4503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      context->if_true());
4504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
4505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HSubgraph* true_graph = CreateEmptySubgraph();
4506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HSubgraph* false_graph = CreateEmptySubgraph();
4507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_CONTROL(expr->expression(),
4508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        false_graph->entry_block(),
4509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        true_graph->entry_block());
4510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      true_graph->entry_block()->SetJoinId(expr->expression()->id());
4511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      true_graph->environment()->Push(graph_->GetConstantTrue());
4512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      false_graph->entry_block()->SetJoinId(expr->expression()->id());
4514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      false_graph->environment()->Push(graph_->GetConstantFalse());
4515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current_subgraph_->AppendJoin(true_graph, false_graph, expr);
4517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(Pop());
4518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::BIT_NOT || op == Token::SUB) {
4520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_VALUE(expr->expression());
4521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = Pop();
4522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* instr = NULL;
4523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    switch (op) {
4524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case Token::BIT_NOT:
4525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instr = new HBitNot(value);
4526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        break;
4527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case Token::SUB:
4528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instr = new HMul(graph_->GetConstantMinus1(), value);
4529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        break;
4530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      default:
4531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        UNREACHABLE();
4532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        break;
4533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnInstruction(instr, expr->id());
4535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::TYPEOF) {
4536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_VALUE(expr->expression());
4537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = Pop();
4538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnInstruction(new HTypeof(value), expr->id());
4539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BAILOUT("Value: unsupported unary operation");
4541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) {
4546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // IncrementOperation is never visited by the visitor. It only
4547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // occurs as a subexpression of CountOperation.
4548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UNREACHABLE();
4549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildIncrement(HValue* value, bool increment) {
4553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HConstant* delta = increment
4554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ? graph_->GetConstant1()
4555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : graph_->GetConstantMinus1();
4556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = new HAdd(value, delta);
4557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AssumeRepresentation(instr,  Representation::Integer32());
4558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
4559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCountOperation(CountOperation* expr) {
4563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  IncrementOperation* increment = expr->increment();
4564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Expression* target = increment->expression();
4565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VariableProxy* proxy = target->AsVariableProxy();
4566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Variable* var = proxy->AsVariable();
4567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Property* prop = target->AsProperty();
4568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(var == NULL || prop == NULL);
4569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool inc = expr->op() == Token::INC;
4570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (var != NULL) {
4572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!var->is_global() && !var->IsStackAllocated()) {
4573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      BAILOUT("non-stack/non-global variable in count operation");
4574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_VALUE(target);
4577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Match the full code generator stack by simulating an extra stack
4579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // element for postfix operations in a non-effect context.
4580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* before = has_extra ? Top() : Pop();
4582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* after = BuildIncrement(before, inc);
4583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddInstruction(after);
4584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Push(after);
4585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (var->is_global()) {
4587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HandleGlobalVariableAssignment(var,
4588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     after,
4589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     expr->position(),
4590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     expr->AssignmentId());
4591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
4592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(var->IsStackAllocated());
4593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Bind(var, after);
4594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Drop(has_extra ? 2 : 1);
4596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (prop != NULL) {
4599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    prop->RecordTypeFeedback(oracle());
4600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (prop->key()->IsPropertyName()) {
4602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Named property.
4603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Match the full code generator stack by simulating an extra stack
4605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // element for postfix operations in a non-effect context.
4606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (has_extra) Push(graph_->GetConstantUndefined());
4608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_VALUE(prop->obj());
4610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = Top();
4611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* load = NULL;
4613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (prop->IsMonomorphic()) {
4614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<Map> map = prop->GetReceiverTypes()->first();
4616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamed(obj, prop, map, name);
4617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
4618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        load = BuildLoadNamedGeneric(obj, prop);
4619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
4620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(load);
4621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (load->HasSideEffects()) AddSimulate(increment->id());
4622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* before = Pop();
4624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // There is no deoptimization to after the increment, so we don't need
4625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // to simulate the expression stack after this instruction.
4626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* after = BuildIncrement(before, inc);
4627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(after);
4628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* store = BuildStoreNamed(obj, after, prop);
4630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(store);
4631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Overwrite the receiver in the bailout environment with the result
4633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // of the operation, and the placeholder with the original value if
4634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // necessary.
4635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      environment()->SetExpressionStackAt(0, after);
4636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (has_extra) environment()->SetExpressionStackAt(1, before);
4637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(has_extra ? 2 : 1);
4639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
4643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Keyed property.
4644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Match the full code generator stack by simulate an extra stack element
4646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // for postfix operations in a non-effect context.
4647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (has_extra) Push(graph_->GetConstantUndefined());
4649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_VALUE(prop->obj());
4651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_VALUE(prop->key());
4652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* obj = environment()->ExpressionStackAt(1);
4653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* key = environment()->ExpressionStackAt(0);
4654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool is_fast_elements = prop->IsMonomorphic() &&
4656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          prop->GetMonomorphicReceiverType()->has_fast_elements();
4657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* load = is_fast_elements
4659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          ? BuildLoadKeyedFastElement(obj, key, prop)
4660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          : BuildLoadKeyedGeneric(obj, key);
4661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PushAndAdd(load);
4662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (load->HasSideEffects()) AddSimulate(increment->id());
4663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* before = Pop();
4665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // There is no deoptimization to after the increment, so we don't need
4666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // to simulate the expression stack after this instruction.
4667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* after = BuildIncrement(before, inc);
4668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(after);
4669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* store = is_fast_elements
4671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          ? BuildStoreKeyedFastElement(obj, key, after, prop)
4672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          : new HStoreKeyedGeneric(obj, key, after);
4673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddInstruction(store);
4674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Drop the key from the bailout environment.  Overwrite the receiver
4676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // with the result of the operation, and the placeholder with the
4677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // original value if necessary.
4678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(1);
4679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      environment()->SetExpressionStackAt(0, after);
4680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (has_extra) environment()->SetExpressionStackAt(1, before);
4681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Drop(has_extra ? 2 : 1);
4683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BAILOUT("invalid lhs in count operation");
4689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
4694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  HValue* left,
4695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  HValue* right) {
4696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = NULL;
4697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (expr->op()) {
4698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::ADD:
4699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = new HAdd(left, right);
4700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::SUB:
4702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = new HSub(left, right);
4703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::MUL:
4705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = new HMul(left, right);
4706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::MOD:
4708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = new HMod(left, right);
4709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::DIV:
4711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = new HDiv(left, right);
4712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::BIT_XOR:
4714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = new HBitXor(left, right);
4715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::BIT_AND:
4717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = new HBitAnd(left, right);
4718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::BIT_OR:
4720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = new HBitOr(left, right);
4721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::SAR:
4723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = new HSar(left, right);
4724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::SHR:
4726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = new HShr(left, right);
4727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::SHL:
4729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      instr = new HShl(left, right);
4730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    default:
4732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNREACHABLE();
4733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TypeInfo info = oracle()->BinaryType(expr, TypeFeedbackOracle::RESULT);
4735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If we hit an uninitialized binary op stub we will get type info
4736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // for a smi operation. If one of the operands is a constant string
4737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // do not generate code assuming it is a smi operation.
4738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsSmi() &&
4739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) ||
4740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch       (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) {
4741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return instr;
4742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_representation) {
4744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("Info: %s/%s\n", info.ToString(), ToRepresentation(info).Mnemonic());
4745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AssumeRepresentation(instr, ToRepresentation(info));
4747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return instr;
4748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check for the form (%_ClassOf(foo) === 'BarClass').
4752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool IsClassOfTest(CompareOperation* expr) {
4753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->op() != Token::EQ_STRICT) return false;
4754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CallRuntime* call = expr->left()->AsCallRuntime();
4755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (call == NULL) return false;
4756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Literal* literal = expr->right()->AsLiteral();
4757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (literal == NULL) return false;
4758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!literal->handle()->IsString()) return false;
4759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false;
4760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(call->arguments()->length() == 1);
4761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
4762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
4766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expr->op() == Token::COMMA) {
4767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_EFFECT(expr->left());
4768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Visit the right subexpression in the same AST context as the entire
4769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // expression.
4770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Visit(expr->right());
4771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (expr->op() == Token::AND || expr->op() == Token::OR) {
4773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool is_logical_and = (expr->op() == Token::AND);
4774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (ast_context()->IsTest()) {
4775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      TestContext* context = TestContext::cast(ast_context());
4776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Translate left subexpression.
4777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HBasicBlock* eval_right = graph()->CreateBasicBlock();
4778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (is_logical_and) {
4779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        VISIT_FOR_CONTROL(expr->left(), eval_right, context->if_false());
4780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
4781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        VISIT_FOR_CONTROL(expr->left(), context->if_true(), eval_right);
4782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
4783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      eval_right->SetJoinId(expr->RightId());
4784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Translate right subexpression by visiting it in the same AST
4786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // context as the entire expression.
4787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      subgraph()->set_exit_block(eval_right);
4788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Visit(expr->right());
4789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
4791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      VISIT_FOR_VALUE(expr->left());
4792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(current_subgraph_->HasExit());
4793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* left = Top();
4795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HEnvironment* environment_copy = environment()->Copy();
4796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      environment_copy->Pop();
4797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HSubgraph* right_subgraph;
4798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      right_subgraph = CreateBranchSubgraph(environment_copy);
4799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ADD_TO_SUBGRAPH(right_subgraph, expr->right());
4800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current_subgraph_->AppendOptional(right_subgraph, is_logical_and, left);
4801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current_subgraph_->exit_block()->SetJoinId(expr->id());
4802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_context()->ReturnValue(Pop());
4803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_VALUE(expr->left());
4807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_VALUE(expr->right());
4808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* right = Pop();
4810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* left = Pop();
4811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* instr = BuildBinaryOperation(expr, left, right);
4812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_position(expr->position());
4813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnInstruction(instr, expr->id());
4814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) {
4819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (value->CheckFlag(HValue::kFlexibleRepresentation)) {
4820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (FLAG_trace_representation) {
4821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintF("Assume representation for %s to be %s (%d)\n",
4822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             value->Mnemonic(),
4823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             r.Mnemonic(),
4824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             graph_->GetMaximumValueID());
4825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    value->ChangeRepresentation(r);
4827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // The representation of the value is dictated by type feedback.
4828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    value->ClearFlag(HValue::kFlexibleRepresentation);
4829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (FLAG_trace_representation) {
4830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("No representation assumed\n");
4831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochRepresentation HGraphBuilder::ToRepresentation(TypeInfo info) {
4836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsSmi()) return Representation::Integer32();
4837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsInteger32()) return Representation::Integer32();
4838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsDouble()) return Representation::Double();
4839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (info.IsNumber()) return Representation::Double();
4840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Representation::Tagged();
4841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
4845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (IsClassOfTest(expr)) {
4846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CallRuntime* call = expr->left()->AsCallRuntime();
4847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_VALUE(call->arguments()->at(0));
4848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = Pop();
4849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Literal* literal = expr->right()->AsLiteral();
4850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<String> rhs = Handle<String>::cast(literal->handle());
4851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* instr = new HClassOfTest(value, rhs);
4852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_position(expr->position());
4853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnInstruction(instr, expr->id());
4854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
4855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check for the pattern: typeof <expression> == <string literal>.
4858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UnaryOperation* left_unary = expr->left()->AsUnaryOperation();
4859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Literal* right_literal = expr->right()->AsLiteral();
4860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) &&
4861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      left_unary != NULL && left_unary->op() == Token::TYPEOF &&
4862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      right_literal != NULL && right_literal->handle()->IsString()) {
4863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VISIT_FOR_VALUE(left_unary->expression());
4864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* left = Pop();
4865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HInstruction* instr = new HTypeofIs(left,
4866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<String>::cast(right_literal->handle()));
4867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr->set_position(expr->position());
4868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ast_context()->ReturnInstruction(instr, expr->id());
4869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
4870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VISIT_FOR_VALUE(expr->left());
4873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VISIT_FOR_VALUE(expr->right());
4874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* right = Pop();
4876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* left = Pop();
4877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Token::Value op = expr->op();
4878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TypeInfo info = oracle()->CompareType(expr, TypeFeedbackOracle::RESULT);
4880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* instr = NULL;
4881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (op == Token::INSTANCEOF) {
4882086aeeaae12517475c22695a200be45495516549Ben Murdoch    // Check to see if the rhs of the instanceof is a global function not
4883086aeeaae12517475c22695a200be45495516549Ben Murdoch    // residing in new space. If it is we assume that the function will stay the
4884086aeeaae12517475c22695a200be45495516549Ben Murdoch    // same.
4885086aeeaae12517475c22695a200be45495516549Ben Murdoch    Handle<JSFunction> target = Handle<JSFunction>::null();
4886086aeeaae12517475c22695a200be45495516549Ben Murdoch    Variable* var = expr->right()->AsVariableProxy()->AsVariable();
4887086aeeaae12517475c22695a200be45495516549Ben Murdoch    bool global_function = (var != NULL) && var->is_global() && !var->is_this();
4888086aeeaae12517475c22695a200be45495516549Ben Murdoch    CompilationInfo* info = graph()->info();
4889086aeeaae12517475c22695a200be45495516549Ben Murdoch    if (global_function &&
4890086aeeaae12517475c22695a200be45495516549Ben Murdoch        info->has_global_object() &&
4891086aeeaae12517475c22695a200be45495516549Ben Murdoch        !info->global_object()->IsAccessCheckNeeded()) {
4892086aeeaae12517475c22695a200be45495516549Ben Murdoch      Handle<String> name = var->name();
4893086aeeaae12517475c22695a200be45495516549Ben Murdoch      Handle<GlobalObject> global(info->global_object());
4894086aeeaae12517475c22695a200be45495516549Ben Murdoch      LookupResult lookup;
4895086aeeaae12517475c22695a200be45495516549Ben Murdoch      global->Lookup(*name, &lookup);
4896086aeeaae12517475c22695a200be45495516549Ben Murdoch      if (lookup.IsProperty() &&
4897086aeeaae12517475c22695a200be45495516549Ben Murdoch          lookup.type() == NORMAL &&
4898086aeeaae12517475c22695a200be45495516549Ben Murdoch          lookup.GetValue()->IsJSFunction()) {
4899086aeeaae12517475c22695a200be45495516549Ben Murdoch        Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
4900086aeeaae12517475c22695a200be45495516549Ben Murdoch        // If the function is in new space we assume it's more likely to
4901086aeeaae12517475c22695a200be45495516549Ben Murdoch        // change and thus prefer the general IC code.
4902086aeeaae12517475c22695a200be45495516549Ben Murdoch        if (!Heap::InNewSpace(*candidate)) {
4903086aeeaae12517475c22695a200be45495516549Ben Murdoch          target = candidate;
4904086aeeaae12517475c22695a200be45495516549Ben Murdoch        }
4905086aeeaae12517475c22695a200be45495516549Ben Murdoch      }
4906086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
4907086aeeaae12517475c22695a200be45495516549Ben Murdoch
4908086aeeaae12517475c22695a200be45495516549Ben Murdoch    // If the target is not null we have found a known global function that is
4909086aeeaae12517475c22695a200be45495516549Ben Murdoch    // assumed to stay the same for this instanceof.
4910086aeeaae12517475c22695a200be45495516549Ben Murdoch    if (target.is_null()) {
4911086aeeaae12517475c22695a200be45495516549Ben Murdoch      instr = new HInstanceOf(left, right);
4912086aeeaae12517475c22695a200be45495516549Ben Murdoch    } else {
4913086aeeaae12517475c22695a200be45495516549Ben Murdoch      AddInstruction(new HCheckFunction(right, target));
4914086aeeaae12517475c22695a200be45495516549Ben Murdoch      instr = new HInstanceOfKnownGlobal(left, target);
4915086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
4916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (op == Token::IN) {
4917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BAILOUT("Unsupported comparison: in");
4918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (info.IsNonPrimitive()) {
4919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    switch (op) {
4920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case Token::EQ:
4921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      case Token::EQ_STRICT: {
49229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        AddInstruction(new HCheckNonSmi(left));
4923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left));
49249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        AddInstruction(new HCheckNonSmi(right));
4925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right));
4926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instr = new HCompareJSObjectEq(left, right);
4927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        break;
4928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
4929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      default:
4930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        BAILOUT("Unsupported non-primitive compare");
4931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        break;
4932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
4933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HCompare* compare = new HCompare(left, right, op);
4935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Representation r = ToRepresentation(info);
4936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    compare->SetInputRepresentation(r);
4937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    instr = compare;
4938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  instr->set_position(expr->position());
4940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(instr, expr->id());
4941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCompareToNull(CompareToNull* expr) {
4945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VISIT_FOR_VALUE(expr->expression());
4946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
4948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HIsNull* compare = new HIsNull(value, expr->is_strict());
4949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(compare, expr->id());
4950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
4954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("ThisFunction");
4955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDeclaration(Declaration* decl) {
4959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We allow only declarations that do not require code generation.
4960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The following all require code generation: global variables and
4961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // functions, variables with slot type LOOKUP, declarations with
4962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // mode CONST, and functions.
4963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Variable* var = decl->proxy()->var();
4964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Slot* slot = var->AsSlot();
4965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (var->is_global() ||
4966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      (slot != NULL && slot->type() == Slot::LOOKUP) ||
4967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      decl->mode() == Variable::CONST ||
4968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      decl->fun() != NULL) {
4969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    BAILOUT("unsupported declaration");
4970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Generators for inline runtime functions.
4975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for types.
4976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsSmi(int argument_count, int ast_id) {
4977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(argument_count == 1);
4978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
4979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HIsSmi* result = new HIsSmi(value);
4980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
4981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsSpecObject(int argument_count, int ast_id) {
4985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(argument_count == 1);
4986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
4987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HHasInstanceType* result =
4988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE);
4989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
4990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsFunction(int argument_count, int ast_id) {
4994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(argument_count == 1);
4995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
4996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HHasInstanceType* result = new HHasInstanceType(value, JS_FUNCTION_TYPE);
4997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
4998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateHasCachedArrayIndex(int argument_count,
5002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                int ast_id) {
5003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(argument_count == 1);
5004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
5005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HHasCachedArrayIndex* result = new HHasCachedArrayIndex(value);
5006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsArray(int argument_count, int ast_id) {
5011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(argument_count == 1);
5012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
5013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HHasInstanceType* result = new HHasInstanceType(value, JS_ARRAY_TYPE);
5014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsRegExp(int argument_count, int ast_id) {
5019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(argument_count == 1);
5020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
5021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HHasInstanceType* result = new HHasInstanceType(value, JS_REGEXP_TYPE);
5022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsObject(int argument_count, int ast_id) {
5027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(argument_count == 1);
5028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
5030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HIsObject* test = new HIsObject(value);
5031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(test, ast_id);
5032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count,
5036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             int ast_id) {
5037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: IsNonNegativeSmi");
5038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsUndetectableObject(int argument_count,
5042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                 int ast_id) {
5043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: IsUndetectableObject");
5044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
5048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int argument_count,
5049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int ast_id) {
5050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
5051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Support for construct call checks.
5055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsConstructCall(int argument_count, int ast_id) {
5056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: IsConstructCall");
5057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for arguments.length and arguments[?].
5061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateArgumentsLength(int argument_count, int ast_id) {
5062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(argument_count == 0);
5063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* elements = AddInstruction(new HArgumentsElements);
5064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HArgumentsLength* result = new HArgumentsLength(elements);
5065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateArguments(int argument_count, int ast_id) {
5070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(argument_count == 1);
5071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* index = Pop();
5072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* elements = AddInstruction(new HArgumentsElements);
5073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HInstruction* length = AddInstruction(new HArgumentsLength(elements));
5074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HAccessArgumentsAt* result = new HAccessArgumentsAt(elements, length, index);
5075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for accessing the class and value fields of an object.
5080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateClassOf(int argument_count, int ast_id) {
5081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The special form detected by IsClassOfTest is detected before we get here
5082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // and does not cause a bailout.
5083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: ClassOf");
5084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateValueOf(int argument_count, int ast_id) {
5088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(argument_count == 1);
5089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* value = Pop();
5090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValueOf* result = new HValueOf(value);
5091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateSetValueOf(int argument_count, int ast_id) {
5096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: SetValueOf");
5097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for charCodeAt(n).
5101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateStringCharCodeAt(int argument_count, int ast_id) {
5102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: StringCharCodeAt");
5103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n].
5107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateStringCharFromCode(int argument_count,
5108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                               int ast_id) {
5109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: StringCharFromCode");
5110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n].
5114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) {
5115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT_EQ(2, argument_count);
5116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushArgumentsForStubCall(argument_count);
5117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCallStub* result = new HCallStub(CodeStub::StringCharAt, argument_count);
5118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for object equality testing.
5123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateObjectEquals(int argument_count, int ast_id) {
5124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(argument_count == 2);
5125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* right = Pop();
5126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* left = Pop();
5127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCompareJSObjectEq* result = new HCompareJSObjectEq(left, right);
5128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateLog(int argument_count, int ast_id) {
5133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UNREACHABLE();  // We caught this in VisitCallRuntime.
5134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for Math.random().
5138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateRandomHeapNumber(int argument_count, int ast_id) {
5139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: RandomHeapNumber");
5140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringAdd.
5144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) {
5145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT_EQ(2, argument_count);
5146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushArgumentsForStubCall(argument_count);
5147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCallStub* result = new HCallStub(CodeStub::StringAdd, argument_count);
5148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for SubString.
5153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateSubString(int argument_count, int ast_id) {
5154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT_EQ(3, argument_count);
5155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushArgumentsForStubCall(argument_count);
5156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCallStub* result = new HCallStub(CodeStub::SubString, argument_count);
5157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringCompare.
5162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) {
5163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT_EQ(2, argument_count);
5164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushArgumentsForStubCall(argument_count);
5165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCallStub* result = new HCallStub(CodeStub::StringCompare, argument_count);
5166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for direct calls from JavaScript to native RegExp code.
5171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) {
5172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT_EQ(4, argument_count);
5173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushArgumentsForStubCall(argument_count);
5174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCallStub* result = new HCallStub(CodeStub::RegExpExec, argument_count);
5175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Construct a RegExp exec result with two in-object properties.
5180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateRegExpConstructResult(int argument_count,
5181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  int ast_id) {
5182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT_EQ(3, argument_count);
5183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushArgumentsForStubCall(argument_count);
5184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCallStub* result =
5185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new HCallStub(CodeStub::RegExpConstructResult, argument_count);
5186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for fast native caches.
5191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateGetFromCache(int argument_count, int ast_id) {
5192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: GetFromCache");
5193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for number to string.
5197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) {
5198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT_EQ(1, argument_count);
5199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushArgumentsForStubCall(argument_count);
5200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCallStub* result = new HCallStub(CodeStub::NumberToString, argument_count);
5201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast swapping of elements. Takes three expressions, the object and two
5206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// indices. This should only be used if the indices are known to be
5207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// non-negative and within bounds of the elements array at the call site.
5208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateSwapElements(int argument_count, int ast_id) {
5209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: SwapElements");
5210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call for custom callbacks.
5214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateCallFunction(int argument_count, int ast_id) {
5215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: CallFunction");
5216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call to math functions.
5220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateMathPow(int argument_count, int ast_id) {
5221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT_EQ(2, argument_count);
5222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* right = Pop();
5223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HValue* left = Pop();
5224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HPower* result = new HPower(left, right);
5225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) {
5230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT_EQ(1, argument_count);
5231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushArgumentsForStubCall(argument_count);
5232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCallStub* result =
5233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new HCallStub(CodeStub::TranscendentalCache, argument_count);
5234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->set_transcendental_type(TranscendentalCache::SIN);
5235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) {
5240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT_EQ(1, argument_count);
5241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushArgumentsForStubCall(argument_count);
5242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCallStub* result =
5243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new HCallStub(CodeStub::TranscendentalCache, argument_count);
5244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->set_transcendental_type(TranscendentalCache::COS);
5245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) {
5250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT_EQ(1, argument_count);
5251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PushArgumentsForStubCall(argument_count);
5252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HCallStub* result =
5253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new HCallStub(CodeStub::TranscendentalCache, argument_count);
5254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->set_transcendental_type(TranscendentalCache::LOG);
5255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ast_context()->ReturnInstruction(result, ast_id);
5256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateMathSqrt(int argument_count, int ast_id) {
5260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: MathSqrt");
5261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check whether two RegExps are equivalent
5265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsRegExpEquivalent(int argument_count,
5266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                               int ast_id) {
5267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: IsRegExpEquivalent");
5268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateGetCachedArrayIndex(int argument_count,
5272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                int ast_id) {
5273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: GetCachedArrayIndex");
5274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateFastAsciiArrayJoin(int argument_count,
5278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                               int ast_id) {
5279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BAILOUT("inlined runtime function: FastAsciiArrayJoin");
5280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef BAILOUT
5284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef CHECK_BAILOUT
5285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef VISIT_FOR_EFFECT
5286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef VISIT_FOR_VALUE
5287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef ADD_TO_SUBGRAPH
5288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(HEnvironment* outer,
5291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           Scope* scope,
5292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           Handle<JSFunction> closure)
5293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : closure_(closure),
5294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      values_(0),
5295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      assigned_variables_(4),
5296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parameter_count_(0),
5297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      local_count_(0),
5298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_(outer),
5299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      pop_count_(0),
5300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      push_count_(0),
5301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_id_(AstNode::kNoNumber) {
5302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0);
5303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(const HEnvironment* other)
5307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : values_(0),
5308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      assigned_variables_(0),
5309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parameter_count_(0),
5310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      local_count_(0),
5311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      outer_(NULL),
5312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      pop_count_(0),
5313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      push_count_(0),
5314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ast_id_(other->ast_id()) {
5315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Initialize(other);
5316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::Initialize(int parameter_count,
5320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              int local_count,
5321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              int stack_height) {
5322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  parameter_count_ = parameter_count;
5323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  local_count_ = local_count;
5324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Avoid reallocating the temporaries' backing store on the first Push.
5326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int total = parameter_count + local_count + stack_height;
5327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  values_.Initialize(total + 4);
5328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < total; ++i) values_.Add(NULL);
5329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
53329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Initialize(const HEnvironment* other) {
53339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  closure_ = other->closure();
53349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  values_.AddAll(other->values_);
53359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  assigned_variables_.AddAll(other->assigned_variables_);
53369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  parameter_count_ = other->parameter_count_;
53379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  local_count_ = other->local_count_;
53389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (other->outer_ != NULL) outer_ = other->outer_->Copy();  // Deep copy.
53399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  pop_count_ = other->pop_count_;
53409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  push_count_ = other->push_count_;
53419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ast_id_ = other->ast_id_;
53429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
53439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
53449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
5345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
5346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!block->IsLoopHeader());
5347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(values_.length() == other->values_.length());
5348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = values_.length();
5350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; ++i) {
5351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* value = values_[i];
5352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (value != NULL && value->IsPhi() && value->block() == block) {
5353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // There is already a phi for the i'th value.
5354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = HPhi::cast(value);
5355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Assert index is correct and that we haven't missed an incoming edge.
5356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(phi->merged_index() == i);
5357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(phi->OperandCount() == block->predecessors()->length());
5358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->AddInput(other->values_[i]);
5359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (values_[i] != other->values_[i]) {
5360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // There is a fresh value on the incoming edge, a phi is needed.
5361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(values_[i] != NULL && other->values_[i] != NULL);
5362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HPhi* phi = new HPhi(i);
5363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* old_value = values_[i];
5364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < block->predecessors()->length(); j++) {
5365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->AddInput(old_value);
5366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      phi->AddInput(other->values_[i]);
5368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      this->values_[i] = phi;
5369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      block->AddPhi(phi);
5370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
53759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Bind(int index, HValue* value) {
53769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(value != NULL);
53779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (!assigned_variables_.Contains(index)) {
53789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    assigned_variables_.Add(index);
53799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
53809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  values_[index] = value;
5381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
53849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::HasExpressionAt(int index) const {
53859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return index >= parameter_count_ + local_count_;
53869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
53879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
53889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
53899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::ExpressionStackIsEmpty() const {
53909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  int first_expression = parameter_count() + local_count();
53919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(length() >= first_expression);
53929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return length() == first_expression;
53939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
53949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
53959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
53969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
53979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  int count = index_from_top + 1;
53989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  int index = values_.length() - count;
53999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(HasExpressionAt(index));
54009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // The push count must include at least the element in question or else
54019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // the new value will not be included in this environment's history.
54029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (push_count_ < count) {
54039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // This is the same effect as popping then re-pushing 'count' elements.
54049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    pop_count_ += (count - push_count_);
54059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    push_count_ = count;
54069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
54079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  values_[index] = value;
54089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
54099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
54109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
54119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Drop(int count) {
54129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  for (int i = 0; i < count; ++i) {
54139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Pop();
5414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::Copy() const {
5419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return new HEnvironment(this);
5420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyWithoutHistory() const {
5424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* result = Copy();
5425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->ClearHistory();
5426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
5427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
5431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* new_env = Copy();
5432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < values_.length(); ++i) {
5433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HPhi* phi = new HPhi(i);
5434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    phi->AddInput(values_[i]);
5435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    new_env->values_[i] = phi;
5436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    loop_header->AddPhi(phi);
5437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  new_env->ClearHistory();
5439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return new_env;
5440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyForInlining(Handle<JSFunction> target,
5444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            FunctionLiteral* function,
5445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            bool is_speculative,
5446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            HConstant* undefined) const {
5447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Outer environment is a copy of this one without the arguments.
5448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int arity = function->scope()->num_parameters();
5449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* outer = Copy();
5450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  outer->Drop(arity + 1);  // Including receiver.
5451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  outer->ClearHistory();
5452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HEnvironment* inner = new HEnvironment(outer, function->scope(), target);
5453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Get the argument values from the original environment.
5454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (is_speculative) {
5455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i <= arity; ++i) {  // Include receiver.
5456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HValue* push = ExpressionStackAt(arity - i);
5457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      inner->SetValueAt(i, push);
5458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
5460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i <= arity; ++i) {  // Include receiver.
5461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      inner->SetValueAt(i, ExpressionStackAt(arity - i));
5462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Initialize the stack-allocated locals to undefined.
5466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int local_base = arity + 1;
5467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int local_count = function->scope()->num_stack_slots();
5468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < local_count; ++i) {
5469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    inner->SetValueAt(local_base + i, undefined);
5470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  inner->set_ast_id(function->id());
5473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return inner;
5474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintTo(StringStream* stream) {
54789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  for (int i = 0; i < length(); i++) {
5479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (i == 0) stream->Add("parameters\n");
5480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (i == parameter_count()) stream->Add("locals\n");
5481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (i == parameter_count() + local_count()) stream->Add("expressions");
5482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HValue* val = values_.at(i);
5483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    stream->Add("%d: ", i);
5484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (val != NULL) {
5485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      val->PrintNameTo(stream);
5486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
5487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      stream->Add("NULL");
5488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    stream->Add("\n");
5490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintToStd() {
5495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HeapStringAllocator string_allocator;
5496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StringStream trace(&string_allocator);
5497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintTo(&trace);
5498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("%s", *trace.ToCString());
5499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceCompilation(FunctionLiteral* function) {
5503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Tag tag(this, "compilation");
5504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<String> name = function->debug_name();
5505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("name", *name->ToCString());
5506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("method", *name->ToCString());
5507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis()));
5508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLithium(const char* name, LChunk* chunk) {
5512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Trace(name, chunk->graph(), chunk);
5513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceHydrogen(const char* name, HGraph* graph) {
5517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Trace(name, graph, NULL);
5518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
5522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Tag tag(this, "cfg");
5523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("name", name);
5524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<HBasicBlock*>* blocks = graph->blocks();
5525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < blocks->length(); i++) {
5526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HBasicBlock* current = blocks->at(i);
5527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Tag block_tag(this, "block");
5528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintBlockProperty("name", current->block_id());
5529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintIntProperty("from_bci", -1);
5530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintIntProperty("to_bci", -1);
5531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!current->predecessors()->is_empty()) {
5533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintIndent();
5534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add("predecessors");
5535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < current->predecessors()->length(); ++j) {
5536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
5537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add("\n");
5539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
5540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintEmptyProperty("predecessors");
5541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->end() == NULL || current->end()->FirstSuccessor() == NULL) {
5544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintEmptyProperty("successors");
5545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (current->end()->SecondSuccessor() == NULL) {
5546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintBlockProperty("successors",
5547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             current->end()->FirstSuccessor()->block_id());
5548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
5549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintBlockProperty("successors",
5550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             current->end()->FirstSuccessor()->block_id(),
5551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             current->end()->SecondSuccessor()->block_id());
5552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintEmptyProperty("xhandlers");
5555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintEmptyProperty("flags");
5556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->dominator() != NULL) {
5558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintBlockProperty("dominator", current->dominator()->block_id());
5559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (chunk != NULL) {
5562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int first_index = current->first_instruction_index();
5563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int last_index = current->last_instruction_index();
5564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintIntProperty(
5565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          "first_lir_id",
5566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          LifetimePosition::FromInstructionIndex(first_index).Value());
5567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintIntProperty(
5568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          "last_lir_id",
5569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          LifetimePosition::FromInstructionIndex(last_index).Value());
5570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    {
5573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag states_tag(this, "states");
5574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag locals_tag(this, "locals");
5575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int total = current->phis()->length();
5576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add("size %d\n", total);
5577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add("method \"None\"");
5578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int j = 0; j < total; ++j) {
5579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        HPhi* phi = current->phis()->at(j);
5580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add("%d ", phi->merged_index());
5581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->PrintNameTo(&trace_);
5582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" ");
5583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        phi->PrintTo(&trace_);
5584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add("\n");
5585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    {
5589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag HIR_tag(this, "HIR");
5590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HInstruction* instruction = current->first();
5591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      while (instruction != NULL) {
5592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int bci = 0;
5593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int uses = instruction->uses()->length();
5594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add("%d %d ", bci, uses);
5595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instruction->PrintNameTo(&trace_);
5596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" ");
5597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instruction->PrintTo(&trace_);
5598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" <|@\n");
5599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        instruction = instruction->next();
5600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (chunk != NULL) {
5605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Tag LIR_tag(this, "LIR");
5606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int first_index = current->first_instruction_index();
5607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int last_index = current->last_instruction_index();
5608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (first_index != -1 && last_index != -1) {
5609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        const ZoneList<LInstruction*>* instructions = chunk->instructions();
5610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        for (int i = first_index; i <= last_index; ++i) {
5611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          LInstruction* linstr = instructions->at(i);
5612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          if (linstr != NULL) {
5613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            trace_.Add("%d ",
5614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       LifetimePosition::FromInstructionIndex(i).Value());
5615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            linstr->PrintTo(&trace_);
5616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            trace_.Add(" <|@\n");
5617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          }
5618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
5619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
5626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Tag tag(this, "intervals");
5627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintStringProperty("name", name);
5628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
5630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < fixed_d->length(); ++i) {
5631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceLiveRange(fixed_d->at(i), "fixed");
5632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<LiveRange*>* fixed = allocator->fixed_live_ranges();
5635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < fixed->length(); ++i) {
5636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceLiveRange(fixed->at(i), "fixed");
5637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
5640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < live_ranges->length(); ++i) {
5641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    TraceLiveRange(live_ranges->at(i), "object");
5642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRange(LiveRange* range, const char* type) {
5647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (range != NULL && !range->IsEmpty()) {
5648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    trace_.Add("%d %s", range->id(), type);
5649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (range->HasRegisterAssigned()) {
5650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      LOperand* op = range->CreateAssignedOperand();
5651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int assigned_reg = op->index();
5652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (op->IsDoubleRegister()) {
5653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"%s\"",
5654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   DoubleRegister::AllocationIndexToString(assigned_reg));
5655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
5656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(op->IsRegister());
5657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg));
5658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (range->IsSpilled()) {
5660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      LOperand* op = range->TopLevel()->GetSpillOperand();
5661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (op->IsDoubleStackSlot()) {
5662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"double_stack:%d\"", op->index());
5663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
5664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        ASSERT(op->IsStackSlot());
5665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" \"stack:%d\"", op->index());
5666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int parent_index = -1;
5669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (range->IsChild()) {
5670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parent_index = range->parent()->id();
5671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
5672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      parent_index = range->id();
5673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    LOperand* op = range->FirstHint();
5675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int hint_index = -1;
5676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (op != NULL && op->IsUnallocated()) hint_index = op->VirtualRegister();
5677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    trace_.Add(" %d %d", parent_index, hint_index);
5678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    UseInterval* cur_interval = range->first_interval();
5679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (cur_interval != NULL) {
5680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      trace_.Add(" [%d, %d[",
5681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 cur_interval->start().Value(),
5682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 cur_interval->end().Value());
5683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      cur_interval = cur_interval->next();
5684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    UsePosition* current_pos = range->first_pos();
5687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    while (current_pos != NULL) {
5688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (current_pos->RegisterIsBeneficial()) {
5689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        trace_.Add(" %d M", current_pos->pos().Value());
5690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      current_pos = current_pos->next();
5692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    trace_.Add(" \"\"\n");
5695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::FlushToFile() {
5700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AppendChars(filename_, *trace_.ToCString(), trace_.length(), false);
5701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  trace_.Reset();
5702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStatistics::Print() {
5706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("Timing results:\n");
5707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int64_t sum = 0;
5708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < timing_.length(); ++i) {
5709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    sum += timing_[i];
5710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < names_.length(); ++i) {
5713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("%30s", names_[i]);
5714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    double ms = static_cast<double>(timing_[i]) / 1000;
5715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    double percent = static_cast<double>(timing_[i]) * 100 / sum;
5716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF(" - %0.3f ms / %0.3f %% \n", ms, percent);
5717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("%30s - %0.3f ms \n", "Sum", static_cast<double>(sum) / 1000);
5719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("---------------------------------------------------------------\n");
5720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("%30s - %0.3f ms (%0.1f times slower than full code gen)\n",
5721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         "Total",
5722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         static_cast<double>(total_) / 1000,
5723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         static_cast<double>(total_) / full_code_gen_);
5724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStatistics::SaveTiming(const char* name, int64_t ticks) {
5728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (name == HPhase::kFullCodeGen) {
5729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    full_code_gen_ += ticks;
5730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (name == HPhase::kTotal) {
5731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    total_ += ticks;
5732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
5733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = 0; i < names_.length(); ++i) {
5734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (names_[i] == name) {
5735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        timing_[i] += ticks;
5736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return;
5737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
5738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    names_.Add(name);
5740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    timing_.Add(ticks);
5741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kFullCodeGen = "Full code generator";
5746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kTotal = "Total";
5747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::Begin(const char* name,
5750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   HGraph* graph,
5751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   LChunk* chunk,
5752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   LAllocator* allocator) {
5753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  name_ = name;
5754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  graph_ = graph;
5755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  chunk_ = chunk;
5756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  allocator_ = allocator;
5757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (allocator != NULL && chunk_ == NULL) {
5758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    chunk_ = allocator->chunk();
5759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_time_hydrogen) start_ = OS::Ticks();
5761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::End() const {
5765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_time_hydrogen) {
5766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int64_t end = OS::Ticks();
5767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    HStatistics::Instance()->SaveTiming(name_, end - start_);
5768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_hydrogen) {
5771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_);
5772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_);
5773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (allocator_ != NULL) {
5774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HTracer::Instance()->TraceLiveRanges(name_, allocator_);
5775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
5776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
5779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (graph_ != NULL) graph_->Verify();
5780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (chunk_ != NULL) chunk_->Verify();
5781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (allocator_ != NULL) allocator_->Verify();
5782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
5783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} }  // namespace v8::internal
5786