blob: 907279ad511617257b8b28de6359cde2910cdf93 [file] [log] [blame]
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001// Copyright 2012 the V8 project authors. All rights reserved.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_HYDROGEN_H_
29#define V8_HYDROGEN_H_
30
31#include "v8.h"
32
lrn@chromium.org1c092762011-05-09 09:42:16 +000033#include "allocation.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000034#include "ast.h"
35#include "compiler.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000036#include "hydrogen-instructions.h"
vegorov@chromium.org7304bca2011-05-16 12:14:13 +000037#include "type-info.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000038#include "zone.h"
39
40namespace v8 {
41namespace internal {
42
43// Forward declarations.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000044class BitVector;
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000045class FunctionState;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000046class HEnvironment;
47class HGraph;
48class HLoopInformation;
49class HTracer;
50class LAllocator;
51class LChunk;
52class LiveRange;
53
54
55class HBasicBlock: public ZoneObject {
56 public:
57 explicit HBasicBlock(HGraph* graph);
58 virtual ~HBasicBlock() { }
59
60 // Simple accessors.
61 int block_id() const { return block_id_; }
62 void set_block_id(int id) { block_id_ = id; }
63 HGraph* graph() const { return graph_; }
64 const ZoneList<HPhi*>* phis() const { return &phis_; }
65 HInstruction* first() const { return first_; }
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +000066 HInstruction* last() const { return last_; }
67 void set_last(HInstruction* instr) { last_ = instr; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +000068 HInstruction* GetLastInstruction();
69 HControlInstruction* end() const { return end_; }
70 HLoopInformation* loop_information() const { return loop_information_; }
71 const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; }
72 bool HasPredecessor() const { return predecessors_.length() > 0; }
73 const ZoneList<HBasicBlock*>* dominated_blocks() const {
74 return &dominated_blocks_;
75 }
76 const ZoneList<int>* deleted_phis() const {
77 return &deleted_phis_;
78 }
79 void RecordDeletedPhi(int merge_index) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000080 deleted_phis_.Add(merge_index, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +000081 }
82 HBasicBlock* dominator() const { return dominator_; }
83 HEnvironment* last_environment() const { return last_environment_; }
84 int argument_count() const { return argument_count_; }
85 void set_argument_count(int count) { argument_count_ = count; }
86 int first_instruction_index() const { return first_instruction_index_; }
87 void set_first_instruction_index(int index) {
88 first_instruction_index_ = index;
89 }
90 int last_instruction_index() const { return last_instruction_index_; }
91 void set_last_instruction_index(int index) {
92 last_instruction_index_ = index;
93 }
94
95 void AttachLoopInformation();
96 void DetachLoopInformation();
97 bool IsLoopHeader() const { return loop_information() != NULL; }
98 bool IsStartBlock() const { return block_id() == 0; }
99 void PostProcessLoopHeader(IterationStatement* stmt);
100
101 bool IsFinished() const { return end_ != NULL; }
102 void AddPhi(HPhi* phi);
103 void RemovePhi(HPhi* phi);
104 void AddInstruction(HInstruction* instr);
105 bool Dominates(HBasicBlock* other) const;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000106 int LoopNestingDepth() const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000107
108 void SetInitialEnvironment(HEnvironment* env);
109 void ClearEnvironment() { last_environment_ = NULL; }
110 bool HasEnvironment() const { return last_environment_ != NULL; }
111 void UpdateEnvironment(HEnvironment* env) { last_environment_ = env; }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000112 HBasicBlock* parent_loop_header() const { return parent_loop_header_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000113
114 void set_parent_loop_header(HBasicBlock* block) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000115 ASSERT(parent_loop_header_ == NULL);
116 parent_loop_header_ = block;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000117 }
118
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000119 bool HasParentLoopHeader() const { return parent_loop_header_ != NULL; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000120
ager@chromium.org04921a82011-06-27 13:21:41 +0000121 void SetJoinId(int ast_id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000122
123 void Finish(HControlInstruction* last);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000124 void FinishExit(HControlInstruction* instruction);
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000125 void Goto(HBasicBlock* block, FunctionState* state = NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000126
127 int PredecessorIndexOf(HBasicBlock* predecessor) const;
ager@chromium.org04921a82011-06-27 13:21:41 +0000128 void AddSimulate(int ast_id) { AddInstruction(CreateSimulate(ast_id)); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000129 void AssignCommonDominator(HBasicBlock* other);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000130 void AssignLoopSuccessorDominators();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000131
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000132 void FinishExitWithDeoptimization(HDeoptimize::UseEnvironment has_uses) {
133 FinishExit(CreateDeoptimize(has_uses));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000134 }
135
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000136 // Add the inlined function exit sequence, adding an HLeaveInlined
137 // instruction and updating the bailout environment.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000138 void AddLeaveInlined(HValue* return_value,
139 HBasicBlock* target,
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000140 FunctionState* state = NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000141
142 // If a target block is tagged as an inline function return, all
143 // predecessors should contain the inlined exit sequence:
144 //
145 // LeaveInlined
146 // Simulate (caller's environment)
147 // Goto (target block)
148 bool IsInlineReturnTarget() const { return is_inline_return_target_; }
149 void MarkAsInlineReturnTarget() { is_inline_return_target_ = true; }
150
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000151 bool IsDeoptimizing() const { return is_deoptimizing_; }
152 void MarkAsDeoptimizing() { is_deoptimizing_ = true; }
153
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000154 bool IsLoopSuccessorDominator() const {
155 return dominates_loop_successors_;
156 }
157 void MarkAsLoopSuccessorDominator() {
158 dominates_loop_successors_ = true;
159 }
160
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000161 inline Zone* zone() const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000162
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000163#ifdef DEBUG
164 void Verify();
165#endif
166
167 private:
168 void RegisterPredecessor(HBasicBlock* pred);
169 void AddDominatedBlock(HBasicBlock* block);
170
ager@chromium.org04921a82011-06-27 13:21:41 +0000171 HSimulate* CreateSimulate(int ast_id);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000172 HDeoptimize* CreateDeoptimize(HDeoptimize::UseEnvironment has_uses);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000173
174 int block_id_;
175 HGraph* graph_;
176 ZoneList<HPhi*> phis_;
177 HInstruction* first_;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000178 HInstruction* last_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000179 HControlInstruction* end_;
180 HLoopInformation* loop_information_;
181 ZoneList<HBasicBlock*> predecessors_;
182 HBasicBlock* dominator_;
183 ZoneList<HBasicBlock*> dominated_blocks_;
184 HEnvironment* last_environment_;
185 // Outgoing parameter count at block exit, set during lithium translation.
186 int argument_count_;
187 // Instruction indices into the lithium code stream.
188 int first_instruction_index_;
189 int last_instruction_index_;
190 ZoneList<int> deleted_phis_;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000191 HBasicBlock* parent_loop_header_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000192 bool is_inline_return_target_;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000193 bool is_deoptimizing_;
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000194 bool dominates_loop_successors_;
195};
196
197
198class HPredecessorIterator BASE_EMBEDDED {
199 public:
200 explicit HPredecessorIterator(HBasicBlock* block)
201 : predecessor_list_(block->predecessors()), current_(0) { }
202
203 bool Done() { return current_ >= predecessor_list_->length(); }
204 HBasicBlock* Current() { return predecessor_list_->at(current_); }
205 void Advance() { current_++; }
206
207 private:
208 const ZoneList<HBasicBlock*>* predecessor_list_;
209 int current_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000210};
211
212
213class HLoopInformation: public ZoneObject {
214 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000215 HLoopInformation(HBasicBlock* loop_header, Zone* zone)
216 : back_edges_(4, zone),
ager@chromium.org04921a82011-06-27 13:21:41 +0000217 loop_header_(loop_header),
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000218 blocks_(8, zone),
ager@chromium.org04921a82011-06-27 13:21:41 +0000219 stack_check_(NULL) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000220 blocks_.Add(loop_header, zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000221 }
222 virtual ~HLoopInformation() {}
223
224 const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; }
225 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
226 HBasicBlock* loop_header() const { return loop_header_; }
227 HBasicBlock* GetLastBackEdge() const;
228 void RegisterBackEdge(HBasicBlock* block);
229
ager@chromium.org04921a82011-06-27 13:21:41 +0000230 HStackCheck* stack_check() const { return stack_check_; }
231 void set_stack_check(HStackCheck* stack_check) {
232 stack_check_ = stack_check;
233 }
234
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000235 private:
236 void AddBlock(HBasicBlock* block);
237
238 ZoneList<HBasicBlock*> back_edges_;
239 HBasicBlock* loop_header_;
240 ZoneList<HBasicBlock*> blocks_;
ager@chromium.org04921a82011-06-27 13:21:41 +0000241 HStackCheck* stack_check_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000242};
243
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000244class BoundsCheckTable;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000245class HGraph: public ZoneObject {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000246 public:
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000247 explicit HGraph(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000248
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000249 Isolate* isolate() { return isolate_; }
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000250 Zone* zone() const { return zone_; }
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000251 CompilationInfo* info() const { return info_; }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000252
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000253 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
254 const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000255 HBasicBlock* entry_block() const { return entry_block_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000256 HEnvironment* start_environment() const { return start_environment_; }
257
258 void InitializeInferredTypes();
259 void InsertTypeConversions();
260 void InsertRepresentationChanges();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000261 void MarkDeoptimizeOnUndefined();
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000262 void ComputeMinusZeroChecks();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000263 bool ProcessArgumentsObject();
264 void EliminateRedundantPhis();
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000265 void EliminateUnreachablePhis();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000266 void Canonicalize();
267 void OrderBlocks();
268 void AssignDominators();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000269 void ReplaceCheckedValues();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000270 void EliminateRedundantBoundsChecks();
ulan@chromium.org0e3f88b2012-05-22 09:16:05 +0000271 void DehoistSimpleArrayIndexComputations();
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000272 void PropagateDeoptimizingMark();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000273
274 // Returns false if there are phi-uses of the arguments-object
275 // which are not supported by the optimizing compiler.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000276 bool CheckArgumentsPhiUses();
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +0000277
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000278 // Returns false if there are phi-uses of an uninitialized const
279 // which are not supported by the optimizing compiler.
280 bool CheckConstPhiUses();
281
282 void CollectPhis();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000283
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000284 Handle<Code> Compile();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000285
286 void set_undefined_constant(HConstant* constant) {
287 undefined_constant_.set(constant);
288 }
289 HConstant* GetConstantUndefined() const { return undefined_constant_.get(); }
290 HConstant* GetConstant1();
291 HConstant* GetConstantMinus1();
292 HConstant* GetConstantTrue();
293 HConstant* GetConstantFalse();
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000294 HConstant* GetConstantHole();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000295
296 HBasicBlock* CreateBasicBlock();
297 HArgumentsObject* GetArgumentsObject() const {
298 return arguments_object_.get();
299 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000300
301 void SetArgumentsObject(HArgumentsObject* object) {
302 arguments_object_.set(object);
303 }
304
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000305 int GetMaximumValueID() const { return values_.length(); }
306 int GetNextBlockID() { return next_block_id_++; }
307 int GetNextValueID(HValue* value) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000308 values_.Add(value, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000309 return values_.length() - 1;
310 }
311 HValue* LookupValue(int id) const {
312 if (id >= 0 && id < values_.length()) return values_[id];
313 return NULL;
314 }
315
316#ifdef DEBUG
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000317 void Verify(bool do_full_verify) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000318#endif
319
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000320 bool has_osr_loop_entry() {
321 return osr_loop_entry_.is_set();
322 }
323
324 HBasicBlock* osr_loop_entry() {
325 return osr_loop_entry_.get();
326 }
327
328 void set_osr_loop_entry(HBasicBlock* entry) {
329 osr_loop_entry_.set(entry);
330 }
331
332 ZoneList<HUnknownOSRValue*>* osr_values() {
333 return osr_values_.get();
334 }
335
336 void set_osr_values(ZoneList<HUnknownOSRValue*>* values) {
337 osr_values_.set(values);
338 }
339
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000340 void MarkRecursive() {
341 is_recursive_ = true;
342 }
343
344 bool is_recursive() const {
345 return is_recursive_;
346 }
347
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000348 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000349 HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
svenpanne@chromium.org619781a2012-07-05 08:22:44 +0000350 Handle<Object> value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000351
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000352 void MarkAsDeoptimizingRecursively(HBasicBlock* block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000353 void InsertTypeConversions(HInstruction* instr);
354 void PropagateMinusZeroChecks(HValue* value, BitVector* visited);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000355 void RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000356 void InsertRepresentationChangeForUse(HValue* value,
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000357 HValue* use_value,
358 int use_index,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000359 Representation to);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000360 void InsertRepresentationChangesForValue(HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000361 void InferTypes(ZoneList<HValue*>* worklist);
362 void InitializeInferredTypes(int from_inclusive, int to_inclusive);
363 void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000364 void EliminateRedundantBoundsChecks(HBasicBlock* bb, BoundsCheckTable* table);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000365
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000366 Isolate* isolate_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000367 int next_block_id_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000368 HBasicBlock* entry_block_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000369 HEnvironment* start_environment_;
370 ZoneList<HBasicBlock*> blocks_;
371 ZoneList<HValue*> values_;
372 ZoneList<HPhi*>* phi_list_;
373 SetOncePointer<HConstant> undefined_constant_;
374 SetOncePointer<HConstant> constant_1_;
375 SetOncePointer<HConstant> constant_minus1_;
376 SetOncePointer<HConstant> constant_true_;
377 SetOncePointer<HConstant> constant_false_;
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000378 SetOncePointer<HConstant> constant_hole_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000379 SetOncePointer<HArgumentsObject> arguments_object_;
380
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000381 SetOncePointer<HBasicBlock> osr_loop_entry_;
382 SetOncePointer<ZoneList<HUnknownOSRValue*> > osr_values_;
383
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000384 CompilationInfo* info_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000385 Zone* zone_;
386
387 bool is_recursive_;
388
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000389 DISALLOW_COPY_AND_ASSIGN(HGraph);
390};
391
392
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000393Zone* HBasicBlock::zone() const { return graph_->zone(); }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000394
395
ulan@chromium.org967e2702012-02-28 09:49:15 +0000396// Type of stack frame an environment might refer to.
397enum FrameType { JS_FUNCTION, JS_CONSTRUCT, ARGUMENTS_ADAPTOR };
398
399
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000400class HEnvironment: public ZoneObject {
401 public:
402 HEnvironment(HEnvironment* outer,
403 Scope* scope,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000404 Handle<JSFunction> closure,
405 Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000406
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000407 HEnvironment* DiscardInlined(bool drop_extra) {
ulan@chromium.org967e2702012-02-28 09:49:15 +0000408 HEnvironment* outer = outer_;
409 while (outer->frame_type() != JS_FUNCTION) outer = outer->outer_;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000410 if (drop_extra) outer->Drop(1);
411 return outer;
412 }
413
ulan@chromium.org6ff65142012-03-21 09:52:17 +0000414 HEnvironment* arguments_environment() {
415 return outer()->frame_type() == ARGUMENTS_ADAPTOR ? outer() : this;
416 }
417
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000418 // Simple accessors.
419 Handle<JSFunction> closure() const { return closure_; }
420 const ZoneList<HValue*>* values() const { return &values_; }
421 const ZoneList<int>* assigned_variables() const {
422 return &assigned_variables_;
423 }
ulan@chromium.org967e2702012-02-28 09:49:15 +0000424 FrameType frame_type() const { return frame_type_; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000425 int parameter_count() const { return parameter_count_; }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000426 int specials_count() const { return specials_count_; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000427 int local_count() const { return local_count_; }
428 HEnvironment* outer() const { return outer_; }
429 int pop_count() const { return pop_count_; }
430 int push_count() const { return push_count_; }
431
432 int ast_id() const { return ast_id_; }
433 void set_ast_id(int id) { ast_id_ = id; }
434
435 int length() const { return values_.length(); }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000436 bool is_special_index(int i) const {
437 return i >= parameter_count() && i < parameter_count() + specials_count();
438 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000439
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000440 int first_expression_index() const {
441 return parameter_count() + specials_count() + local_count();
442 }
443
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000444 void Bind(Variable* variable, HValue* value) {
445 Bind(IndexFor(variable), value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000446 }
447
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000448 void Bind(int index, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000449
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000450 void BindContext(HValue* value) {
451 Bind(parameter_count(), value);
452 }
453
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000454 HValue* Lookup(Variable* variable) const {
455 return Lookup(IndexFor(variable));
456 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000457
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000458 HValue* Lookup(int index) const {
459 HValue* result = values_[index];
460 ASSERT(result != NULL);
461 return result;
462 }
463
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000464 HValue* LookupContext() const {
465 // Return first special.
466 return Lookup(parameter_count());
467 }
468
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000469 void Push(HValue* value) {
470 ASSERT(value != NULL);
471 ++push_count_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000472 values_.Add(value, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000473 }
474
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000475 HValue* Pop() {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000476 ASSERT(!ExpressionStackIsEmpty());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000477 if (push_count_ > 0) {
478 --push_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000479 } else {
480 ++pop_count_;
481 }
482 return values_.RemoveLast();
483 }
484
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000485 void Drop(int count);
486
487 HValue* Top() const { return ExpressionStackAt(0); }
488
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000489 bool ExpressionStackIsEmpty() const;
490
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000491 HValue* ExpressionStackAt(int index_from_top) const {
492 int index = length() - index_from_top - 1;
493 ASSERT(HasExpressionAt(index));
494 return values_[index];
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000495 }
496
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000497 void SetExpressionStackAt(int index_from_top, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000498
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000499 HEnvironment* Copy() const;
500 HEnvironment* CopyWithoutHistory() const;
501 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const;
502
503 // Create an "inlined version" of this environment, where the original
504 // environment is the outer environment but the top expression stack
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000505 // elements are moved to an inner environment as parameters.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000506 HEnvironment* CopyForInlining(Handle<JSFunction> target,
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000507 int arguments,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000508 FunctionLiteral* function,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000509 HConstant* undefined,
ulan@chromium.org967e2702012-02-28 09:49:15 +0000510 CallKind call_kind,
511 bool is_construct) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000512
513 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000514
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000515 void ClearHistory() {
516 pop_count_ = 0;
517 push_count_ = 0;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000518 assigned_variables_.Rewind(0);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000519 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000520
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000521 void SetValueAt(int index, HValue* value) {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000522 ASSERT(index < length());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000523 values_[index] = value;
524 }
525
526 void PrintTo(StringStream* stream);
527 void PrintToStd();
528
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000529 Zone* zone() const { return zone_; }
530
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000531 private:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000532 HEnvironment(const HEnvironment* other, Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000533
ulan@chromium.org967e2702012-02-28 09:49:15 +0000534 HEnvironment(HEnvironment* outer,
535 Handle<JSFunction> closure,
536 FrameType frame_type,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000537 int arguments,
538 Zone* zone);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000539
ulan@chromium.org967e2702012-02-28 09:49:15 +0000540 // Create an artificial stub environment (e.g. for argument adaptor or
541 // constructor stub).
542 HEnvironment* CreateStubEnvironment(HEnvironment* outer,
543 Handle<JSFunction> target,
544 FrameType frame_type,
545 int arguments) const;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000546
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000547 // True if index is included in the expression stack part of the environment.
548 bool HasExpressionAt(int index) const;
549
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000550 void Initialize(int parameter_count, int local_count, int stack_height);
551 void Initialize(const HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000552
553 // Map a variable to an environment index. Parameter indices are shifted
554 // by 1 (receiver is parameter index -1 but environment index 0).
555 // Stack-allocated local indices are shifted by the number of parameters.
556 int IndexFor(Variable* variable) const {
jkummerow@chromium.org486075a2011-09-07 12:44:28 +0000557 ASSERT(variable->IsStackAllocated());
558 int shift = variable->IsParameter()
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000559 ? 1
560 : parameter_count_ + specials_count_;
jkummerow@chromium.org486075a2011-09-07 12:44:28 +0000561 return variable->index() + shift;
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000562 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000563
564 Handle<JSFunction> closure_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000565 // Value array [parameters] [specials] [locals] [temporaries].
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000566 ZoneList<HValue*> values_;
567 ZoneList<int> assigned_variables_;
ulan@chromium.org967e2702012-02-28 09:49:15 +0000568 FrameType frame_type_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000569 int parameter_count_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000570 int specials_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000571 int local_count_;
572 HEnvironment* outer_;
573 int pop_count_;
574 int push_count_;
575 int ast_id_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000576 Zone* zone_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000577};
578
579
580class HGraphBuilder;
581
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000582enum ArgumentsAllowedFlag {
583 ARGUMENTS_NOT_ALLOWED,
584 ARGUMENTS_ALLOWED
585};
586
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000587// This class is not BASE_EMBEDDED because our inlining implementation uses
588// new and delete.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000589class AstContext {
590 public:
591 bool IsEffect() const { return kind_ == Expression::kEffect; }
592 bool IsValue() const { return kind_ == Expression::kValue; }
593 bool IsTest() const { return kind_ == Expression::kTest; }
594
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000595 // 'Fill' this context with a hydrogen value. The value is assumed to
596 // have already been inserted in the instruction stream (or not need to
597 // be, e.g., HPhi). Call this function in tail position in the Visit
598 // functions for expressions.
599 virtual void ReturnValue(HValue* value) = 0;
600
601 // Add a hydrogen instruction to the instruction stream (recording an
602 // environment simulation if necessary) and then fill this context with
603 // the instruction as value.
604 virtual void ReturnInstruction(HInstruction* instr, int ast_id) = 0;
605
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000606 // Finishes the current basic block and materialize a boolean for
607 // value context, nothing for effect, generate a branch for test context.
608 // Call this function in tail position in the Visit functions for
609 // expressions.
610 virtual void ReturnControl(HControlInstruction* instr, int ast_id) = 0;
611
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000612 void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; }
613 bool is_for_typeof() { return for_typeof_; }
614
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000615 protected:
616 AstContext(HGraphBuilder* owner, Expression::Context kind);
617 virtual ~AstContext();
618
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000619 HGraphBuilder* owner() const { return owner_; }
620
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000621 inline Zone* zone() const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000622
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000623 // We want to be able to assert, in a context-specific way, that the stack
624 // height makes sense when the context is filled.
625#ifdef DEBUG
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000626 int original_length_;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000627#endif
628
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000629 private:
630 HGraphBuilder* owner_;
631 Expression::Context kind_;
632 AstContext* outer_;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000633 bool for_typeof_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000634};
635
636
637class EffectContext: public AstContext {
638 public:
639 explicit EffectContext(HGraphBuilder* owner)
640 : AstContext(owner, Expression::kEffect) {
641 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000642 virtual ~EffectContext();
643
644 virtual void ReturnValue(HValue* value);
645 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000646 virtual void ReturnControl(HControlInstruction* instr, int ast_id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000647};
648
649
650class ValueContext: public AstContext {
651 public:
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000652 explicit ValueContext(HGraphBuilder* owner, ArgumentsAllowedFlag flag)
653 : AstContext(owner, Expression::kValue), flag_(flag) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000654 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000655 virtual ~ValueContext();
656
657 virtual void ReturnValue(HValue* value);
658 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000659 virtual void ReturnControl(HControlInstruction* instr, int ast_id);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000660
661 bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
662
663 private:
664 ArgumentsAllowedFlag flag_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000665};
666
667
668class TestContext: public AstContext {
669 public:
670 TestContext(HGraphBuilder* owner,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000671 Expression* condition,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000672 HBasicBlock* if_true,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000673 HBasicBlock* if_false)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000674 : AstContext(owner, Expression::kTest),
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000675 condition_(condition),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000676 if_true_(if_true),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000677 if_false_(if_false) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000678 }
679
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000680 virtual void ReturnValue(HValue* value);
681 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000682 virtual void ReturnControl(HControlInstruction* instr, int ast_id);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000683
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000684 static TestContext* cast(AstContext* context) {
685 ASSERT(context->IsTest());
686 return reinterpret_cast<TestContext*>(context);
687 }
688
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000689 Expression* condition() const { return condition_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000690 HBasicBlock* if_true() const { return if_true_; }
691 HBasicBlock* if_false() const { return if_false_; }
692
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000693 private:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000694 // Build the shared core part of the translation unpacking a value into
695 // control flow.
696 void BuildBranch(HValue* value);
697
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000698 Expression* condition_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000699 HBasicBlock* if_true_;
700 HBasicBlock* if_false_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000701};
702
703
ulan@chromium.org967e2702012-02-28 09:49:15 +0000704enum ReturnHandlingFlag {
705 NORMAL_RETURN,
706 DROP_EXTRA_ON_RETURN,
707 CONSTRUCT_CALL_RETURN
708};
709
710
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000711class FunctionState {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000712 public:
713 FunctionState(HGraphBuilder* owner,
714 CompilationInfo* info,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000715 TypeFeedbackOracle* oracle,
ulan@chromium.org967e2702012-02-28 09:49:15 +0000716 ReturnHandlingFlag return_handling);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000717 ~FunctionState();
718
719 CompilationInfo* compilation_info() { return compilation_info_; }
720 TypeFeedbackOracle* oracle() { return oracle_; }
721 AstContext* call_context() { return call_context_; }
ulan@chromium.org967e2702012-02-28 09:49:15 +0000722 bool drop_extra() { return return_handling_ == DROP_EXTRA_ON_RETURN; }
723 bool is_construct() { return return_handling_ == CONSTRUCT_CALL_RETURN; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000724 HBasicBlock* function_return() { return function_return_; }
725 TestContext* test_context() { return test_context_; }
726 void ClearInlinedTestContext() {
727 delete test_context_;
728 test_context_ = NULL;
729 }
730
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000731 FunctionState* outer() { return outer_; }
732
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000733 HEnterInlined* entry() { return entry_; }
734 void set_entry(HEnterInlined* entry) { entry_ = entry; }
735
736 HArgumentsElements* arguments_elements() { return arguments_elements_; }
737 void set_arguments_elements(HArgumentsElements* arguments_elements) {
738 arguments_elements_ = arguments_elements;
739 }
740
741 bool arguments_pushed() { return arguments_elements() != NULL; }
742
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000743 private:
744 HGraphBuilder* owner_;
745
746 CompilationInfo* compilation_info_;
747 TypeFeedbackOracle* oracle_;
748
749 // During function inlining, expression context of the call being
750 // inlined. NULL when not inlining.
751 AstContext* call_context_;
752
ulan@chromium.org967e2702012-02-28 09:49:15 +0000753 // Indicate whether we have to perform special handling on return from
754 // inlined functions.
755 // - DROP_EXTRA_ON_RETURN: Drop an extra value from the environment.
756 // - CONSTRUCT_CALL_RETURN: Either use allocated receiver or return value.
757 ReturnHandlingFlag return_handling_;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000758
ulan@chromium.org967e2702012-02-28 09:49:15 +0000759 // When inlining in an effect or value context, this is the return block.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000760 // It is NULL otherwise. When inlining in a test context, there are a
761 // pair of return blocks in the context. When not inlining, there is no
762 // local return point.
763 HBasicBlock* function_return_;
764
765 // When inlining a call in a test context, a context containing a pair of
766 // return blocks. NULL in all other cases.
767 TestContext* test_context_;
768
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000769 // When inlining HEnterInlined instruction corresponding to the function
770 // entry.
771 HEnterInlined* entry_;
772
773 HArgumentsElements* arguments_elements_;
774
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000775 FunctionState* outer_;
776};
777
778
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000779class HGraphBuilder: public AstVisitor {
780 public:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000781 enum BreakType { BREAK, CONTINUE };
erikcorry0ad885c2011-11-21 13:51:57 +0000782 enum SwitchType { UNKNOWN_SWITCH, SMI_SWITCH, STRING_SWITCH };
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000783
784 // A class encapsulating (lazily-allocated) break and continue blocks for
785 // a breakable statement. Separated from BreakAndContinueScope so that it
786 // can have a separate lifetime.
787 class BreakAndContinueInfo BASE_EMBEDDED {
788 public:
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000789 explicit BreakAndContinueInfo(BreakableStatement* target,
790 int drop_extra = 0)
791 : target_(target),
792 break_block_(NULL),
793 continue_block_(NULL),
794 drop_extra_(drop_extra) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000795 }
796
797 BreakableStatement* target() { return target_; }
798 HBasicBlock* break_block() { return break_block_; }
799 void set_break_block(HBasicBlock* block) { break_block_ = block; }
800 HBasicBlock* continue_block() { return continue_block_; }
801 void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000802 int drop_extra() { return drop_extra_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000803
804 private:
805 BreakableStatement* target_;
806 HBasicBlock* break_block_;
807 HBasicBlock* continue_block_;
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000808 int drop_extra_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000809 };
810
811 // A helper class to maintain a stack of current BreakAndContinueInfo
812 // structures mirroring BreakableStatement nesting.
813 class BreakAndContinueScope BASE_EMBEDDED {
814 public:
815 BreakAndContinueScope(BreakAndContinueInfo* info, HGraphBuilder* owner)
816 : info_(info), owner_(owner), next_(owner->break_scope()) {
817 owner->set_break_scope(this);
818 }
819
820 ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
821
822 BreakAndContinueInfo* info() { return info_; }
823 HGraphBuilder* owner() { return owner_; }
824 BreakAndContinueScope* next() { return next_; }
825
826 // Search the break stack for a break or continue target.
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000827 HBasicBlock* Get(BreakableStatement* stmt, BreakType type, int* drop_extra);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000828
829 private:
830 BreakAndContinueInfo* info_;
831 HGraphBuilder* owner_;
832 BreakAndContinueScope* next_;
833 };
834
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000835 HGraphBuilder(CompilationInfo* info, TypeFeedbackOracle* oracle);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000836
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000837 HGraph* CreateGraph();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000838
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000839 // Simple accessors.
840 HGraph* graph() const { return graph_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000841 BreakAndContinueScope* break_scope() const { return break_scope_; }
842 void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000843
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000844 HBasicBlock* current_block() const { return current_block_; }
845 void set_current_block(HBasicBlock* block) { current_block_ = block; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000846 HEnvironment* environment() const {
847 return current_block()->last_environment();
848 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000849
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000850 bool inline_bailout() { return inline_bailout_; }
851
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000852 // Adding instructions.
853 HInstruction* AddInstruction(HInstruction* instr);
ager@chromium.org04921a82011-06-27 13:21:41 +0000854 void AddSimulate(int ast_id);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000855
856 // Bailout environment manipulation.
857 void Push(HValue* value) { environment()->Push(value); }
858 HValue* Pop() { return environment()->Pop(); }
859
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000860 void Bailout(const char* reason);
861
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000862 HBasicBlock* CreateJoin(HBasicBlock* first,
863 HBasicBlock* second,
864 int join_id);
865
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000866 TypeFeedbackOracle* oracle() const { return function_state()->oracle(); }
867
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000868 FunctionState* function_state() const { return function_state_; }
869
yangguo@chromium.org56454712012-02-16 15:33:53 +0000870 void VisitDeclarations(ZoneList<Declaration*>* declarations);
871
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000872 private:
873 // Type of a member function that generates inline code for a native function.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000874 typedef void (HGraphBuilder::*InlineFunctionGenerator)(CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000875
876 // Forward declarations for inner scope classes.
877 class SubgraphScope;
878
879 static const InlineFunctionGenerator kInlineFunctionGenerators[];
880
881 static const int kMaxCallPolymorphism = 4;
882 static const int kMaxLoadPolymorphism = 4;
883 static const int kMaxStorePolymorphism = 4;
884
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000885 // Even in the 'unlimited' case we have to have some limit in order not to
886 // overflow the stack.
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +0000887 static const int kUnlimitedMaxInlinedSourceSize = 100000;
888 static const int kUnlimitedMaxInlinedNodes = 10000;
889 static const int kUnlimitedMaxInlinedNodesCumulative = 10000;
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000890
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000891 // Simple accessors.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000892 void set_function_state(FunctionState* state) { function_state_ = state; }
893
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000894 AstContext* ast_context() const { return ast_context_; }
895 void set_ast_context(AstContext* context) { ast_context_ = context; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000896
897 // Accessors forwarded to the function state.
898 CompilationInfo* info() const {
899 return function_state()->compilation_info();
900 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000901 AstContext* call_context() const {
902 return function_state()->call_context();
903 }
904 HBasicBlock* function_return() const {
905 return function_state()->function_return();
906 }
907 TestContext* inlined_test_context() const {
908 return function_state()->test_context();
909 }
910 void ClearInlinedTestContext() {
911 function_state()->ClearInlinedTestContext();
912 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000913 StrictModeFlag function_strict_mode_flag() {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000914 return function_state()->compilation_info()->is_classic_mode()
915 ? kNonStrictMode : kStrictMode;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000916 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000917
918 // Generators for inline runtime functions.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000919#define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000920 void Generate##Name(CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000921
922 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
923 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
924#undef INLINE_FUNCTION_GENERATOR_DECLARATION
925
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000926 void VisitDelete(UnaryOperation* expr);
927 void VisitVoid(UnaryOperation* expr);
928 void VisitTypeof(UnaryOperation* expr);
929 void VisitAdd(UnaryOperation* expr);
930 void VisitSub(UnaryOperation* expr);
931 void VisitBitNot(UnaryOperation* expr);
932 void VisitNot(UnaryOperation* expr);
933
934 void VisitComma(BinaryOperation* expr);
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000935 void VisitLogicalExpression(BinaryOperation* expr);
936 void VisitArithmeticExpression(BinaryOperation* expr);
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000937
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000938 bool PreProcessOsrEntry(IterationStatement* statement);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000939 // True iff. we are compiling for OSR and the statement is the entry.
940 bool HasOsrEntryAt(IterationStatement* statement);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000941 void VisitLoopBody(IterationStatement* stmt,
ager@chromium.org04921a82011-06-27 13:21:41 +0000942 HBasicBlock* loop_entry,
943 BreakAndContinueInfo* break_info);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000944
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000945 // Create a back edge in the flow graph. body_exit is the predecessor
946 // block and loop_entry is the successor block. loop_successor is the
947 // block where control flow exits the loop normally (e.g., via failure of
948 // the condition) and break_block is the block where control flow breaks
949 // from the loop. All blocks except loop_entry can be NULL. The return
950 // value is the new successor block which is the join of loop_successor
951 // and break_block, or NULL.
952 HBasicBlock* CreateLoop(IterationStatement* statement,
953 HBasicBlock* loop_entry,
954 HBasicBlock* body_exit,
955 HBasicBlock* loop_successor,
956 HBasicBlock* break_block);
957
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000958 HBasicBlock* JoinContinue(IterationStatement* statement,
959 HBasicBlock* exit_block,
960 HBasicBlock* continue_block);
961
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000962 HValue* Top() const { return environment()->Top(); }
963 void Drop(int n) { environment()->Drop(n); }
964 void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
965
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000966 // The value of the arguments object is allowed in some but not most value
967 // contexts. (It's allowed in all effect contexts and disallowed in all
968 // test contexts.)
969 void VisitForValue(Expression* expr,
970 ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000971 void VisitForTypeOf(Expression* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000972 void VisitForEffect(Expression* expr);
973 void VisitForControl(Expression* expr,
974 HBasicBlock* true_block,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000975 HBasicBlock* false_block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000976
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000977 // Visit an argument subexpression and emit a push to the outgoing
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000978 // arguments. Returns the hydrogen value that was pushed.
979 HValue* VisitArgument(Expression* expr);
980
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000981 void VisitArgumentList(ZoneList<Expression*>* arguments);
982
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000983 // Visit a list of expressions from left to right, each in a value context.
984 void VisitExpressions(ZoneList<Expression*>* exprs);
985
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000986 void AddPhi(HPhi* phi);
987
988 void PushAndAdd(HInstruction* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000989
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000990 // Remove the arguments from the bailout environment and emit instructions
991 // to push them as outgoing parameters.
ulan@chromium.org967e2702012-02-28 09:49:15 +0000992 template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000993
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000994 void TraceRepresentation(Token::Value op,
995 TypeInfo info,
996 HValue* value,
997 Representation rep);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000998 static Representation ToRepresentation(TypeInfo info);
999
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001000 void SetUpScope(Scope* scope);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001001 virtual void VisitStatements(ZoneList<Statement*>* statements);
1002
1003#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
1004 AST_NODE_LIST(DECLARE_VISIT)
1005#undef DECLARE_VISIT
1006
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001007 HBasicBlock* CreateBasicBlock(HEnvironment* env);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001008 HBasicBlock* CreateLoopHeaderBlock();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001009
1010 // Helpers for flow graph construction.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001011 enum GlobalPropertyAccess {
1012 kUseCell,
1013 kUseGeneric
1014 };
1015 GlobalPropertyAccess LookupGlobalProperty(Variable* var,
1016 LookupResult* lookup,
1017 bool is_store);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001018
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001019 void EnsureArgumentsArePushedForAccess();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001020 bool TryArgumentsAccess(Property* expr);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001021
1022 // Try to optimize fun.apply(receiver, arguments) pattern.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001023 bool TryCallApply(Call* expr);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001024
jkummerow@chromium.org212d9642012-05-11 15:02:09 +00001025 int InliningAstSize(Handle<JSFunction> target);
ulan@chromium.org967e2702012-02-28 09:49:15 +00001026 bool TryInline(CallKind call_kind,
1027 Handle<JSFunction> target,
1028 ZoneList<Expression*>* arguments,
1029 HValue* receiver,
1030 int ast_id,
1031 int return_id,
1032 ReturnHandlingFlag return_handling);
1033
1034 bool TryInlineCall(Call* expr, bool drop_extra = false);
1035 bool TryInlineConstruct(CallNew* expr, HValue* receiver);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001036 bool TryInlineBuiltinMethodCall(Call* expr,
ulan@chromium.org967e2702012-02-28 09:49:15 +00001037 HValue* receiver,
1038 Handle<Map> receiver_map,
1039 CheckType check_type);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001040 bool TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001041
1042 // If --trace-inlining, print a line of the inlining trace. Inlining
1043 // succeeded if the reason string is NULL and failed if there is a
1044 // non-NULL reason string.
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001045 void TraceInline(Handle<JSFunction> target,
1046 Handle<JSFunction> caller,
1047 const char* failure_reason);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001048
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001049 void HandleGlobalVariableAssignment(Variable* var,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001050 HValue* value,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001051 int position,
1052 int ast_id);
1053
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001054 void HandlePropertyAssignment(Assignment* expr);
1055 void HandleCompoundAssignment(Assignment* expr);
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001056 void HandlePolymorphicLoadNamedField(Property* expr,
1057 HValue* object,
1058 SmallMapList* types,
1059 Handle<String> name);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001060 void HandlePolymorphicStoreNamedField(Assignment* expr,
1061 HValue* object,
1062 HValue* value,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001063 SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001064 Handle<String> name);
1065 void HandlePolymorphicCallNamed(Call* expr,
1066 HValue* receiver,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001067 SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001068 Handle<String> name);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001069 void HandleLiteralCompareTypeof(CompareOperation* expr,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001070 HTypeof* typeof_expr,
ager@chromium.org04921a82011-06-27 13:21:41 +00001071 Handle<String> check);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001072 void HandleLiteralCompareNil(CompareOperation* expr,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001073 HValue* value,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001074 NilValue nil);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001075
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001076 HStringCharCodeAt* BuildStringCharCodeAt(HValue* context,
1077 HValue* string,
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001078 HValue* index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001079 HInstruction* BuildBinaryOperation(BinaryOperation* expr,
1080 HValue* left,
1081 HValue* right);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001082 HInstruction* BuildIncrement(bool returns_original_input,
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001083 CountOperation* expr);
whesse@chromium.org023421e2010-12-21 12:19:12 +00001084 HLoadNamedField* BuildLoadNamedField(HValue* object,
1085 Property* expr,
1086 Handle<Map> type,
1087 LookupResult* result,
1088 bool smi_and_map_check);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001089 HInstruction* BuildLoadNamedGeneric(HValue* object, Property* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001090 HInstruction* BuildLoadKeyedGeneric(HValue* object,
1091 HValue* key);
whesse@chromium.org7b260152011-06-20 15:33:18 +00001092 HInstruction* BuildExternalArrayElementAccess(
1093 HValue* external_elements,
1094 HValue* checked_key,
1095 HValue* val,
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001096 ElementsKind elements_kind,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001097 bool is_store);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001098 HInstruction* BuildFastElementAccess(HValue* elements,
1099 HValue* checked_key,
1100 HValue* val,
1101 ElementsKind elements_kind,
1102 bool is_store);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001103
mstarzinger@chromium.orgc6d9cee2012-07-03 10:03:19 +00001104 HInstruction* TryBuildConsolidatedElementLoad(HValue* object,
1105 HValue* key,
1106 HValue* val,
1107 SmallMapList* maps);
1108
1109 HInstruction* BuildUncheckedMonomorphicElementAccess(HValue* object,
1110 HValue* key,
1111 HValue* val,
1112 HCheckMaps* mapcheck,
1113 Handle<Map> map,
1114 bool is_store);
1115
whesse@chromium.org7b260152011-06-20 15:33:18 +00001116 HInstruction* BuildMonomorphicElementAccess(HValue* object,
1117 HValue* key,
1118 HValue* val,
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00001119 HValue* dependency,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001120 Handle<Map> map,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001121 bool is_store);
mstarzinger@chromium.orgc6d9cee2012-07-03 10:03:19 +00001122
whesse@chromium.org7b260152011-06-20 15:33:18 +00001123 HValue* HandlePolymorphicElementAccess(HValue* object,
1124 HValue* key,
1125 HValue* val,
1126 Expression* prop,
1127 int ast_id,
1128 int position,
1129 bool is_store,
1130 bool* has_side_effects);
1131
1132 HValue* HandleKeyedElementAccess(HValue* obj,
1133 HValue* key,
1134 HValue* val,
1135 Expression* expr,
1136 int ast_id,
1137 int position,
1138 bool is_store,
1139 bool* has_side_effects);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001140
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001141 HInstruction* BuildLoadNamed(HValue* object,
1142 Property* prop,
1143 Handle<Map> map,
1144 Handle<String> name);
1145 HInstruction* BuildStoreNamed(HValue* object,
1146 HValue* value,
1147 Expression* expr);
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +00001148 HInstruction* BuildStoreNamed(HValue* object,
1149 HValue* value,
1150 ObjectLiteral::Property* prop);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001151 HInstruction* BuildStoreNamedField(HValue* object,
1152 Handle<String> name,
1153 HValue* value,
1154 Handle<Map> type,
1155 LookupResult* lookup,
1156 bool smi_and_map_check);
1157 HInstruction* BuildStoreNamedGeneric(HValue* object,
1158 Handle<String> name,
1159 HValue* value);
1160 HInstruction* BuildStoreKeyedGeneric(HValue* object,
1161 HValue* key,
1162 HValue* value);
1163
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001164 HValue* BuildContextChainWalk(Variable* var);
1165
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001166 HInstruction* BuildThisFunction();
1167
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001168 void AddCheckConstantFunction(Call* expr,
1169 HValue* receiver,
1170 Handle<Map> receiver_map,
1171 bool smi_and_map_check);
1172
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001173 Zone* zone() const { return zone_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001174
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001175 // The translation state of the currently-being-translated function.
1176 FunctionState* function_state_;
1177
1178 // The base of the function state stack.
1179 FunctionState initial_function_state_;
1180
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001181 // Expression context of the currently visited subexpression. NULL when
1182 // visiting statements.
1183 AstContext* ast_context_;
1184
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001185 // A stack of breakable statements entered.
1186 BreakAndContinueScope* break_scope_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001187
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001188 HGraph* graph_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001189 HBasicBlock* current_block_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001190
1191 int inlined_count_;
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001192 ZoneList<Handle<Object> > globals_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001193
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001194 Zone* zone_;
1195
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001196 bool inline_bailout_;
1197
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001198 friend class FunctionState; // Pushes and pops the state stack.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001199 friend class AstContext; // Pushes and pops the AST context stack.
1200
1201 DISALLOW_COPY_AND_ASSIGN(HGraphBuilder);
1202};
1203
1204
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001205Zone* AstContext::zone() const { return owner_->zone(); }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001206
1207
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001208class HValueMap: public ZoneObject {
1209 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001210 explicit HValueMap(Zone* zone)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001211 : array_size_(0),
1212 lists_size_(0),
1213 count_(0),
1214 present_flags_(0),
1215 array_(NULL),
1216 lists_(NULL),
1217 free_list_head_(kNil) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001218 ResizeLists(kInitialSize, zone);
1219 Resize(kInitialSize, zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001220 }
1221
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001222 void Kill(GVNFlagSet flags);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001223
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001224 void Add(HValue* value, Zone* zone) {
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001225 present_flags_.Add(value->gvn_flags());
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001226 Insert(value, zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001227 }
1228
1229 HValue* Lookup(HValue* value) const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001230
1231 HValueMap* Copy(Zone* zone) const {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001232 return new(zone) HValueMap(zone, this);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001233 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001234
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001235 bool IsEmpty() const { return count_ == 0; }
1236
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001237 private:
1238 // A linked list of HValue* values. Stored in arrays.
1239 struct HValueMapListElement {
1240 HValue* value;
1241 int next; // Index in the array of the next list element.
1242 };
1243 static const int kNil = -1; // The end of a linked list
1244
1245 // Must be a power of 2.
1246 static const int kInitialSize = 16;
1247
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001248 HValueMap(Zone* zone, const HValueMap* other);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001249
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001250 void Resize(int new_size, Zone* zone);
1251 void ResizeLists(int new_size, Zone* zone);
1252 void Insert(HValue* value, Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001253 uint32_t Bound(uint32_t value) const { return value & (array_size_ - 1); }
1254
1255 int array_size_;
1256 int lists_size_;
1257 int count_; // The number of values stored in the HValueMap.
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001258 GVNFlagSet present_flags_; // All flags that are in any value in the
1259 // HValueMap.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001260 HValueMapListElement* array_; // Primary store - contains the first value
1261 // with a given hash. Colliding elements are stored in linked lists.
1262 HValueMapListElement* lists_; // The linked lists containing hash collisions.
1263 int free_list_head_; // Unused elements in lists_ are on the free list.
1264};
1265
1266
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001267class HSideEffectMap BASE_EMBEDDED {
1268 public:
1269 HSideEffectMap();
1270 explicit HSideEffectMap(HSideEffectMap* other);
rossberg@chromium.org400388e2012-06-06 09:29:22 +00001271 HSideEffectMap& operator= (const HSideEffectMap& other);
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001272
1273 void Kill(GVNFlagSet flags);
1274
1275 void Store(GVNFlagSet flags, HInstruction* instr);
1276
1277 bool IsEmpty() const { return count_ == 0; }
1278
1279 inline HInstruction* operator[](int i) const {
1280 ASSERT(0 <= i);
1281 ASSERT(i < kNumberOfTrackedSideEffects);
1282 return data_[i];
1283 }
1284 inline HInstruction* at(int i) const { return operator[](i); }
1285
1286 private:
1287 int count_;
1288 HInstruction* data_[kNumberOfTrackedSideEffects];
1289};
1290
1291
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001292class HStatistics: public Malloced {
1293 public:
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001294 void Initialize(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001295 void Print();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001296 void SaveTiming(const char* name, int64_t ticks, unsigned size);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001297 static HStatistics* Instance() {
1298 static SetOncePointer<HStatistics> instance;
1299 if (!instance.is_set()) {
1300 instance.set(new HStatistics());
1301 }
1302 return instance.get();
1303 }
1304
1305 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001306 HStatistics()
1307 : timing_(5),
1308 names_(5),
1309 sizes_(5),
1310 total_(0),
1311 total_size_(0),
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001312 full_code_gen_(0),
1313 source_size_(0) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001314
1315 List<int64_t> timing_;
1316 List<const char*> names_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001317 List<unsigned> sizes_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001318 int64_t total_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001319 unsigned total_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001320 int64_t full_code_gen_;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001321 double source_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001322};
1323
1324
1325class HPhase BASE_EMBEDDED {
1326 public:
1327 static const char* const kFullCodeGen;
1328 static const char* const kTotal;
1329
1330 explicit HPhase(const char* name) { Begin(name, NULL, NULL, NULL); }
1331 HPhase(const char* name, HGraph* graph) {
1332 Begin(name, graph, NULL, NULL);
1333 }
1334 HPhase(const char* name, LChunk* chunk) {
1335 Begin(name, NULL, chunk, NULL);
1336 }
1337 HPhase(const char* name, LAllocator* allocator) {
1338 Begin(name, NULL, NULL, allocator);
1339 }
1340
1341 ~HPhase() {
1342 End();
1343 }
1344
1345 private:
1346 void Begin(const char* name,
1347 HGraph* graph,
1348 LChunk* chunk,
1349 LAllocator* allocator);
1350 void End() const;
1351
1352 int64_t start_;
1353 const char* name_;
1354 HGraph* graph_;
1355 LChunk* chunk_;
1356 LAllocator* allocator_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001357 unsigned start_allocation_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001358};
1359
1360
1361class HTracer: public Malloced {
1362 public:
1363 void TraceCompilation(FunctionLiteral* function);
1364 void TraceHydrogen(const char* name, HGraph* graph);
1365 void TraceLithium(const char* name, LChunk* chunk);
1366 void TraceLiveRanges(const char* name, LAllocator* allocator);
1367
1368 static HTracer* Instance() {
1369 static SetOncePointer<HTracer> instance;
1370 if (!instance.is_set()) {
1371 instance.set(new HTracer("hydrogen.cfg"));
1372 }
1373 return instance.get();
1374 }
1375
1376 private:
1377 class Tag BASE_EMBEDDED {
1378 public:
1379 Tag(HTracer* tracer, const char* name) {
1380 name_ = name;
1381 tracer_ = tracer;
1382 tracer->PrintIndent();
1383 tracer->trace_.Add("begin_%s\n", name);
1384 tracer->indent_++;
1385 }
1386
1387 ~Tag() {
1388 tracer_->indent_--;
1389 tracer_->PrintIndent();
1390 tracer_->trace_.Add("end_%s\n", name_);
1391 ASSERT(tracer_->indent_ >= 0);
1392 tracer_->FlushToFile();
1393 }
1394
1395 private:
1396 HTracer* tracer_;
1397 const char* name_;
1398 };
1399
1400 explicit HTracer(const char* filename)
1401 : filename_(filename), trace_(&string_allocator_), indent_(0) {
1402 WriteChars(filename, "", 0, false);
1403 }
1404
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001405 void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001406 void Trace(const char* name, HGraph* graph, LChunk* chunk);
1407 void FlushToFile();
1408
1409 void PrintEmptyProperty(const char* name) {
1410 PrintIndent();
1411 trace_.Add("%s\n", name);
1412 }
1413
1414 void PrintStringProperty(const char* name, const char* value) {
1415 PrintIndent();
1416 trace_.Add("%s \"%s\"\n", name, value);
1417 }
1418
1419 void PrintLongProperty(const char* name, int64_t value) {
1420 PrintIndent();
1421 trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
1422 }
1423
1424 void PrintBlockProperty(const char* name, int block_id) {
1425 PrintIndent();
1426 trace_.Add("%s \"B%d\"\n", name, block_id);
1427 }
1428
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001429 void PrintIntProperty(const char* name, int value) {
1430 PrintIndent();
1431 trace_.Add("%s %d\n", name, value);
1432 }
1433
1434 void PrintIndent() {
1435 for (int i = 0; i < indent_; i++) {
1436 trace_.Add(" ");
1437 }
1438 }
1439
1440 const char* filename_;
1441 HeapStringAllocator string_allocator_;
1442 StringStream trace_;
1443 int indent_;
1444};
1445
1446
1447} } // namespace v8::internal
1448
1449#endif // V8_HYDROGEN_H_