blob: 60a4420024d3ad4019de686e7e880ecd2a6fd28e [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;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000051class LChunk;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000052class 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
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000284 void set_undefined_constant(HConstant* constant) {
285 undefined_constant_.set(constant);
286 }
287 HConstant* GetConstantUndefined() const { return undefined_constant_.get(); }
288 HConstant* GetConstant1();
289 HConstant* GetConstantMinus1();
290 HConstant* GetConstantTrue();
291 HConstant* GetConstantFalse();
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000292 HConstant* GetConstantHole();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000293
294 HBasicBlock* CreateBasicBlock();
295 HArgumentsObject* GetArgumentsObject() const {
296 return arguments_object_.get();
297 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000298
299 void SetArgumentsObject(HArgumentsObject* object) {
300 arguments_object_.set(object);
301 }
302
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000303 int GetMaximumValueID() const { return values_.length(); }
304 int GetNextBlockID() { return next_block_id_++; }
305 int GetNextValueID(HValue* value) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000306 values_.Add(value, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000307 return values_.length() - 1;
308 }
309 HValue* LookupValue(int id) const {
310 if (id >= 0 && id < values_.length()) return values_[id];
311 return NULL;
312 }
313
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000314 bool Optimize(SmartArrayPointer<char>* bailout_reason);
315
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000316#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);
rossberg@chromium.org657d53b2012-07-12 11:06:03 +0000351 HConstant* GetConstantInt32(SetOncePointer<HConstant>* pointer,
352 int32_t integer_value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000353
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000354 void MarkAsDeoptimizingRecursively(HBasicBlock* block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000355 void InsertTypeConversions(HInstruction* instr);
356 void PropagateMinusZeroChecks(HValue* value, BitVector* visited);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000357 void RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000358 void InsertRepresentationChangeForUse(HValue* value,
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000359 HValue* use_value,
360 int use_index,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000361 Representation to);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000362 void InsertRepresentationChangesForValue(HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000363 void InferTypes(ZoneList<HValue*>* worklist);
364 void InitializeInferredTypes(int from_inclusive, int to_inclusive);
365 void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000366 void EliminateRedundantBoundsChecks(HBasicBlock* bb, BoundsCheckTable* table);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000367
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000368 Isolate* isolate_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000369 int next_block_id_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000370 HBasicBlock* entry_block_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000371 HEnvironment* start_environment_;
372 ZoneList<HBasicBlock*> blocks_;
373 ZoneList<HValue*> values_;
374 ZoneList<HPhi*>* phi_list_;
375 SetOncePointer<HConstant> undefined_constant_;
376 SetOncePointer<HConstant> constant_1_;
377 SetOncePointer<HConstant> constant_minus1_;
378 SetOncePointer<HConstant> constant_true_;
379 SetOncePointer<HConstant> constant_false_;
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000380 SetOncePointer<HConstant> constant_hole_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000381 SetOncePointer<HArgumentsObject> arguments_object_;
382
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000383 SetOncePointer<HBasicBlock> osr_loop_entry_;
384 SetOncePointer<ZoneList<HUnknownOSRValue*> > osr_values_;
385
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000386 CompilationInfo* info_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000387 Zone* zone_;
388
389 bool is_recursive_;
390
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000391 DISALLOW_COPY_AND_ASSIGN(HGraph);
392};
393
394
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000395Zone* HBasicBlock::zone() const { return graph_->zone(); }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000396
397
ulan@chromium.org967e2702012-02-28 09:49:15 +0000398// Type of stack frame an environment might refer to.
399enum FrameType { JS_FUNCTION, JS_CONSTRUCT, ARGUMENTS_ADAPTOR };
400
401
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000402class HEnvironment: public ZoneObject {
403 public:
404 HEnvironment(HEnvironment* outer,
405 Scope* scope,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000406 Handle<JSFunction> closure,
407 Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000408
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000409 HEnvironment* DiscardInlined(bool drop_extra) {
ulan@chromium.org967e2702012-02-28 09:49:15 +0000410 HEnvironment* outer = outer_;
411 while (outer->frame_type() != JS_FUNCTION) outer = outer->outer_;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000412 if (drop_extra) outer->Drop(1);
413 return outer;
414 }
415
ulan@chromium.org6ff65142012-03-21 09:52:17 +0000416 HEnvironment* arguments_environment() {
417 return outer()->frame_type() == ARGUMENTS_ADAPTOR ? outer() : this;
418 }
419
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000420 // Simple accessors.
421 Handle<JSFunction> closure() const { return closure_; }
422 const ZoneList<HValue*>* values() const { return &values_; }
423 const ZoneList<int>* assigned_variables() const {
424 return &assigned_variables_;
425 }
ulan@chromium.org967e2702012-02-28 09:49:15 +0000426 FrameType frame_type() const { return frame_type_; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000427 int parameter_count() const { return parameter_count_; }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000428 int specials_count() const { return specials_count_; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000429 int local_count() const { return local_count_; }
430 HEnvironment* outer() const { return outer_; }
431 int pop_count() const { return pop_count_; }
432 int push_count() const { return push_count_; }
433
434 int ast_id() const { return ast_id_; }
435 void set_ast_id(int id) { ast_id_ = id; }
436
437 int length() const { return values_.length(); }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000438 bool is_special_index(int i) const {
439 return i >= parameter_count() && i < parameter_count() + specials_count();
440 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000441
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000442 int first_expression_index() const {
443 return parameter_count() + specials_count() + local_count();
444 }
445
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000446 void Bind(Variable* variable, HValue* value) {
447 Bind(IndexFor(variable), value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000448 }
449
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000450 void Bind(int index, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000451
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000452 void BindContext(HValue* value) {
453 Bind(parameter_count(), value);
454 }
455
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000456 HValue* Lookup(Variable* variable) const {
457 return Lookup(IndexFor(variable));
458 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000459
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000460 HValue* Lookup(int index) const {
461 HValue* result = values_[index];
462 ASSERT(result != NULL);
463 return result;
464 }
465
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000466 HValue* LookupContext() const {
467 // Return first special.
468 return Lookup(parameter_count());
469 }
470
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000471 void Push(HValue* value) {
472 ASSERT(value != NULL);
473 ++push_count_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000474 values_.Add(value, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000475 }
476
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000477 HValue* Pop() {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000478 ASSERT(!ExpressionStackIsEmpty());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000479 if (push_count_ > 0) {
480 --push_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000481 } else {
482 ++pop_count_;
483 }
484 return values_.RemoveLast();
485 }
486
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000487 void Drop(int count);
488
489 HValue* Top() const { return ExpressionStackAt(0); }
490
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000491 bool ExpressionStackIsEmpty() const;
492
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000493 HValue* ExpressionStackAt(int index_from_top) const {
494 int index = length() - index_from_top - 1;
495 ASSERT(HasExpressionAt(index));
496 return values_[index];
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000497 }
498
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000499 void SetExpressionStackAt(int index_from_top, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000500
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000501 HEnvironment* Copy() const;
502 HEnvironment* CopyWithoutHistory() const;
503 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const;
504
505 // Create an "inlined version" of this environment, where the original
506 // environment is the outer environment but the top expression stack
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000507 // elements are moved to an inner environment as parameters.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000508 HEnvironment* CopyForInlining(Handle<JSFunction> target,
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000509 int arguments,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000510 FunctionLiteral* function,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000511 HConstant* undefined,
ulan@chromium.org967e2702012-02-28 09:49:15 +0000512 CallKind call_kind,
513 bool is_construct) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000514
515 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000516
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000517 void ClearHistory() {
518 pop_count_ = 0;
519 push_count_ = 0;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000520 assigned_variables_.Rewind(0);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000521 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000522
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000523 void SetValueAt(int index, HValue* value) {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000524 ASSERT(index < length());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000525 values_[index] = value;
526 }
527
528 void PrintTo(StringStream* stream);
529 void PrintToStd();
530
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000531 Zone* zone() const { return zone_; }
532
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000533 private:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000534 HEnvironment(const HEnvironment* other, Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000535
ulan@chromium.org967e2702012-02-28 09:49:15 +0000536 HEnvironment(HEnvironment* outer,
537 Handle<JSFunction> closure,
538 FrameType frame_type,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000539 int arguments,
540 Zone* zone);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000541
ulan@chromium.org967e2702012-02-28 09:49:15 +0000542 // Create an artificial stub environment (e.g. for argument adaptor or
543 // constructor stub).
544 HEnvironment* CreateStubEnvironment(HEnvironment* outer,
545 Handle<JSFunction> target,
546 FrameType frame_type,
547 int arguments) const;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000548
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000549 // True if index is included in the expression stack part of the environment.
550 bool HasExpressionAt(int index) const;
551
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000552 void Initialize(int parameter_count, int local_count, int stack_height);
553 void Initialize(const HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000554
555 // Map a variable to an environment index. Parameter indices are shifted
556 // by 1 (receiver is parameter index -1 but environment index 0).
557 // Stack-allocated local indices are shifted by the number of parameters.
558 int IndexFor(Variable* variable) const {
jkummerow@chromium.org486075a2011-09-07 12:44:28 +0000559 ASSERT(variable->IsStackAllocated());
560 int shift = variable->IsParameter()
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000561 ? 1
562 : parameter_count_ + specials_count_;
jkummerow@chromium.org486075a2011-09-07 12:44:28 +0000563 return variable->index() + shift;
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000564 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000565
566 Handle<JSFunction> closure_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000567 // Value array [parameters] [specials] [locals] [temporaries].
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000568 ZoneList<HValue*> values_;
569 ZoneList<int> assigned_variables_;
ulan@chromium.org967e2702012-02-28 09:49:15 +0000570 FrameType frame_type_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000571 int parameter_count_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000572 int specials_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000573 int local_count_;
574 HEnvironment* outer_;
575 int pop_count_;
576 int push_count_;
577 int ast_id_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000578 Zone* zone_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000579};
580
581
582class HGraphBuilder;
583
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000584enum ArgumentsAllowedFlag {
585 ARGUMENTS_NOT_ALLOWED,
586 ARGUMENTS_ALLOWED
587};
588
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000589// This class is not BASE_EMBEDDED because our inlining implementation uses
590// new and delete.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000591class AstContext {
592 public:
593 bool IsEffect() const { return kind_ == Expression::kEffect; }
594 bool IsValue() const { return kind_ == Expression::kValue; }
595 bool IsTest() const { return kind_ == Expression::kTest; }
596
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000597 // 'Fill' this context with a hydrogen value. The value is assumed to
598 // have already been inserted in the instruction stream (or not need to
599 // be, e.g., HPhi). Call this function in tail position in the Visit
600 // functions for expressions.
601 virtual void ReturnValue(HValue* value) = 0;
602
603 // Add a hydrogen instruction to the instruction stream (recording an
604 // environment simulation if necessary) and then fill this context with
605 // the instruction as value.
606 virtual void ReturnInstruction(HInstruction* instr, int ast_id) = 0;
607
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000608 // Finishes the current basic block and materialize a boolean for
609 // value context, nothing for effect, generate a branch for test context.
610 // Call this function in tail position in the Visit functions for
611 // expressions.
612 virtual void ReturnControl(HControlInstruction* instr, int ast_id) = 0;
613
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000614 void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; }
615 bool is_for_typeof() { return for_typeof_; }
616
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000617 protected:
618 AstContext(HGraphBuilder* owner, Expression::Context kind);
619 virtual ~AstContext();
620
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000621 HGraphBuilder* owner() const { return owner_; }
622
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000623 inline Zone* zone() const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000624
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000625 // We want to be able to assert, in a context-specific way, that the stack
626 // height makes sense when the context is filled.
627#ifdef DEBUG
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000628 int original_length_;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000629#endif
630
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000631 private:
632 HGraphBuilder* owner_;
633 Expression::Context kind_;
634 AstContext* outer_;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000635 bool for_typeof_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000636};
637
638
639class EffectContext: public AstContext {
640 public:
641 explicit EffectContext(HGraphBuilder* owner)
642 : AstContext(owner, Expression::kEffect) {
643 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000644 virtual ~EffectContext();
645
646 virtual void ReturnValue(HValue* value);
647 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000648 virtual void ReturnControl(HControlInstruction* instr, int ast_id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000649};
650
651
652class ValueContext: public AstContext {
653 public:
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000654 explicit ValueContext(HGraphBuilder* owner, ArgumentsAllowedFlag flag)
655 : AstContext(owner, Expression::kValue), flag_(flag) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000656 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000657 virtual ~ValueContext();
658
659 virtual void ReturnValue(HValue* value);
660 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000661 virtual void ReturnControl(HControlInstruction* instr, int ast_id);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000662
663 bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
664
665 private:
666 ArgumentsAllowedFlag flag_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000667};
668
669
670class TestContext: public AstContext {
671 public:
672 TestContext(HGraphBuilder* owner,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000673 Expression* condition,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000674 HBasicBlock* if_true,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000675 HBasicBlock* if_false)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000676 : AstContext(owner, Expression::kTest),
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000677 condition_(condition),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000678 if_true_(if_true),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000679 if_false_(if_false) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000680 }
681
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000682 virtual void ReturnValue(HValue* value);
683 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000684 virtual void ReturnControl(HControlInstruction* instr, int ast_id);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000685
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000686 static TestContext* cast(AstContext* context) {
687 ASSERT(context->IsTest());
688 return reinterpret_cast<TestContext*>(context);
689 }
690
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000691 Expression* condition() const { return condition_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000692 HBasicBlock* if_true() const { return if_true_; }
693 HBasicBlock* if_false() const { return if_false_; }
694
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000695 private:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000696 // Build the shared core part of the translation unpacking a value into
697 // control flow.
698 void BuildBranch(HValue* value);
699
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000700 Expression* condition_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000701 HBasicBlock* if_true_;
702 HBasicBlock* if_false_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000703};
704
705
ulan@chromium.org967e2702012-02-28 09:49:15 +0000706enum ReturnHandlingFlag {
707 NORMAL_RETURN,
708 DROP_EXTRA_ON_RETURN,
709 CONSTRUCT_CALL_RETURN
710};
711
712
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000713class FunctionState {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000714 public:
715 FunctionState(HGraphBuilder* owner,
716 CompilationInfo* info,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000717 TypeFeedbackOracle* oracle,
ulan@chromium.org967e2702012-02-28 09:49:15 +0000718 ReturnHandlingFlag return_handling);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000719 ~FunctionState();
720
721 CompilationInfo* compilation_info() { return compilation_info_; }
722 TypeFeedbackOracle* oracle() { return oracle_; }
723 AstContext* call_context() { return call_context_; }
ulan@chromium.org967e2702012-02-28 09:49:15 +0000724 bool drop_extra() { return return_handling_ == DROP_EXTRA_ON_RETURN; }
725 bool is_construct() { return return_handling_ == CONSTRUCT_CALL_RETURN; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000726 HBasicBlock* function_return() { return function_return_; }
727 TestContext* test_context() { return test_context_; }
728 void ClearInlinedTestContext() {
729 delete test_context_;
730 test_context_ = NULL;
731 }
732
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000733 FunctionState* outer() { return outer_; }
734
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000735 HEnterInlined* entry() { return entry_; }
736 void set_entry(HEnterInlined* entry) { entry_ = entry; }
737
738 HArgumentsElements* arguments_elements() { return arguments_elements_; }
739 void set_arguments_elements(HArgumentsElements* arguments_elements) {
740 arguments_elements_ = arguments_elements;
741 }
742
743 bool arguments_pushed() { return arguments_elements() != NULL; }
744
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000745 private:
746 HGraphBuilder* owner_;
747
748 CompilationInfo* compilation_info_;
749 TypeFeedbackOracle* oracle_;
750
751 // During function inlining, expression context of the call being
752 // inlined. NULL when not inlining.
753 AstContext* call_context_;
754
ulan@chromium.org967e2702012-02-28 09:49:15 +0000755 // Indicate whether we have to perform special handling on return from
756 // inlined functions.
757 // - DROP_EXTRA_ON_RETURN: Drop an extra value from the environment.
758 // - CONSTRUCT_CALL_RETURN: Either use allocated receiver or return value.
759 ReturnHandlingFlag return_handling_;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000760
ulan@chromium.org967e2702012-02-28 09:49:15 +0000761 // When inlining in an effect or value context, this is the return block.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000762 // It is NULL otherwise. When inlining in a test context, there are a
763 // pair of return blocks in the context. When not inlining, there is no
764 // local return point.
765 HBasicBlock* function_return_;
766
767 // When inlining a call in a test context, a context containing a pair of
768 // return blocks. NULL in all other cases.
769 TestContext* test_context_;
770
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000771 // When inlining HEnterInlined instruction corresponding to the function
772 // entry.
773 HEnterInlined* entry_;
774
775 HArgumentsElements* arguments_elements_;
776
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000777 FunctionState* outer_;
778};
779
780
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000781class HGraphBuilder: public AstVisitor {
782 public:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000783 enum BreakType { BREAK, CONTINUE };
erikcorry0ad885c2011-11-21 13:51:57 +0000784 enum SwitchType { UNKNOWN_SWITCH, SMI_SWITCH, STRING_SWITCH };
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000785
786 // A class encapsulating (lazily-allocated) break and continue blocks for
787 // a breakable statement. Separated from BreakAndContinueScope so that it
788 // can have a separate lifetime.
789 class BreakAndContinueInfo BASE_EMBEDDED {
790 public:
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000791 explicit BreakAndContinueInfo(BreakableStatement* target,
792 int drop_extra = 0)
793 : target_(target),
794 break_block_(NULL),
795 continue_block_(NULL),
796 drop_extra_(drop_extra) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000797 }
798
799 BreakableStatement* target() { return target_; }
800 HBasicBlock* break_block() { return break_block_; }
801 void set_break_block(HBasicBlock* block) { break_block_ = block; }
802 HBasicBlock* continue_block() { return continue_block_; }
803 void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000804 int drop_extra() { return drop_extra_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000805
806 private:
807 BreakableStatement* target_;
808 HBasicBlock* break_block_;
809 HBasicBlock* continue_block_;
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000810 int drop_extra_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000811 };
812
813 // A helper class to maintain a stack of current BreakAndContinueInfo
814 // structures mirroring BreakableStatement nesting.
815 class BreakAndContinueScope BASE_EMBEDDED {
816 public:
817 BreakAndContinueScope(BreakAndContinueInfo* info, HGraphBuilder* owner)
818 : info_(info), owner_(owner), next_(owner->break_scope()) {
819 owner->set_break_scope(this);
820 }
821
822 ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
823
824 BreakAndContinueInfo* info() { return info_; }
825 HGraphBuilder* owner() { return owner_; }
826 BreakAndContinueScope* next() { return next_; }
827
828 // Search the break stack for a break or continue target.
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000829 HBasicBlock* Get(BreakableStatement* stmt, BreakType type, int* drop_extra);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000830
831 private:
832 BreakAndContinueInfo* info_;
833 HGraphBuilder* owner_;
834 BreakAndContinueScope* next_;
835 };
836
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000837 HGraphBuilder(CompilationInfo* info, TypeFeedbackOracle* oracle);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000838
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000839 HGraph* CreateGraph();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000840
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000841 // Simple accessors.
842 HGraph* graph() const { return graph_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000843 BreakAndContinueScope* break_scope() const { return break_scope_; }
844 void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000845
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000846 HBasicBlock* current_block() const { return current_block_; }
847 void set_current_block(HBasicBlock* block) { current_block_ = block; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000848 HEnvironment* environment() const {
849 return current_block()->last_environment();
850 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000851
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000852 bool inline_bailout() { return inline_bailout_; }
853
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000854 // Adding instructions.
855 HInstruction* AddInstruction(HInstruction* instr);
ager@chromium.org04921a82011-06-27 13:21:41 +0000856 void AddSimulate(int ast_id);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000857
858 // Bailout environment manipulation.
859 void Push(HValue* value) { environment()->Push(value); }
860 HValue* Pop() { return environment()->Pop(); }
861
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000862 void Bailout(const char* reason);
863
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000864 HBasicBlock* CreateJoin(HBasicBlock* first,
865 HBasicBlock* second,
866 int join_id);
867
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000868 TypeFeedbackOracle* oracle() const { return function_state()->oracle(); }
869
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000870 FunctionState* function_state() const { return function_state_; }
871
yangguo@chromium.org56454712012-02-16 15:33:53 +0000872 void VisitDeclarations(ZoneList<Declaration*>* declarations);
873
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000874 private:
875 // Type of a member function that generates inline code for a native function.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000876 typedef void (HGraphBuilder::*InlineFunctionGenerator)(CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000877
878 // Forward declarations for inner scope classes.
879 class SubgraphScope;
880
881 static const InlineFunctionGenerator kInlineFunctionGenerators[];
882
883 static const int kMaxCallPolymorphism = 4;
884 static const int kMaxLoadPolymorphism = 4;
885 static const int kMaxStorePolymorphism = 4;
886
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000887 // Even in the 'unlimited' case we have to have some limit in order not to
888 // overflow the stack.
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +0000889 static const int kUnlimitedMaxInlinedSourceSize = 100000;
890 static const int kUnlimitedMaxInlinedNodes = 10000;
891 static const int kUnlimitedMaxInlinedNodesCumulative = 10000;
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000892
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000893 // Simple accessors.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000894 void set_function_state(FunctionState* state) { function_state_ = state; }
895
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000896 AstContext* ast_context() const { return ast_context_; }
897 void set_ast_context(AstContext* context) { ast_context_ = context; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000898
899 // Accessors forwarded to the function state.
900 CompilationInfo* info() const {
901 return function_state()->compilation_info();
902 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000903 AstContext* call_context() const {
904 return function_state()->call_context();
905 }
906 HBasicBlock* function_return() const {
907 return function_state()->function_return();
908 }
909 TestContext* inlined_test_context() const {
910 return function_state()->test_context();
911 }
912 void ClearInlinedTestContext() {
913 function_state()->ClearInlinedTestContext();
914 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000915 StrictModeFlag function_strict_mode_flag() {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000916 return function_state()->compilation_info()->is_classic_mode()
917 ? kNonStrictMode : kStrictMode;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000918 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000919
920 // Generators for inline runtime functions.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000921#define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000922 void Generate##Name(CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000923
924 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
925 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
926#undef INLINE_FUNCTION_GENERATOR_DECLARATION
927
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000928 void VisitDelete(UnaryOperation* expr);
929 void VisitVoid(UnaryOperation* expr);
930 void VisitTypeof(UnaryOperation* expr);
931 void VisitAdd(UnaryOperation* expr);
932 void VisitSub(UnaryOperation* expr);
933 void VisitBitNot(UnaryOperation* expr);
934 void VisitNot(UnaryOperation* expr);
935
936 void VisitComma(BinaryOperation* expr);
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000937 void VisitLogicalExpression(BinaryOperation* expr);
938 void VisitArithmeticExpression(BinaryOperation* expr);
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000939
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000940 bool PreProcessOsrEntry(IterationStatement* statement);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000941 // True iff. we are compiling for OSR and the statement is the entry.
942 bool HasOsrEntryAt(IterationStatement* statement);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000943 void VisitLoopBody(IterationStatement* stmt,
ager@chromium.org04921a82011-06-27 13:21:41 +0000944 HBasicBlock* loop_entry,
945 BreakAndContinueInfo* break_info);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000946
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000947 // Create a back edge in the flow graph. body_exit is the predecessor
948 // block and loop_entry is the successor block. loop_successor is the
949 // block where control flow exits the loop normally (e.g., via failure of
950 // the condition) and break_block is the block where control flow breaks
951 // from the loop. All blocks except loop_entry can be NULL. The return
952 // value is the new successor block which is the join of loop_successor
953 // and break_block, or NULL.
954 HBasicBlock* CreateLoop(IterationStatement* statement,
955 HBasicBlock* loop_entry,
956 HBasicBlock* body_exit,
957 HBasicBlock* loop_successor,
958 HBasicBlock* break_block);
959
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000960 HBasicBlock* JoinContinue(IterationStatement* statement,
961 HBasicBlock* exit_block,
962 HBasicBlock* continue_block);
963
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000964 HValue* Top() const { return environment()->Top(); }
965 void Drop(int n) { environment()->Drop(n); }
966 void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
967
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000968 // The value of the arguments object is allowed in some but not most value
969 // contexts. (It's allowed in all effect contexts and disallowed in all
970 // test contexts.)
971 void VisitForValue(Expression* expr,
972 ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000973 void VisitForTypeOf(Expression* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000974 void VisitForEffect(Expression* expr);
975 void VisitForControl(Expression* expr,
976 HBasicBlock* true_block,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000977 HBasicBlock* false_block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000978
verwaest@chromium.org753aee42012-07-17 16:15:42 +0000979 // Visit an argument subexpression and emit a push to the outgoing arguments.
980 void VisitArgument(Expression* expr);
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000981
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000982 void VisitArgumentList(ZoneList<Expression*>* arguments);
983
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000984 // Visit a list of expressions from left to right, each in a value context.
985 void VisitExpressions(ZoneList<Expression*>* exprs);
986
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000987 void AddPhi(HPhi* phi);
988
989 void PushAndAdd(HInstruction* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000990
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000991 // Remove the arguments from the bailout environment and emit instructions
992 // to push them as outgoing parameters.
ulan@chromium.org967e2702012-02-28 09:49:15 +0000993 template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000994
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000995 void TraceRepresentation(Token::Value op,
996 TypeInfo info,
997 HValue* value,
998 Representation rep);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000999 static Representation ToRepresentation(TypeInfo info);
1000
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001001 void SetUpScope(Scope* scope);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001002 virtual void VisitStatements(ZoneList<Statement*>* statements);
1003
1004#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
1005 AST_NODE_LIST(DECLARE_VISIT)
1006#undef DECLARE_VISIT
1007
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001008 HBasicBlock* CreateBasicBlock(HEnvironment* env);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001009 HBasicBlock* CreateLoopHeaderBlock();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001010
1011 // Helpers for flow graph construction.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001012 enum GlobalPropertyAccess {
1013 kUseCell,
1014 kUseGeneric
1015 };
1016 GlobalPropertyAccess LookupGlobalProperty(Variable* var,
1017 LookupResult* lookup,
1018 bool is_store);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001019
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001020 void EnsureArgumentsArePushedForAccess();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001021 bool TryArgumentsAccess(Property* expr);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001022
1023 // Try to optimize fun.apply(receiver, arguments) pattern.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001024 bool TryCallApply(Call* expr);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001025
jkummerow@chromium.org212d9642012-05-11 15:02:09 +00001026 int InliningAstSize(Handle<JSFunction> target);
ulan@chromium.org967e2702012-02-28 09:49:15 +00001027 bool TryInline(CallKind call_kind,
1028 Handle<JSFunction> target,
1029 ZoneList<Expression*>* arguments,
1030 HValue* receiver,
1031 int ast_id,
1032 int return_id,
1033 ReturnHandlingFlag return_handling);
1034
1035 bool TryInlineCall(Call* expr, bool drop_extra = false);
1036 bool TryInlineConstruct(CallNew* expr, HValue* receiver);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001037 bool TryInlineBuiltinMethodCall(Call* expr,
ulan@chromium.org967e2702012-02-28 09:49:15 +00001038 HValue* receiver,
1039 Handle<Map> receiver_map,
1040 CheckType check_type);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001041 bool TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001042
1043 // If --trace-inlining, print a line of the inlining trace. Inlining
1044 // succeeded if the reason string is NULL and failed if there is a
1045 // non-NULL reason string.
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001046 void TraceInline(Handle<JSFunction> target,
1047 Handle<JSFunction> caller,
1048 const char* failure_reason);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001049
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001050 void HandleGlobalVariableAssignment(Variable* var,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001051 HValue* value,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001052 int position,
1053 int ast_id);
1054
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001055 void HandlePropertyAssignment(Assignment* expr);
1056 void HandleCompoundAssignment(Assignment* expr);
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001057 void HandlePolymorphicLoadNamedField(Property* expr,
1058 HValue* object,
1059 SmallMapList* types,
1060 Handle<String> name);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001061 void HandlePolymorphicStoreNamedField(Assignment* expr,
1062 HValue* object,
1063 HValue* value,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001064 SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001065 Handle<String> name);
1066 void HandlePolymorphicCallNamed(Call* expr,
1067 HValue* receiver,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001068 SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001069 Handle<String> name);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001070 void HandleLiteralCompareTypeof(CompareOperation* expr,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001071 HTypeof* typeof_expr,
ager@chromium.org04921a82011-06-27 13:21:41 +00001072 Handle<String> check);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001073 void HandleLiteralCompareNil(CompareOperation* expr,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001074 HValue* value,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001075 NilValue nil);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001076
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001077 HStringCharCodeAt* BuildStringCharCodeAt(HValue* context,
1078 HValue* string,
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001079 HValue* index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001080 HInstruction* BuildBinaryOperation(BinaryOperation* expr,
1081 HValue* left,
1082 HValue* right);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001083 HInstruction* BuildIncrement(bool returns_original_input,
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001084 CountOperation* expr);
whesse@chromium.org023421e2010-12-21 12:19:12 +00001085 HLoadNamedField* BuildLoadNamedField(HValue* object,
1086 Property* expr,
1087 Handle<Map> type,
1088 LookupResult* result,
1089 bool smi_and_map_check);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001090 HInstruction* BuildLoadNamedGeneric(HValue* object, Property* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001091 HInstruction* BuildLoadKeyedGeneric(HValue* object,
1092 HValue* key);
whesse@chromium.org7b260152011-06-20 15:33:18 +00001093 HInstruction* BuildExternalArrayElementAccess(
1094 HValue* external_elements,
1095 HValue* checked_key,
1096 HValue* val,
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001097 ElementsKind elements_kind,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001098 bool is_store);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001099 HInstruction* BuildFastElementAccess(HValue* elements,
1100 HValue* checked_key,
1101 HValue* val,
1102 ElementsKind elements_kind,
1103 bool is_store);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001104
mstarzinger@chromium.orgc6d9cee2012-07-03 10:03:19 +00001105 HInstruction* TryBuildConsolidatedElementLoad(HValue* object,
1106 HValue* key,
1107 HValue* val,
1108 SmallMapList* maps);
1109
1110 HInstruction* BuildUncheckedMonomorphicElementAccess(HValue* object,
1111 HValue* key,
1112 HValue* val,
1113 HCheckMaps* mapcheck,
1114 Handle<Map> map,
1115 bool is_store);
1116
whesse@chromium.org7b260152011-06-20 15:33:18 +00001117 HInstruction* BuildMonomorphicElementAccess(HValue* object,
1118 HValue* key,
1119 HValue* val,
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00001120 HValue* dependency,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001121 Handle<Map> map,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001122 bool is_store);
mstarzinger@chromium.orgc6d9cee2012-07-03 10:03:19 +00001123
whesse@chromium.org7b260152011-06-20 15:33:18 +00001124 HValue* HandlePolymorphicElementAccess(HValue* object,
1125 HValue* key,
1126 HValue* val,
1127 Expression* prop,
1128 int ast_id,
1129 int position,
1130 bool is_store,
1131 bool* has_side_effects);
1132
1133 HValue* HandleKeyedElementAccess(HValue* obj,
1134 HValue* key,
1135 HValue* val,
1136 Expression* expr,
1137 int ast_id,
1138 int position,
1139 bool is_store,
1140 bool* has_side_effects);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001141
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001142 HInstruction* BuildCallGetter(HValue* obj,
1143 Property* expr,
1144 Handle<Map> map,
1145 Handle<Object> callback,
1146 Handle<JSObject> holder);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001147 HInstruction* BuildLoadNamed(HValue* object,
1148 Property* prop,
1149 Handle<Map> map,
1150 Handle<String> name);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00001151 HInstruction* BuildCallSetter(HValue* object,
1152 Handle<String> name,
1153 HValue* value,
1154 Handle<Map> map,
1155 Handle<Object> callback,
1156 Handle<JSObject> holder);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001157 HInstruction* BuildStoreNamed(HValue* object,
1158 HValue* value,
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00001159 Handle<Map> type,
1160 Expression* key);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001161 HInstruction* BuildStoreNamedField(HValue* object,
1162 Handle<String> name,
1163 HValue* value,
1164 Handle<Map> type,
1165 LookupResult* lookup,
1166 bool smi_and_map_check);
1167 HInstruction* BuildStoreNamedGeneric(HValue* object,
1168 Handle<String> name,
1169 HValue* value);
1170 HInstruction* BuildStoreKeyedGeneric(HValue* object,
1171 HValue* key,
1172 HValue* value);
1173
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001174 HValue* BuildContextChainWalk(Variable* var);
1175
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001176 HInstruction* BuildThisFunction();
1177
yangguo@chromium.org99aa4902012-07-06 16:21:55 +00001178 void AddCheckConstantFunction(Handle<JSObject> holder,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001179 HValue* receiver,
1180 Handle<Map> receiver_map,
1181 bool smi_and_map_check);
1182
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001183 Zone* zone() const { return zone_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001184
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001185 // The translation state of the currently-being-translated function.
1186 FunctionState* function_state_;
1187
1188 // The base of the function state stack.
1189 FunctionState initial_function_state_;
1190
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001191 // Expression context of the currently visited subexpression. NULL when
1192 // visiting statements.
1193 AstContext* ast_context_;
1194
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001195 // A stack of breakable statements entered.
1196 BreakAndContinueScope* break_scope_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001197
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001198 HGraph* graph_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001199 HBasicBlock* current_block_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001200
1201 int inlined_count_;
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001202 ZoneList<Handle<Object> > globals_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001203
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001204 Zone* zone_;
1205
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001206 bool inline_bailout_;
1207
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001208 friend class FunctionState; // Pushes and pops the state stack.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001209 friend class AstContext; // Pushes and pops the AST context stack.
1210
1211 DISALLOW_COPY_AND_ASSIGN(HGraphBuilder);
1212};
1213
1214
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001215Zone* AstContext::zone() const { return owner_->zone(); }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001216
1217
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001218class HValueMap: public ZoneObject {
1219 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001220 explicit HValueMap(Zone* zone)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001221 : array_size_(0),
1222 lists_size_(0),
1223 count_(0),
1224 present_flags_(0),
1225 array_(NULL),
1226 lists_(NULL),
1227 free_list_head_(kNil) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001228 ResizeLists(kInitialSize, zone);
1229 Resize(kInitialSize, zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001230 }
1231
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001232 void Kill(GVNFlagSet flags);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001233
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001234 void Add(HValue* value, Zone* zone) {
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001235 present_flags_.Add(value->gvn_flags());
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001236 Insert(value, zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001237 }
1238
1239 HValue* Lookup(HValue* value) const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001240
1241 HValueMap* Copy(Zone* zone) const {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001242 return new(zone) HValueMap(zone, this);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001243 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001244
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001245 bool IsEmpty() const { return count_ == 0; }
1246
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001247 private:
1248 // A linked list of HValue* values. Stored in arrays.
1249 struct HValueMapListElement {
1250 HValue* value;
1251 int next; // Index in the array of the next list element.
1252 };
1253 static const int kNil = -1; // The end of a linked list
1254
1255 // Must be a power of 2.
1256 static const int kInitialSize = 16;
1257
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001258 HValueMap(Zone* zone, const HValueMap* other);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001259
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001260 void Resize(int new_size, Zone* zone);
1261 void ResizeLists(int new_size, Zone* zone);
1262 void Insert(HValue* value, Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001263 uint32_t Bound(uint32_t value) const { return value & (array_size_ - 1); }
1264
1265 int array_size_;
1266 int lists_size_;
1267 int count_; // The number of values stored in the HValueMap.
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001268 GVNFlagSet present_flags_; // All flags that are in any value in the
1269 // HValueMap.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001270 HValueMapListElement* array_; // Primary store - contains the first value
1271 // with a given hash. Colliding elements are stored in linked lists.
1272 HValueMapListElement* lists_; // The linked lists containing hash collisions.
1273 int free_list_head_; // Unused elements in lists_ are on the free list.
1274};
1275
1276
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001277class HSideEffectMap BASE_EMBEDDED {
1278 public:
1279 HSideEffectMap();
1280 explicit HSideEffectMap(HSideEffectMap* other);
rossberg@chromium.org400388e2012-06-06 09:29:22 +00001281 HSideEffectMap& operator= (const HSideEffectMap& other);
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001282
1283 void Kill(GVNFlagSet flags);
1284
1285 void Store(GVNFlagSet flags, HInstruction* instr);
1286
1287 bool IsEmpty() const { return count_ == 0; }
1288
1289 inline HInstruction* operator[](int i) const {
1290 ASSERT(0 <= i);
1291 ASSERT(i < kNumberOfTrackedSideEffects);
1292 return data_[i];
1293 }
1294 inline HInstruction* at(int i) const { return operator[](i); }
1295
1296 private:
1297 int count_;
1298 HInstruction* data_[kNumberOfTrackedSideEffects];
1299};
1300
1301
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001302class HStatistics: public Malloced {
1303 public:
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001304 void Initialize(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001305 void Print();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001306 void SaveTiming(const char* name, int64_t ticks, unsigned size);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001307 static HStatistics* Instance() {
1308 static SetOncePointer<HStatistics> instance;
1309 if (!instance.is_set()) {
1310 instance.set(new HStatistics());
1311 }
1312 return instance.get();
1313 }
1314
1315 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001316 HStatistics()
1317 : timing_(5),
1318 names_(5),
1319 sizes_(5),
1320 total_(0),
1321 total_size_(0),
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001322 full_code_gen_(0),
1323 source_size_(0) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001324
1325 List<int64_t> timing_;
1326 List<const char*> names_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001327 List<unsigned> sizes_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001328 int64_t total_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001329 unsigned total_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001330 int64_t full_code_gen_;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001331 double source_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001332};
1333
1334
1335class HPhase BASE_EMBEDDED {
1336 public:
1337 static const char* const kFullCodeGen;
1338 static const char* const kTotal;
1339
1340 explicit HPhase(const char* name) { Begin(name, NULL, NULL, NULL); }
1341 HPhase(const char* name, HGraph* graph) {
1342 Begin(name, graph, NULL, NULL);
1343 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00001344 HPhase(const char* name, LChunk* chunk) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001345 Begin(name, NULL, chunk, NULL);
1346 }
1347 HPhase(const char* name, LAllocator* allocator) {
1348 Begin(name, NULL, NULL, allocator);
1349 }
1350
1351 ~HPhase() {
1352 End();
1353 }
1354
1355 private:
1356 void Begin(const char* name,
1357 HGraph* graph,
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00001358 LChunk* chunk,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001359 LAllocator* allocator);
1360 void End() const;
1361
1362 int64_t start_;
1363 const char* name_;
1364 HGraph* graph_;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00001365 LChunk* chunk_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001366 LAllocator* allocator_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001367 unsigned start_allocation_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001368};
1369
1370
1371class HTracer: public Malloced {
1372 public:
1373 void TraceCompilation(FunctionLiteral* function);
1374 void TraceHydrogen(const char* name, HGraph* graph);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00001375 void TraceLithium(const char* name, LChunk* chunk);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001376 void TraceLiveRanges(const char* name, LAllocator* allocator);
1377
1378 static HTracer* Instance() {
1379 static SetOncePointer<HTracer> instance;
1380 if (!instance.is_set()) {
1381 instance.set(new HTracer("hydrogen.cfg"));
1382 }
1383 return instance.get();
1384 }
1385
1386 private:
1387 class Tag BASE_EMBEDDED {
1388 public:
1389 Tag(HTracer* tracer, const char* name) {
1390 name_ = name;
1391 tracer_ = tracer;
1392 tracer->PrintIndent();
1393 tracer->trace_.Add("begin_%s\n", name);
1394 tracer->indent_++;
1395 }
1396
1397 ~Tag() {
1398 tracer_->indent_--;
1399 tracer_->PrintIndent();
1400 tracer_->trace_.Add("end_%s\n", name_);
1401 ASSERT(tracer_->indent_ >= 0);
1402 tracer_->FlushToFile();
1403 }
1404
1405 private:
1406 HTracer* tracer_;
1407 const char* name_;
1408 };
1409
1410 explicit HTracer(const char* filename)
1411 : filename_(filename), trace_(&string_allocator_), indent_(0) {
1412 WriteChars(filename, "", 0, false);
1413 }
1414
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001415 void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00001416 void Trace(const char* name, HGraph* graph, LChunk* chunk);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001417 void FlushToFile();
1418
1419 void PrintEmptyProperty(const char* name) {
1420 PrintIndent();
1421 trace_.Add("%s\n", name);
1422 }
1423
1424 void PrintStringProperty(const char* name, const char* value) {
1425 PrintIndent();
1426 trace_.Add("%s \"%s\"\n", name, value);
1427 }
1428
1429 void PrintLongProperty(const char* name, int64_t value) {
1430 PrintIndent();
1431 trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
1432 }
1433
1434 void PrintBlockProperty(const char* name, int block_id) {
1435 PrintIndent();
1436 trace_.Add("%s \"B%d\"\n", name, block_id);
1437 }
1438
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001439 void PrintIntProperty(const char* name, int value) {
1440 PrintIndent();
1441 trace_.Add("%s %d\n", name, value);
1442 }
1443
1444 void PrintIndent() {
1445 for (int i = 0; i < indent_; i++) {
1446 trace_.Add(" ");
1447 }
1448 }
1449
1450 const char* filename_;
1451 HeapStringAllocator string_allocator_;
1452 StringStream trace_;
1453 int indent_;
1454};
1455
1456
1457} } // namespace v8::internal
1458
1459#endif // V8_HYDROGEN_H_