blob: 7b7b92297760ffba6fa1288eec8b7fb14cdd256a [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) {
80 deleted_phis_.Add(merge_index);
81 }
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
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000161 inline Zone* zone();
162
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:
215 explicit HLoopInformation(HBasicBlock* loop_header)
ager@chromium.org04921a82011-06-27 13:21:41 +0000216 : back_edges_(4),
217 loop_header_(loop_header),
218 blocks_(8),
219 stack_check_(NULL) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000220 blocks_.Add(loop_header);
221 }
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
244
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000245class HGraph: public ZoneObject {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000246 public:
247 explicit HGraph(CompilationInfo* info);
248
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000249 Isolate* isolate() { return isolate_; }
250 Zone* zone() { return isolate_->zone(); }
251
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000252 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
253 const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000254 HBasicBlock* entry_block() const { return entry_block_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000255 HEnvironment* start_environment() const { return start_environment_; }
256
257 void InitializeInferredTypes();
258 void InsertTypeConversions();
259 void InsertRepresentationChanges();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000260 void MarkDeoptimizeOnUndefined();
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000261 void ComputeMinusZeroChecks();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000262 bool ProcessArgumentsObject();
263 void EliminateRedundantPhis();
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000264 void EliminateUnreachablePhis();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000265 void Canonicalize();
266 void OrderBlocks();
267 void AssignDominators();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000268 void ReplaceCheckedValues();
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000269 void PropagateDeoptimizingMark();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000270
271 // Returns false if there are phi-uses of the arguments-object
272 // which are not supported by the optimizing compiler.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000273 bool CheckArgumentsPhiUses();
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +0000274
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000275 // Returns false if there are phi-uses of an uninitialized const
276 // which are not supported by the optimizing compiler.
277 bool CheckConstPhiUses();
278
279 void CollectPhis();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000280
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000281 Handle<Code> Compile(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000282
283 void set_undefined_constant(HConstant* constant) {
284 undefined_constant_.set(constant);
285 }
286 HConstant* GetConstantUndefined() const { return undefined_constant_.get(); }
287 HConstant* GetConstant1();
288 HConstant* GetConstantMinus1();
289 HConstant* GetConstantTrue();
290 HConstant* GetConstantFalse();
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000291 HConstant* GetConstantHole();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000292
293 HBasicBlock* CreateBasicBlock();
294 HArgumentsObject* GetArgumentsObject() const {
295 return arguments_object_.get();
296 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000297
298 void SetArgumentsObject(HArgumentsObject* object) {
299 arguments_object_.set(object);
300 }
301
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000302 int GetMaximumValueID() const { return values_.length(); }
303 int GetNextBlockID() { return next_block_id_++; }
304 int GetNextValueID(HValue* value) {
305 values_.Add(value);
306 return values_.length() - 1;
307 }
308 HValue* LookupValue(int id) const {
309 if (id >= 0 && id < values_.length()) return values_[id];
310 return NULL;
311 }
312
313#ifdef DEBUG
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000314 void Verify(bool do_full_verify) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000315#endif
316
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000317 bool has_osr_loop_entry() {
318 return osr_loop_entry_.is_set();
319 }
320
321 HBasicBlock* osr_loop_entry() {
322 return osr_loop_entry_.get();
323 }
324
325 void set_osr_loop_entry(HBasicBlock* entry) {
326 osr_loop_entry_.set(entry);
327 }
328
329 ZoneList<HUnknownOSRValue*>* osr_values() {
330 return osr_values_.get();
331 }
332
333 void set_osr_values(ZoneList<HUnknownOSRValue*>* values) {
334 osr_values_.set(values);
335 }
336
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000337 private:
338 void Postorder(HBasicBlock* block,
339 BitVector* visited,
340 ZoneList<HBasicBlock*>* order,
341 HBasicBlock* loop_header);
342 void PostorderLoopBlocks(HLoopInformation* loop,
343 BitVector* visited,
344 ZoneList<HBasicBlock*>* order,
345 HBasicBlock* loop_header);
346 HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
347 Object* value);
348
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000349 void MarkAsDeoptimizingRecursively(HBasicBlock* block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000350 void InsertTypeConversions(HInstruction* instr);
351 void PropagateMinusZeroChecks(HValue* value, BitVector* visited);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000352 void RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000353 void InsertRepresentationChangeForUse(HValue* value,
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000354 HValue* use_value,
355 int use_index,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000356 Representation to);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000357 void InsertRepresentationChangesForValue(HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000358 void InferTypes(ZoneList<HValue*>* worklist);
359 void InitializeInferredTypes(int from_inclusive, int to_inclusive);
360 void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor);
361
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000362 Isolate* isolate_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000363 int next_block_id_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000364 HBasicBlock* entry_block_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000365 HEnvironment* start_environment_;
366 ZoneList<HBasicBlock*> blocks_;
367 ZoneList<HValue*> values_;
368 ZoneList<HPhi*>* phi_list_;
369 SetOncePointer<HConstant> undefined_constant_;
370 SetOncePointer<HConstant> constant_1_;
371 SetOncePointer<HConstant> constant_minus1_;
372 SetOncePointer<HConstant> constant_true_;
373 SetOncePointer<HConstant> constant_false_;
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000374 SetOncePointer<HConstant> constant_hole_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000375 SetOncePointer<HArgumentsObject> arguments_object_;
376
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000377 SetOncePointer<HBasicBlock> osr_loop_entry_;
378 SetOncePointer<ZoneList<HUnknownOSRValue*> > osr_values_;
379
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000380 DISALLOW_COPY_AND_ASSIGN(HGraph);
381};
382
383
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000384Zone* HBasicBlock::zone() { return graph_->zone(); }
385
386
ulan@chromium.org967e2702012-02-28 09:49:15 +0000387// Type of stack frame an environment might refer to.
388enum FrameType { JS_FUNCTION, JS_CONSTRUCT, ARGUMENTS_ADAPTOR };
389
390
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000391class HEnvironment: public ZoneObject {
392 public:
393 HEnvironment(HEnvironment* outer,
394 Scope* scope,
395 Handle<JSFunction> closure);
396
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000397 HEnvironment* DiscardInlined(bool drop_extra) {
ulan@chromium.org967e2702012-02-28 09:49:15 +0000398 HEnvironment* outer = outer_;
399 while (outer->frame_type() != JS_FUNCTION) outer = outer->outer_;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000400 if (drop_extra) outer->Drop(1);
401 return outer;
402 }
403
ulan@chromium.org6ff65142012-03-21 09:52:17 +0000404 HEnvironment* arguments_environment() {
405 return outer()->frame_type() == ARGUMENTS_ADAPTOR ? outer() : this;
406 }
407
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000408 // Simple accessors.
409 Handle<JSFunction> closure() const { return closure_; }
410 const ZoneList<HValue*>* values() const { return &values_; }
411 const ZoneList<int>* assigned_variables() const {
412 return &assigned_variables_;
413 }
ulan@chromium.org967e2702012-02-28 09:49:15 +0000414 FrameType frame_type() const { return frame_type_; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000415 int parameter_count() const { return parameter_count_; }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000416 int specials_count() const { return specials_count_; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000417 int local_count() const { return local_count_; }
418 HEnvironment* outer() const { return outer_; }
419 int pop_count() const { return pop_count_; }
420 int push_count() const { return push_count_; }
421
422 int ast_id() const { return ast_id_; }
423 void set_ast_id(int id) { ast_id_ = id; }
424
425 int length() const { return values_.length(); }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000426 bool is_special_index(int i) const {
427 return i >= parameter_count() && i < parameter_count() + specials_count();
428 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000429
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000430 int first_expression_index() const {
431 return parameter_count() + specials_count() + local_count();
432 }
433
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000434 void Bind(Variable* variable, HValue* value) {
435 Bind(IndexFor(variable), value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000436 }
437
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000438 void Bind(int index, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000439
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000440 void BindContext(HValue* value) {
441 Bind(parameter_count(), value);
442 }
443
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000444 HValue* Lookup(Variable* variable) const {
445 return Lookup(IndexFor(variable));
446 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000447
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000448 HValue* Lookup(int index) const {
449 HValue* result = values_[index];
450 ASSERT(result != NULL);
451 return result;
452 }
453
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000454 HValue* LookupContext() const {
455 // Return first special.
456 return Lookup(parameter_count());
457 }
458
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000459 void Push(HValue* value) {
460 ASSERT(value != NULL);
461 ++push_count_;
462 values_.Add(value);
463 }
464
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000465 HValue* Pop() {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000466 ASSERT(!ExpressionStackIsEmpty());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000467 if (push_count_ > 0) {
468 --push_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000469 } else {
470 ++pop_count_;
471 }
472 return values_.RemoveLast();
473 }
474
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000475 void Drop(int count);
476
477 HValue* Top() const { return ExpressionStackAt(0); }
478
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000479 bool ExpressionStackIsEmpty() const;
480
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000481 HValue* ExpressionStackAt(int index_from_top) const {
482 int index = length() - index_from_top - 1;
483 ASSERT(HasExpressionAt(index));
484 return values_[index];
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000485 }
486
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000487 void SetExpressionStackAt(int index_from_top, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000488
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000489 HEnvironment* Copy() const;
490 HEnvironment* CopyWithoutHistory() const;
491 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const;
492
493 // Create an "inlined version" of this environment, where the original
494 // environment is the outer environment but the top expression stack
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000495 // elements are moved to an inner environment as parameters.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000496 HEnvironment* CopyForInlining(Handle<JSFunction> target,
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000497 int arguments,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000498 FunctionLiteral* function,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000499 HConstant* undefined,
ulan@chromium.org967e2702012-02-28 09:49:15 +0000500 CallKind call_kind,
501 bool is_construct) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000502
503 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000504
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000505 void ClearHistory() {
506 pop_count_ = 0;
507 push_count_ = 0;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000508 assigned_variables_.Rewind(0);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000509 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000510
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000511 void SetValueAt(int index, HValue* value) {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000512 ASSERT(index < length());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000513 values_[index] = value;
514 }
515
516 void PrintTo(StringStream* stream);
517 void PrintToStd();
518
519 private:
520 explicit HEnvironment(const HEnvironment* other);
521
ulan@chromium.org967e2702012-02-28 09:49:15 +0000522 HEnvironment(HEnvironment* outer,
523 Handle<JSFunction> closure,
524 FrameType frame_type,
525 int arguments);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000526
ulan@chromium.org967e2702012-02-28 09:49:15 +0000527 // Create an artificial stub environment (e.g. for argument adaptor or
528 // constructor stub).
529 HEnvironment* CreateStubEnvironment(HEnvironment* outer,
530 Handle<JSFunction> target,
531 FrameType frame_type,
532 int arguments) const;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000533
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000534 // True if index is included in the expression stack part of the environment.
535 bool HasExpressionAt(int index) const;
536
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000537 void Initialize(int parameter_count, int local_count, int stack_height);
538 void Initialize(const HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000539
540 // Map a variable to an environment index. Parameter indices are shifted
541 // by 1 (receiver is parameter index -1 but environment index 0).
542 // Stack-allocated local indices are shifted by the number of parameters.
543 int IndexFor(Variable* variable) const {
jkummerow@chromium.org486075a2011-09-07 12:44:28 +0000544 ASSERT(variable->IsStackAllocated());
545 int shift = variable->IsParameter()
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000546 ? 1
547 : parameter_count_ + specials_count_;
jkummerow@chromium.org486075a2011-09-07 12:44:28 +0000548 return variable->index() + shift;
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000549 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000550
551 Handle<JSFunction> closure_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000552 // Value array [parameters] [specials] [locals] [temporaries].
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000553 ZoneList<HValue*> values_;
554 ZoneList<int> assigned_variables_;
ulan@chromium.org967e2702012-02-28 09:49:15 +0000555 FrameType frame_type_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000556 int parameter_count_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000557 int specials_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000558 int local_count_;
559 HEnvironment* outer_;
560 int pop_count_;
561 int push_count_;
562 int ast_id_;
563};
564
565
566class HGraphBuilder;
567
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000568enum ArgumentsAllowedFlag {
569 ARGUMENTS_NOT_ALLOWED,
570 ARGUMENTS_ALLOWED
571};
572
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000573// This class is not BASE_EMBEDDED because our inlining implementation uses
574// new and delete.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000575class AstContext {
576 public:
577 bool IsEffect() const { return kind_ == Expression::kEffect; }
578 bool IsValue() const { return kind_ == Expression::kValue; }
579 bool IsTest() const { return kind_ == Expression::kTest; }
580
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000581 // 'Fill' this context with a hydrogen value. The value is assumed to
582 // have already been inserted in the instruction stream (or not need to
583 // be, e.g., HPhi). Call this function in tail position in the Visit
584 // functions for expressions.
585 virtual void ReturnValue(HValue* value) = 0;
586
587 // Add a hydrogen instruction to the instruction stream (recording an
588 // environment simulation if necessary) and then fill this context with
589 // the instruction as value.
590 virtual void ReturnInstruction(HInstruction* instr, int ast_id) = 0;
591
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000592 // Finishes the current basic block and materialize a boolean for
593 // value context, nothing for effect, generate a branch for test context.
594 // Call this function in tail position in the Visit functions for
595 // expressions.
596 virtual void ReturnControl(HControlInstruction* instr, int ast_id) = 0;
597
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000598 void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; }
599 bool is_for_typeof() { return for_typeof_; }
600
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000601 protected:
602 AstContext(HGraphBuilder* owner, Expression::Context kind);
603 virtual ~AstContext();
604
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000605 HGraphBuilder* owner() const { return owner_; }
606
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000607 inline Zone* zone();
608
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000609 // We want to be able to assert, in a context-specific way, that the stack
610 // height makes sense when the context is filled.
611#ifdef DEBUG
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000612 int original_length_;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000613#endif
614
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000615 private:
616 HGraphBuilder* owner_;
617 Expression::Context kind_;
618 AstContext* outer_;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000619 bool for_typeof_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000620};
621
622
623class EffectContext: public AstContext {
624 public:
625 explicit EffectContext(HGraphBuilder* owner)
626 : AstContext(owner, Expression::kEffect) {
627 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000628 virtual ~EffectContext();
629
630 virtual void ReturnValue(HValue* value);
631 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000632 virtual void ReturnControl(HControlInstruction* instr, int ast_id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000633};
634
635
636class ValueContext: public AstContext {
637 public:
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000638 explicit ValueContext(HGraphBuilder* owner, ArgumentsAllowedFlag flag)
639 : AstContext(owner, Expression::kValue), flag_(flag) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000640 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000641 virtual ~ValueContext();
642
643 virtual void ReturnValue(HValue* value);
644 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000645 virtual void ReturnControl(HControlInstruction* instr, int ast_id);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000646
647 bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
648
649 private:
650 ArgumentsAllowedFlag flag_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000651};
652
653
654class TestContext: public AstContext {
655 public:
656 TestContext(HGraphBuilder* owner,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000657 Expression* condition,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000658 HBasicBlock* if_true,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000659 HBasicBlock* if_false)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000660 : AstContext(owner, Expression::kTest),
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000661 condition_(condition),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000662 if_true_(if_true),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000663 if_false_(if_false) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000664 }
665
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000666 virtual void ReturnValue(HValue* value);
667 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000668 virtual void ReturnControl(HControlInstruction* instr, int ast_id);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000669
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000670 static TestContext* cast(AstContext* context) {
671 ASSERT(context->IsTest());
672 return reinterpret_cast<TestContext*>(context);
673 }
674
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000675 Expression* condition() const { return condition_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000676 HBasicBlock* if_true() const { return if_true_; }
677 HBasicBlock* if_false() const { return if_false_; }
678
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000679 private:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000680 // Build the shared core part of the translation unpacking a value into
681 // control flow.
682 void BuildBranch(HValue* value);
683
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000684 Expression* condition_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000685 HBasicBlock* if_true_;
686 HBasicBlock* if_false_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000687};
688
689
ulan@chromium.org967e2702012-02-28 09:49:15 +0000690enum ReturnHandlingFlag {
691 NORMAL_RETURN,
692 DROP_EXTRA_ON_RETURN,
693 CONSTRUCT_CALL_RETURN
694};
695
696
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000697class FunctionState {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000698 public:
699 FunctionState(HGraphBuilder* owner,
700 CompilationInfo* info,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000701 TypeFeedbackOracle* oracle,
ulan@chromium.org967e2702012-02-28 09:49:15 +0000702 ReturnHandlingFlag return_handling);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000703 ~FunctionState();
704
705 CompilationInfo* compilation_info() { return compilation_info_; }
706 TypeFeedbackOracle* oracle() { return oracle_; }
707 AstContext* call_context() { return call_context_; }
ulan@chromium.org967e2702012-02-28 09:49:15 +0000708 bool drop_extra() { return return_handling_ == DROP_EXTRA_ON_RETURN; }
709 bool is_construct() { return return_handling_ == CONSTRUCT_CALL_RETURN; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000710 HBasicBlock* function_return() { return function_return_; }
711 TestContext* test_context() { return test_context_; }
712 void ClearInlinedTestContext() {
713 delete test_context_;
714 test_context_ = NULL;
715 }
716
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000717 FunctionState* outer() { return outer_; }
718
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000719 HEnterInlined* entry() { return entry_; }
720 void set_entry(HEnterInlined* entry) { entry_ = entry; }
721
722 HArgumentsElements* arguments_elements() { return arguments_elements_; }
723 void set_arguments_elements(HArgumentsElements* arguments_elements) {
724 arguments_elements_ = arguments_elements;
725 }
726
727 bool arguments_pushed() { return arguments_elements() != NULL; }
728
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000729 private:
730 HGraphBuilder* owner_;
731
732 CompilationInfo* compilation_info_;
733 TypeFeedbackOracle* oracle_;
734
735 // During function inlining, expression context of the call being
736 // inlined. NULL when not inlining.
737 AstContext* call_context_;
738
ulan@chromium.org967e2702012-02-28 09:49:15 +0000739 // Indicate whether we have to perform special handling on return from
740 // inlined functions.
741 // - DROP_EXTRA_ON_RETURN: Drop an extra value from the environment.
742 // - CONSTRUCT_CALL_RETURN: Either use allocated receiver or return value.
743 ReturnHandlingFlag return_handling_;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000744
ulan@chromium.org967e2702012-02-28 09:49:15 +0000745 // When inlining in an effect or value context, this is the return block.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000746 // It is NULL otherwise. When inlining in a test context, there are a
747 // pair of return blocks in the context. When not inlining, there is no
748 // local return point.
749 HBasicBlock* function_return_;
750
751 // When inlining a call in a test context, a context containing a pair of
752 // return blocks. NULL in all other cases.
753 TestContext* test_context_;
754
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000755 // When inlining HEnterInlined instruction corresponding to the function
756 // entry.
757 HEnterInlined* entry_;
758
759 HArgumentsElements* arguments_elements_;
760
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000761 FunctionState* outer_;
762};
763
764
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000765class HGraphBuilder: public AstVisitor {
766 public:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000767 enum BreakType { BREAK, CONTINUE };
erikcorry0ad885c2011-11-21 13:51:57 +0000768 enum SwitchType { UNKNOWN_SWITCH, SMI_SWITCH, STRING_SWITCH };
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000769
770 // A class encapsulating (lazily-allocated) break and continue blocks for
771 // a breakable statement. Separated from BreakAndContinueScope so that it
772 // can have a separate lifetime.
773 class BreakAndContinueInfo BASE_EMBEDDED {
774 public:
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000775 explicit BreakAndContinueInfo(BreakableStatement* target,
776 int drop_extra = 0)
777 : target_(target),
778 break_block_(NULL),
779 continue_block_(NULL),
780 drop_extra_(drop_extra) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000781 }
782
783 BreakableStatement* target() { return target_; }
784 HBasicBlock* break_block() { return break_block_; }
785 void set_break_block(HBasicBlock* block) { break_block_ = block; }
786 HBasicBlock* continue_block() { return continue_block_; }
787 void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000788 int drop_extra() { return drop_extra_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000789
790 private:
791 BreakableStatement* target_;
792 HBasicBlock* break_block_;
793 HBasicBlock* continue_block_;
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000794 int drop_extra_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000795 };
796
797 // A helper class to maintain a stack of current BreakAndContinueInfo
798 // structures mirroring BreakableStatement nesting.
799 class BreakAndContinueScope BASE_EMBEDDED {
800 public:
801 BreakAndContinueScope(BreakAndContinueInfo* info, HGraphBuilder* owner)
802 : info_(info), owner_(owner), next_(owner->break_scope()) {
803 owner->set_break_scope(this);
804 }
805
806 ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
807
808 BreakAndContinueInfo* info() { return info_; }
809 HGraphBuilder* owner() { return owner_; }
810 BreakAndContinueScope* next() { return next_; }
811
812 // Search the break stack for a break or continue target.
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000813 HBasicBlock* Get(BreakableStatement* stmt, BreakType type, int* drop_extra);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000814
815 private:
816 BreakAndContinueInfo* info_;
817 HGraphBuilder* owner_;
818 BreakAndContinueScope* next_;
819 };
820
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000821 HGraphBuilder(CompilationInfo* info, TypeFeedbackOracle* oracle);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000822
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000823 HGraph* CreateGraph();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000824
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000825 // Simple accessors.
826 HGraph* graph() const { return graph_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000827 BreakAndContinueScope* break_scope() const { return break_scope_; }
828 void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000829
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000830 HBasicBlock* current_block() const { return current_block_; }
831 void set_current_block(HBasicBlock* block) { current_block_ = block; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000832 HEnvironment* environment() const {
833 return current_block()->last_environment();
834 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000835
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000836 bool inline_bailout() { return inline_bailout_; }
837
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000838 // Adding instructions.
839 HInstruction* AddInstruction(HInstruction* instr);
ager@chromium.org04921a82011-06-27 13:21:41 +0000840 void AddSimulate(int ast_id);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000841
842 // Bailout environment manipulation.
843 void Push(HValue* value) { environment()->Push(value); }
844 HValue* Pop() { return environment()->Pop(); }
845
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000846 void Bailout(const char* reason);
847
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000848 HBasicBlock* CreateJoin(HBasicBlock* first,
849 HBasicBlock* second,
850 int join_id);
851
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000852 TypeFeedbackOracle* oracle() const { return function_state()->oracle(); }
853
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000854 FunctionState* function_state() const { return function_state_; }
855
yangguo@chromium.org56454712012-02-16 15:33:53 +0000856 void VisitDeclarations(ZoneList<Declaration*>* declarations);
857
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000858 private:
859 // Type of a member function that generates inline code for a native function.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000860 typedef void (HGraphBuilder::*InlineFunctionGenerator)(CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000861
862 // Forward declarations for inner scope classes.
863 class SubgraphScope;
864
865 static const InlineFunctionGenerator kInlineFunctionGenerators[];
866
867 static const int kMaxCallPolymorphism = 4;
868 static const int kMaxLoadPolymorphism = 4;
869 static const int kMaxStorePolymorphism = 4;
870
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000871 // Even in the 'unlimited' case we have to have some limit in order not to
872 // overflow the stack.
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +0000873 static const int kUnlimitedMaxInlinedSourceSize = 100000;
874 static const int kUnlimitedMaxInlinedNodes = 10000;
875 static const int kUnlimitedMaxInlinedNodesCumulative = 10000;
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000876
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000877 // Simple accessors.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000878 void set_function_state(FunctionState* state) { function_state_ = state; }
879
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000880 AstContext* ast_context() const { return ast_context_; }
881 void set_ast_context(AstContext* context) { ast_context_ = context; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000882
883 // Accessors forwarded to the function state.
884 CompilationInfo* info() const {
885 return function_state()->compilation_info();
886 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000887 AstContext* call_context() const {
888 return function_state()->call_context();
889 }
890 HBasicBlock* function_return() const {
891 return function_state()->function_return();
892 }
893 TestContext* inlined_test_context() const {
894 return function_state()->test_context();
895 }
896 void ClearInlinedTestContext() {
897 function_state()->ClearInlinedTestContext();
898 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000899 StrictModeFlag function_strict_mode_flag() {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000900 return function_state()->compilation_info()->is_classic_mode()
901 ? kNonStrictMode : kStrictMode;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000902 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000903
904 // Generators for inline runtime functions.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000905#define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000906 void Generate##Name(CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000907
908 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
909 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
910#undef INLINE_FUNCTION_GENERATOR_DECLARATION
911
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000912 void VisitDelete(UnaryOperation* expr);
913 void VisitVoid(UnaryOperation* expr);
914 void VisitTypeof(UnaryOperation* expr);
915 void VisitAdd(UnaryOperation* expr);
916 void VisitSub(UnaryOperation* expr);
917 void VisitBitNot(UnaryOperation* expr);
918 void VisitNot(UnaryOperation* expr);
919
920 void VisitComma(BinaryOperation* expr);
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000921 void VisitLogicalExpression(BinaryOperation* expr);
922 void VisitArithmeticExpression(BinaryOperation* expr);
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000923
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000924 bool PreProcessOsrEntry(IterationStatement* statement);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000925 // True iff. we are compiling for OSR and the statement is the entry.
926 bool HasOsrEntryAt(IterationStatement* statement);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000927 void VisitLoopBody(IterationStatement* stmt,
ager@chromium.org04921a82011-06-27 13:21:41 +0000928 HBasicBlock* loop_entry,
929 BreakAndContinueInfo* break_info);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000930
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000931 // Create a back edge in the flow graph. body_exit is the predecessor
932 // block and loop_entry is the successor block. loop_successor is the
933 // block where control flow exits the loop normally (e.g., via failure of
934 // the condition) and break_block is the block where control flow breaks
935 // from the loop. All blocks except loop_entry can be NULL. The return
936 // value is the new successor block which is the join of loop_successor
937 // and break_block, or NULL.
938 HBasicBlock* CreateLoop(IterationStatement* statement,
939 HBasicBlock* loop_entry,
940 HBasicBlock* body_exit,
941 HBasicBlock* loop_successor,
942 HBasicBlock* break_block);
943
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000944 HBasicBlock* JoinContinue(IterationStatement* statement,
945 HBasicBlock* exit_block,
946 HBasicBlock* continue_block);
947
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000948 HValue* Top() const { return environment()->Top(); }
949 void Drop(int n) { environment()->Drop(n); }
950 void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
951
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000952 // The value of the arguments object is allowed in some but not most value
953 // contexts. (It's allowed in all effect contexts and disallowed in all
954 // test contexts.)
955 void VisitForValue(Expression* expr,
956 ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000957 void VisitForTypeOf(Expression* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000958 void VisitForEffect(Expression* expr);
959 void VisitForControl(Expression* expr,
960 HBasicBlock* true_block,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000961 HBasicBlock* false_block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000962
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000963 // Visit an argument subexpression and emit a push to the outgoing
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000964 // arguments. Returns the hydrogen value that was pushed.
965 HValue* VisitArgument(Expression* expr);
966
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000967 void VisitArgumentList(ZoneList<Expression*>* arguments);
968
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000969 // Visit a list of expressions from left to right, each in a value context.
970 void VisitExpressions(ZoneList<Expression*>* exprs);
971
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000972 void AddPhi(HPhi* phi);
973
974 void PushAndAdd(HInstruction* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000975
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000976 // Remove the arguments from the bailout environment and emit instructions
977 // to push them as outgoing parameters.
ulan@chromium.org967e2702012-02-28 09:49:15 +0000978 template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000979
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000980 void TraceRepresentation(Token::Value op,
981 TypeInfo info,
982 HValue* value,
983 Representation rep);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000984 static Representation ToRepresentation(TypeInfo info);
985
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000986 void SetUpScope(Scope* scope);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000987 virtual void VisitStatements(ZoneList<Statement*>* statements);
988
989#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
990 AST_NODE_LIST(DECLARE_VISIT)
991#undef DECLARE_VISIT
992
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000993 HBasicBlock* CreateBasicBlock(HEnvironment* env);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000994 HBasicBlock* CreateLoopHeaderBlock();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000995
996 // Helpers for flow graph construction.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000997 enum GlobalPropertyAccess {
998 kUseCell,
999 kUseGeneric
1000 };
1001 GlobalPropertyAccess LookupGlobalProperty(Variable* var,
1002 LookupResult* lookup,
1003 bool is_store);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001004
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001005 void EnsureArgumentsArePushedForAccess();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001006 bool TryArgumentsAccess(Property* expr);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001007
1008 // Try to optimize fun.apply(receiver, arguments) pattern.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001009 bool TryCallApply(Call* expr);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001010
ulan@chromium.org967e2702012-02-28 09:49:15 +00001011 bool TryInline(CallKind call_kind,
1012 Handle<JSFunction> target,
1013 ZoneList<Expression*>* arguments,
1014 HValue* receiver,
1015 int ast_id,
1016 int return_id,
1017 ReturnHandlingFlag return_handling);
1018
1019 bool TryInlineCall(Call* expr, bool drop_extra = false);
1020 bool TryInlineConstruct(CallNew* expr, HValue* receiver);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001021 bool TryInlineBuiltinMethodCall(Call* expr,
ulan@chromium.org967e2702012-02-28 09:49:15 +00001022 HValue* receiver,
1023 Handle<Map> receiver_map,
1024 CheckType check_type);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001025 bool TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001026
1027 // If --trace-inlining, print a line of the inlining trace. Inlining
1028 // succeeded if the reason string is NULL and failed if there is a
1029 // non-NULL reason string.
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001030 void TraceInline(Handle<JSFunction> target,
1031 Handle<JSFunction> caller,
1032 const char* failure_reason);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001033
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001034 void HandleGlobalVariableAssignment(Variable* var,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001035 HValue* value,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001036 int position,
1037 int ast_id);
1038
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001039 void HandlePropertyAssignment(Assignment* expr);
1040 void HandleCompoundAssignment(Assignment* expr);
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001041 void HandlePolymorphicLoadNamedField(Property* expr,
1042 HValue* object,
1043 SmallMapList* types,
1044 Handle<String> name);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001045 void HandlePolymorphicStoreNamedField(Assignment* expr,
1046 HValue* object,
1047 HValue* value,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001048 SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001049 Handle<String> name);
1050 void HandlePolymorphicCallNamed(Call* expr,
1051 HValue* receiver,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001052 SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001053 Handle<String> name);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001054 void HandleLiteralCompareTypeof(CompareOperation* expr,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001055 HTypeof* typeof_expr,
ager@chromium.org04921a82011-06-27 13:21:41 +00001056 Handle<String> check);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001057 void HandleLiteralCompareNil(CompareOperation* expr,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001058 HValue* value,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001059 NilValue nil);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001060
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001061 HStringCharCodeAt* BuildStringCharCodeAt(HValue* context,
1062 HValue* string,
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001063 HValue* index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001064 HInstruction* BuildBinaryOperation(BinaryOperation* expr,
1065 HValue* left,
1066 HValue* right);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001067 HInstruction* BuildIncrement(bool returns_original_input,
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001068 CountOperation* expr);
whesse@chromium.org023421e2010-12-21 12:19:12 +00001069 HLoadNamedField* BuildLoadNamedField(HValue* object,
1070 Property* expr,
1071 Handle<Map> type,
1072 LookupResult* result,
1073 bool smi_and_map_check);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001074 HInstruction* BuildLoadNamedGeneric(HValue* object, Property* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001075 HInstruction* BuildLoadKeyedGeneric(HValue* object,
1076 HValue* key);
whesse@chromium.org7b260152011-06-20 15:33:18 +00001077 HInstruction* BuildExternalArrayElementAccess(
1078 HValue* external_elements,
1079 HValue* checked_key,
1080 HValue* val,
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001081 ElementsKind elements_kind,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001082 bool is_store);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001083 HInstruction* BuildFastElementAccess(HValue* elements,
1084 HValue* checked_key,
1085 HValue* val,
1086 ElementsKind elements_kind,
1087 bool is_store);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001088
whesse@chromium.org7b260152011-06-20 15:33:18 +00001089 HInstruction* BuildMonomorphicElementAccess(HValue* object,
1090 HValue* key,
1091 HValue* val,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001092 Handle<Map> map,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001093 bool is_store);
1094 HValue* HandlePolymorphicElementAccess(HValue* object,
1095 HValue* key,
1096 HValue* val,
1097 Expression* prop,
1098 int ast_id,
1099 int position,
1100 bool is_store,
1101 bool* has_side_effects);
1102
1103 HValue* HandleKeyedElementAccess(HValue* obj,
1104 HValue* key,
1105 HValue* val,
1106 Expression* expr,
1107 int ast_id,
1108 int position,
1109 bool is_store,
1110 bool* has_side_effects);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001111
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001112 HInstruction* BuildLoadNamed(HValue* object,
1113 Property* prop,
1114 Handle<Map> map,
1115 Handle<String> name);
1116 HInstruction* BuildStoreNamed(HValue* object,
1117 HValue* value,
1118 Expression* expr);
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +00001119 HInstruction* BuildStoreNamed(HValue* object,
1120 HValue* value,
1121 ObjectLiteral::Property* prop);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001122 HInstruction* BuildStoreNamedField(HValue* object,
1123 Handle<String> name,
1124 HValue* value,
1125 Handle<Map> type,
1126 LookupResult* lookup,
1127 bool smi_and_map_check);
1128 HInstruction* BuildStoreNamedGeneric(HValue* object,
1129 Handle<String> name,
1130 HValue* value);
1131 HInstruction* BuildStoreKeyedGeneric(HValue* object,
1132 HValue* key,
1133 HValue* value);
1134
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001135 HValue* BuildContextChainWalk(Variable* var);
1136
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001137 void AddCheckConstantFunction(Call* expr,
1138 HValue* receiver,
1139 Handle<Map> receiver_map,
1140 bool smi_and_map_check);
1141
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001142 Zone* zone() { return zone_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001143
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001144 // The translation state of the currently-being-translated function.
1145 FunctionState* function_state_;
1146
1147 // The base of the function state stack.
1148 FunctionState initial_function_state_;
1149
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001150 // Expression context of the currently visited subexpression. NULL when
1151 // visiting statements.
1152 AstContext* ast_context_;
1153
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001154 // A stack of breakable statements entered.
1155 BreakAndContinueScope* break_scope_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001156
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001157 HGraph* graph_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001158 HBasicBlock* current_block_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001159
1160 int inlined_count_;
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001161 ZoneList<Handle<Object> > globals_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001162
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001163 Zone* zone_;
1164
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001165 bool inline_bailout_;
1166
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001167 friend class FunctionState; // Pushes and pops the state stack.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001168 friend class AstContext; // Pushes and pops the AST context stack.
1169
1170 DISALLOW_COPY_AND_ASSIGN(HGraphBuilder);
1171};
1172
1173
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001174Zone* AstContext::zone() { return owner_->zone(); }
1175
1176
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001177class HValueMap: public ZoneObject {
1178 public:
1179 HValueMap()
1180 : array_size_(0),
1181 lists_size_(0),
1182 count_(0),
1183 present_flags_(0),
1184 array_(NULL),
1185 lists_(NULL),
1186 free_list_head_(kNil) {
1187 ResizeLists(kInitialSize);
1188 Resize(kInitialSize);
1189 }
1190
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001191 void Kill(GVNFlagSet flags);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001192
1193 void Add(HValue* value) {
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001194 present_flags_.Add(value->gvn_flags());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001195 Insert(value);
1196 }
1197
1198 HValue* Lookup(HValue* value) const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001199
1200 HValueMap* Copy(Zone* zone) const {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001201 return new(zone) HValueMap(zone, this);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001202 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001203
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001204 bool IsEmpty() const { return count_ == 0; }
1205
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001206 private:
1207 // A linked list of HValue* values. Stored in arrays.
1208 struct HValueMapListElement {
1209 HValue* value;
1210 int next; // Index in the array of the next list element.
1211 };
1212 static const int kNil = -1; // The end of a linked list
1213
1214 // Must be a power of 2.
1215 static const int kInitialSize = 16;
1216
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001217 HValueMap(Zone* zone, const HValueMap* other);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001218
1219 void Resize(int new_size);
1220 void ResizeLists(int new_size);
1221 void Insert(HValue* value);
1222 uint32_t Bound(uint32_t value) const { return value & (array_size_ - 1); }
1223
1224 int array_size_;
1225 int lists_size_;
1226 int count_; // The number of values stored in the HValueMap.
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001227 GVNFlagSet present_flags_; // All flags that are in any value in the
1228 // HValueMap.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001229 HValueMapListElement* array_; // Primary store - contains the first value
1230 // with a given hash. Colliding elements are stored in linked lists.
1231 HValueMapListElement* lists_; // The linked lists containing hash collisions.
1232 int free_list_head_; // Unused elements in lists_ are on the free list.
1233};
1234
1235
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001236class HSideEffectMap BASE_EMBEDDED {
1237 public:
1238 HSideEffectMap();
1239 explicit HSideEffectMap(HSideEffectMap* other);
1240
1241 void Kill(GVNFlagSet flags);
1242
1243 void Store(GVNFlagSet flags, HInstruction* instr);
1244
1245 bool IsEmpty() const { return count_ == 0; }
1246
1247 inline HInstruction* operator[](int i) const {
1248 ASSERT(0 <= i);
1249 ASSERT(i < kNumberOfTrackedSideEffects);
1250 return data_[i];
1251 }
1252 inline HInstruction* at(int i) const { return operator[](i); }
1253
1254 private:
1255 int count_;
1256 HInstruction* data_[kNumberOfTrackedSideEffects];
1257};
1258
1259
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001260class HStatistics: public Malloced {
1261 public:
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001262 void Initialize(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001263 void Print();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001264 void SaveTiming(const char* name, int64_t ticks, unsigned size);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001265 static HStatistics* Instance() {
1266 static SetOncePointer<HStatistics> instance;
1267 if (!instance.is_set()) {
1268 instance.set(new HStatistics());
1269 }
1270 return instance.get();
1271 }
1272
1273 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001274 HStatistics()
1275 : timing_(5),
1276 names_(5),
1277 sizes_(5),
1278 total_(0),
1279 total_size_(0),
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001280 full_code_gen_(0),
1281 source_size_(0) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001282
1283 List<int64_t> timing_;
1284 List<const char*> names_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001285 List<unsigned> sizes_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001286 int64_t total_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001287 unsigned total_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001288 int64_t full_code_gen_;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001289 double source_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001290};
1291
1292
1293class HPhase BASE_EMBEDDED {
1294 public:
1295 static const char* const kFullCodeGen;
1296 static const char* const kTotal;
1297
1298 explicit HPhase(const char* name) { Begin(name, NULL, NULL, NULL); }
1299 HPhase(const char* name, HGraph* graph) {
1300 Begin(name, graph, NULL, NULL);
1301 }
1302 HPhase(const char* name, LChunk* chunk) {
1303 Begin(name, NULL, chunk, NULL);
1304 }
1305 HPhase(const char* name, LAllocator* allocator) {
1306 Begin(name, NULL, NULL, allocator);
1307 }
1308
1309 ~HPhase() {
1310 End();
1311 }
1312
1313 private:
1314 void Begin(const char* name,
1315 HGraph* graph,
1316 LChunk* chunk,
1317 LAllocator* allocator);
1318 void End() const;
1319
1320 int64_t start_;
1321 const char* name_;
1322 HGraph* graph_;
1323 LChunk* chunk_;
1324 LAllocator* allocator_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001325 unsigned start_allocation_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001326};
1327
1328
1329class HTracer: public Malloced {
1330 public:
1331 void TraceCompilation(FunctionLiteral* function);
1332 void TraceHydrogen(const char* name, HGraph* graph);
1333 void TraceLithium(const char* name, LChunk* chunk);
1334 void TraceLiveRanges(const char* name, LAllocator* allocator);
1335
1336 static HTracer* Instance() {
1337 static SetOncePointer<HTracer> instance;
1338 if (!instance.is_set()) {
1339 instance.set(new HTracer("hydrogen.cfg"));
1340 }
1341 return instance.get();
1342 }
1343
1344 private:
1345 class Tag BASE_EMBEDDED {
1346 public:
1347 Tag(HTracer* tracer, const char* name) {
1348 name_ = name;
1349 tracer_ = tracer;
1350 tracer->PrintIndent();
1351 tracer->trace_.Add("begin_%s\n", name);
1352 tracer->indent_++;
1353 }
1354
1355 ~Tag() {
1356 tracer_->indent_--;
1357 tracer_->PrintIndent();
1358 tracer_->trace_.Add("end_%s\n", name_);
1359 ASSERT(tracer_->indent_ >= 0);
1360 tracer_->FlushToFile();
1361 }
1362
1363 private:
1364 HTracer* tracer_;
1365 const char* name_;
1366 };
1367
1368 explicit HTracer(const char* filename)
1369 : filename_(filename), trace_(&string_allocator_), indent_(0) {
1370 WriteChars(filename, "", 0, false);
1371 }
1372
1373 void TraceLiveRange(LiveRange* range, const char* type);
1374 void Trace(const char* name, HGraph* graph, LChunk* chunk);
1375 void FlushToFile();
1376
1377 void PrintEmptyProperty(const char* name) {
1378 PrintIndent();
1379 trace_.Add("%s\n", name);
1380 }
1381
1382 void PrintStringProperty(const char* name, const char* value) {
1383 PrintIndent();
1384 trace_.Add("%s \"%s\"\n", name, value);
1385 }
1386
1387 void PrintLongProperty(const char* name, int64_t value) {
1388 PrintIndent();
1389 trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
1390 }
1391
1392 void PrintBlockProperty(const char* name, int block_id) {
1393 PrintIndent();
1394 trace_.Add("%s \"B%d\"\n", name, block_id);
1395 }
1396
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001397 void PrintIntProperty(const char* name, int value) {
1398 PrintIndent();
1399 trace_.Add("%s %d\n", name, value);
1400 }
1401
1402 void PrintIndent() {
1403 for (int i = 0; i < indent_; i++) {
1404 trace_.Add(" ");
1405 }
1406 }
1407
1408 const char* filename_;
1409 HeapStringAllocator string_allocator_;
1410 StringStream trace_;
1411 int indent_;
1412};
1413
1414
1415} } // namespace v8::internal
1416
1417#endif // V8_HYDROGEN_H_