blob: 7442b5f6c0abe1c2787a23fdc51503d11b906fe7 [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"
37#include "zone.h"
danno@chromium.orgca29dd82013-04-26 11:59:48 +000038#include "scopes.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000039
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_; }
ulan@chromium.org750145a2013-03-07 15:14:13 +000064 Isolate* isolate() const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000065 const ZoneList<HPhi*>* phis() const { return &phis_; }
66 HInstruction* first() const { return first_; }
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +000067 HInstruction* last() const { return last_; }
68 void set_last(HInstruction* instr) { last_ = instr; }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000069 HInstruction* GetLastInstruction();
kasperl@chromium.orga5551262010-12-07 12:49:48 +000070 HControlInstruction* end() const { return end_; }
71 HLoopInformation* loop_information() const { return loop_information_; }
72 const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; }
73 bool HasPredecessor() const { return predecessors_.length() > 0; }
74 const ZoneList<HBasicBlock*>* dominated_blocks() const {
75 return &dominated_blocks_;
76 }
77 const ZoneList<int>* deleted_phis() const {
78 return &deleted_phis_;
79 }
80 void RecordDeletedPhi(int merge_index) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000081 deleted_phis_.Add(merge_index, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +000082 }
83 HBasicBlock* dominator() const { return dominator_; }
84 HEnvironment* last_environment() const { return last_environment_; }
85 int argument_count() const { return argument_count_; }
86 void set_argument_count(int count) { argument_count_ = count; }
87 int first_instruction_index() const { return first_instruction_index_; }
88 void set_first_instruction_index(int index) {
89 first_instruction_index_ = index;
90 }
91 int last_instruction_index() const { return last_instruction_index_; }
92 void set_last_instruction_index(int index) {
93 last_instruction_index_ = index;
94 }
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000095 bool is_osr_entry() { return is_osr_entry_; }
96 void set_osr_entry() { is_osr_entry_ = true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +000097
98 void AttachLoopInformation();
99 void DetachLoopInformation();
100 bool IsLoopHeader() const { return loop_information() != NULL; }
101 bool IsStartBlock() const { return block_id() == 0; }
102 void PostProcessLoopHeader(IterationStatement* stmt);
103
104 bool IsFinished() const { return end_ != NULL; }
105 void AddPhi(HPhi* phi);
106 void RemovePhi(HPhi* phi);
107 void AddInstruction(HInstruction* instr);
108 bool Dominates(HBasicBlock* other) const;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000109 int LoopNestingDepth() const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000110
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000111 void SetInitialEnvironment(HEnvironment* env);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000112 void ClearEnvironment() {
113 ASSERT(IsFinished());
114 ASSERT(end()->SuccessorCount() == 0);
115 last_environment_ = NULL;
116 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000117 bool HasEnvironment() const { return last_environment_ != NULL; }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000118 void UpdateEnvironment(HEnvironment* env);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000119 HBasicBlock* parent_loop_header() const { return parent_loop_header_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000120
121 void set_parent_loop_header(HBasicBlock* block) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000122 ASSERT(parent_loop_header_ == NULL);
123 parent_loop_header_ = block;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000124 }
125
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000126 bool HasParentLoopHeader() const { return parent_loop_header_ != NULL; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000127
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000128 void SetJoinId(BailoutId ast_id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000129
130 void Finish(HControlInstruction* last);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000131 void FinishExit(HControlInstruction* instruction);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000132 void Goto(HBasicBlock* block,
133 FunctionState* state = NULL,
134 bool add_simulate = true);
135 void GotoNoSimulate(HBasicBlock* block) {
136 Goto(block, NULL, false);
137 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000138
139 int PredecessorIndexOf(HBasicBlock* predecessor) const;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000140 void AddSimulate(BailoutId ast_id,
141 RemovableSimulate removable = FIXED_SIMULATE) {
142 AddInstruction(CreateSimulate(ast_id, removable));
143 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000144 void AssignCommonDominator(HBasicBlock* other);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000145 void AssignLoopSuccessorDominators();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000146
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000147 void FinishExitWithDeoptimization(HDeoptimize::UseEnvironment has_uses) {
148 FinishExit(CreateDeoptimize(has_uses));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000149 }
150
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000151 // Add the inlined function exit sequence, adding an HLeaveInlined
152 // instruction and updating the bailout environment.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000153 void AddLeaveInlined(HValue* return_value, FunctionState* state);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000154
155 // If a target block is tagged as an inline function return, all
156 // predecessors should contain the inlined exit sequence:
157 //
158 // LeaveInlined
159 // Simulate (caller's environment)
160 // Goto (target block)
161 bool IsInlineReturnTarget() const { return is_inline_return_target_; }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000162 void MarkAsInlineReturnTarget(HBasicBlock* inlined_entry_block) {
163 is_inline_return_target_ = true;
164 inlined_entry_block_ = inlined_entry_block;
165 }
166 HBasicBlock* inlined_entry_block() { return inlined_entry_block_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000167
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000168 bool IsDeoptimizing() const { return is_deoptimizing_; }
169 void MarkAsDeoptimizing() { is_deoptimizing_ = true; }
170
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000171 bool IsLoopSuccessorDominator() const {
172 return dominates_loop_successors_;
173 }
174 void MarkAsLoopSuccessorDominator() {
175 dominates_loop_successors_ = true;
176 }
177
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000178 inline Zone* zone() const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000179
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000180#ifdef DEBUG
181 void Verify();
182#endif
183
184 private:
185 void RegisterPredecessor(HBasicBlock* pred);
186 void AddDominatedBlock(HBasicBlock* block);
187
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000188 HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000189 HDeoptimize* CreateDeoptimize(HDeoptimize::UseEnvironment has_uses);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000190
191 int block_id_;
192 HGraph* graph_;
193 ZoneList<HPhi*> phis_;
194 HInstruction* first_;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000195 HInstruction* last_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000196 HControlInstruction* end_;
197 HLoopInformation* loop_information_;
198 ZoneList<HBasicBlock*> predecessors_;
199 HBasicBlock* dominator_;
200 ZoneList<HBasicBlock*> dominated_blocks_;
201 HEnvironment* last_environment_;
202 // Outgoing parameter count at block exit, set during lithium translation.
203 int argument_count_;
204 // Instruction indices into the lithium code stream.
205 int first_instruction_index_;
206 int last_instruction_index_;
207 ZoneList<int> deleted_phis_;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000208 HBasicBlock* parent_loop_header_;
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000209 // For blocks marked as inline return target: the block with HEnterInlined.
210 HBasicBlock* inlined_entry_block_;
211 bool is_inline_return_target_ : 1;
212 bool is_deoptimizing_ : 1;
213 bool dominates_loop_successors_ : 1;
214 bool is_osr_entry_ : 1;
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000215};
216
217
218class HPredecessorIterator BASE_EMBEDDED {
219 public:
220 explicit HPredecessorIterator(HBasicBlock* block)
221 : predecessor_list_(block->predecessors()), current_(0) { }
222
223 bool Done() { return current_ >= predecessor_list_->length(); }
224 HBasicBlock* Current() { return predecessor_list_->at(current_); }
225 void Advance() { current_++; }
226
227 private:
228 const ZoneList<HBasicBlock*>* predecessor_list_;
229 int current_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000230};
231
232
233class HLoopInformation: public ZoneObject {
234 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000235 HLoopInformation(HBasicBlock* loop_header, Zone* zone)
236 : back_edges_(4, zone),
ager@chromium.org04921a82011-06-27 13:21:41 +0000237 loop_header_(loop_header),
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000238 blocks_(8, zone),
ager@chromium.org04921a82011-06-27 13:21:41 +0000239 stack_check_(NULL) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000240 blocks_.Add(loop_header, zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000241 }
242 virtual ~HLoopInformation() {}
243
244 const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; }
245 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
246 HBasicBlock* loop_header() const { return loop_header_; }
247 HBasicBlock* GetLastBackEdge() const;
248 void RegisterBackEdge(HBasicBlock* block);
249
ager@chromium.org04921a82011-06-27 13:21:41 +0000250 HStackCheck* stack_check() const { return stack_check_; }
251 void set_stack_check(HStackCheck* stack_check) {
252 stack_check_ = stack_check;
253 }
254
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000255 private:
256 void AddBlock(HBasicBlock* block);
257
258 ZoneList<HBasicBlock*> back_edges_;
259 HBasicBlock* loop_header_;
260 ZoneList<HBasicBlock*> blocks_;
ager@chromium.org04921a82011-06-27 13:21:41 +0000261 HStackCheck* stack_check_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000262};
263
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000264
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000265class BoundsCheckTable;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000266class HGraph: public ZoneObject {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000267 public:
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000268 explicit HGraph(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000269
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000270 Isolate* isolate() const { return isolate_; }
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000271 Zone* zone() const { return zone_; }
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000272 CompilationInfo* info() const { return info_; }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000273
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000274 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
275 const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000276 HBasicBlock* entry_block() const { return entry_block_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000277 HEnvironment* start_environment() const { return start_environment_; }
278
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000279 void FinalizeUniqueValueIds();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000280 void InitializeInferredTypes();
281 void InsertTypeConversions();
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000282 void MergeRemovableSimulates();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000283 void InsertRepresentationChanges();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000284 void MarkDeoptimizeOnUndefined();
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000285 void ComputeMinusZeroChecks();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000286 void ComputeSafeUint32Operations();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000287 bool ProcessArgumentsObject();
288 void EliminateRedundantPhis();
289 void Canonicalize();
290 void OrderBlocks();
291 void AssignDominators();
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000292 void SetupInformativeDefinitions();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000293 void EliminateRedundantBoundsChecks();
ulan@chromium.org0e3f88b2012-05-22 09:16:05 +0000294 void DehoistSimpleArrayIndexComputations();
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000295 void RestoreActualValues();
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000296 void DeadCodeElimination(const char *phase_name);
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000297 void PropagateDeoptimizingMark();
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000298 void AnalyzeAndPruneEnvironmentLiveness();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000299
300 // Returns false if there are phi-uses of the arguments-object
301 // which are not supported by the optimizing compiler.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000302 bool CheckArgumentsPhiUses();
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +0000303
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000304 // Returns false if there are phi-uses of an uninitialized const
305 // which are not supported by the optimizing compiler.
306 bool CheckConstPhiUses();
307
308 void CollectPhis();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000309
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000310 void set_undefined_constant(HConstant* constant) {
311 undefined_constant_.set(constant);
312 }
313 HConstant* GetConstantUndefined() const { return undefined_constant_.get(); }
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000314 HConstant* GetConstant0();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000315 HConstant* GetConstant1();
316 HConstant* GetConstantMinus1();
317 HConstant* GetConstantTrue();
318 HConstant* GetConstantFalse();
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000319 HConstant* GetConstantHole();
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000320 HConstant* GetConstantNull();
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000321 HConstant* GetInvalidContext();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000322
323 HBasicBlock* CreateBasicBlock();
324 HArgumentsObject* GetArgumentsObject() const {
325 return arguments_object_.get();
326 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000327
328 void SetArgumentsObject(HArgumentsObject* object) {
329 arguments_object_.set(object);
330 }
331
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000332 int GetMaximumValueID() const { return values_.length(); }
333 int GetNextBlockID() { return next_block_id_++; }
334 int GetNextValueID(HValue* value) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000335 values_.Add(value, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000336 return values_.length() - 1;
337 }
338 HValue* LookupValue(int id) const {
339 if (id >= 0 && id < values_.length()) return values_[id];
340 return NULL;
341 }
342
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000343 bool Optimize(SmartArrayPointer<char>* bailout_reason);
344
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000345#ifdef DEBUG
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000346 void Verify(bool do_full_verify) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000347#endif
348
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000349 bool has_osr_loop_entry() {
350 return osr_loop_entry_.is_set();
351 }
352
353 HBasicBlock* osr_loop_entry() {
354 return osr_loop_entry_.get();
355 }
356
357 void set_osr_loop_entry(HBasicBlock* entry) {
358 osr_loop_entry_.set(entry);
359 }
360
361 ZoneList<HUnknownOSRValue*>* osr_values() {
362 return osr_values_.get();
363 }
364
365 void set_osr_values(ZoneList<HUnknownOSRValue*>* values) {
366 osr_values_.set(values);
367 }
368
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000369 int update_type_change_checksum(int delta) {
370 type_change_checksum_ += delta;
371 return type_change_checksum_;
372 }
373
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000374 void update_maximum_environment_size(int environment_size) {
375 if (environment_size > maximum_environment_size_) {
376 maximum_environment_size_ = environment_size;
377 }
378 }
379 int maximum_environment_size() { return maximum_environment_size_; }
380
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000381 bool use_optimistic_licm() {
382 return use_optimistic_licm_;
383 }
384
385 void set_use_optimistic_licm(bool value) {
386 use_optimistic_licm_ = value;
387 }
388
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000389 bool has_soft_deoptimize() {
390 return has_soft_deoptimize_;
391 }
392
393 void set_has_soft_deoptimize(bool value) {
394 has_soft_deoptimize_ = value;
395 }
396
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000397 void MarkRecursive() {
398 is_recursive_ = true;
399 }
400
401 bool is_recursive() const {
402 return is_recursive_;
403 }
404
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000405 void MarkDependsOnEmptyArrayProtoElements() {
danno@chromium.org41728482013-06-12 22:31:22 +0000406 // Add map dependency if not already added.
407 if (depends_on_empty_array_proto_elements_) return;
408 isolate()->initial_object_prototype()->map()->AddDependentCompilationInfo(
409 DependentCode::kElementsCantBeAddedGroup, info());
410 isolate()->initial_array_prototype()->map()->AddDependentCompilationInfo(
411 DependentCode::kElementsCantBeAddedGroup, info());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000412 depends_on_empty_array_proto_elements_ = true;
413 }
414
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000415 bool depends_on_empty_array_proto_elements() {
416 return depends_on_empty_array_proto_elements_;
417 }
418
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000419 void RecordUint32Instruction(HInstruction* instr) {
420 if (uint32_instructions_ == NULL) {
421 uint32_instructions_ = new(zone()) ZoneList<HInstruction*>(4, zone());
422 }
423 uint32_instructions_->Add(instr, zone());
424 }
425
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000426 private:
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +0000427 HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
428 int32_t integer_value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000429
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000430 template<class Phase>
431 void Run() {
432 Phase phase(this);
433 phase.Run();
434 }
435
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000436 void MarkLive(HValue* ref, HValue* instr, ZoneList<HValue*>* worklist);
437 void MarkLiveInstructions();
438 void RemoveDeadInstructions();
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000439 void MarkAsDeoptimizingRecursively(HBasicBlock* block);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000440 void NullifyUnreachableInstructions();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000441 void InsertTypeConversions(HInstruction* instr);
442 void PropagateMinusZeroChecks(HValue* value, BitVector* visited);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000443 void RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000444 void InsertRepresentationChangeForUse(HValue* value,
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000445 HValue* use_value,
446 int use_index,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000447 Representation to);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000448 void InsertRepresentationChangesForValue(HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000449 void InferTypes(ZoneList<HValue*>* worklist);
450 void InitializeInferredTypes(int from_inclusive, int to_inclusive);
451 void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000452 void SetupInformativeDefinitionsInBlock(HBasicBlock* block);
453 void SetupInformativeDefinitionsRecursively(HBasicBlock* block);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000454 void EliminateRedundantBoundsChecks(HBasicBlock* bb, BoundsCheckTable* table);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000455
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000456 Isolate* isolate_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000457 int next_block_id_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000458 HBasicBlock* entry_block_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000459 HEnvironment* start_environment_;
460 ZoneList<HBasicBlock*> blocks_;
461 ZoneList<HValue*> values_;
462 ZoneList<HPhi*>* phi_list_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000463 ZoneList<HInstruction*>* uint32_instructions_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000464 SetOncePointer<HConstant> undefined_constant_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000465 SetOncePointer<HConstant> constant_0_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000466 SetOncePointer<HConstant> constant_1_;
467 SetOncePointer<HConstant> constant_minus1_;
468 SetOncePointer<HConstant> constant_true_;
469 SetOncePointer<HConstant> constant_false_;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000470 SetOncePointer<HConstant> constant_the_hole_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000471 SetOncePointer<HConstant> constant_null_;
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000472 SetOncePointer<HConstant> constant_invalid_context_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000473 SetOncePointer<HArgumentsObject> arguments_object_;
474
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000475 SetOncePointer<HBasicBlock> osr_loop_entry_;
476 SetOncePointer<ZoneList<HUnknownOSRValue*> > osr_values_;
477
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000478 CompilationInfo* info_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000479 Zone* zone_;
480
481 bool is_recursive_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000482 bool use_optimistic_licm_;
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000483 bool has_soft_deoptimize_;
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000484 bool depends_on_empty_array_proto_elements_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000485 int type_change_checksum_;
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000486 int maximum_environment_size_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000487
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000488 DISALLOW_COPY_AND_ASSIGN(HGraph);
489};
490
491
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000492Zone* HBasicBlock::zone() const { return graph_->zone(); }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000493
494
ulan@chromium.org967e2702012-02-28 09:49:15 +0000495// Type of stack frame an environment might refer to.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000496enum FrameType {
497 JS_FUNCTION,
498 JS_CONSTRUCT,
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +0000499 JS_GETTER,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000500 JS_SETTER,
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000501 ARGUMENTS_ADAPTOR,
502 STUB
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000503};
ulan@chromium.org967e2702012-02-28 09:49:15 +0000504
505
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000506class HEnvironment: public ZoneObject {
507 public:
508 HEnvironment(HEnvironment* outer,
509 Scope* scope,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000510 Handle<JSFunction> closure,
511 Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000512
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000513 HEnvironment(Zone* zone, int parameter_count);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000514
ulan@chromium.org6ff65142012-03-21 09:52:17 +0000515 HEnvironment* arguments_environment() {
516 return outer()->frame_type() == ARGUMENTS_ADAPTOR ? outer() : this;
517 }
518
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000519 // Simple accessors.
520 Handle<JSFunction> closure() const { return closure_; }
521 const ZoneList<HValue*>* values() const { return &values_; }
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000522 const GrowableBitVector* assigned_variables() const {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000523 return &assigned_variables_;
524 }
ulan@chromium.org967e2702012-02-28 09:49:15 +0000525 FrameType frame_type() const { return frame_type_; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000526 int parameter_count() const { return parameter_count_; }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000527 int specials_count() const { return specials_count_; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000528 int local_count() const { return local_count_; }
529 HEnvironment* outer() const { return outer_; }
530 int pop_count() const { return pop_count_; }
531 int push_count() const { return push_count_; }
532
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000533 BailoutId ast_id() const { return ast_id_; }
534 void set_ast_id(BailoutId id) { ast_id_ = id; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000535
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000536 HEnterInlined* entry() const { return entry_; }
537 void set_entry(HEnterInlined* entry) { entry_ = entry; }
538
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000539 int length() const { return values_.length(); }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000540 bool is_special_index(int i) const {
541 return i >= parameter_count() && i < parameter_count() + specials_count();
542 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000543
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000544 int first_expression_index() const {
545 return parameter_count() + specials_count() + local_count();
546 }
547
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000548 int first_local_index() const {
549 return parameter_count() + specials_count();
550 }
551
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000552 void Bind(Variable* variable, HValue* value) {
553 Bind(IndexFor(variable), value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000554 }
555
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000556 void Bind(int index, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000557
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000558 void BindContext(HValue* value) {
559 Bind(parameter_count(), value);
560 }
561
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000562 HValue* Lookup(Variable* variable) const {
563 return Lookup(IndexFor(variable));
564 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000565
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000566 HValue* Lookup(int index) const {
567 HValue* result = values_[index];
568 ASSERT(result != NULL);
569 return result;
570 }
571
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000572 HValue* LookupContext() const {
573 // Return first special.
574 return Lookup(parameter_count());
575 }
576
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000577 void Push(HValue* value) {
578 ASSERT(value != NULL);
579 ++push_count_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000580 values_.Add(value, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000581 }
582
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000583 HValue* Pop() {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000584 ASSERT(!ExpressionStackIsEmpty());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000585 if (push_count_ > 0) {
586 --push_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000587 } else {
588 ++pop_count_;
589 }
590 return values_.RemoveLast();
591 }
592
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000593 void Drop(int count);
594
595 HValue* Top() const { return ExpressionStackAt(0); }
596
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000597 bool ExpressionStackIsEmpty() const;
598
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000599 HValue* ExpressionStackAt(int index_from_top) const {
600 int index = length() - index_from_top - 1;
601 ASSERT(HasExpressionAt(index));
602 return values_[index];
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000603 }
604
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000605 void SetExpressionStackAt(int index_from_top, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000606
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000607 HEnvironment* Copy() const;
608 HEnvironment* CopyWithoutHistory() const;
609 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const;
610
611 // Create an "inlined version" of this environment, where the original
612 // environment is the outer environment but the top expression stack
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000613 // elements are moved to an inner environment as parameters.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000614 HEnvironment* CopyForInlining(Handle<JSFunction> target,
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000615 int arguments,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000616 FunctionLiteral* function,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000617 HConstant* undefined,
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000618 InliningKind inlining_kind,
619 bool undefined_receiver) const;
620
621 static bool UseUndefinedReceiver(Handle<JSFunction> closure,
622 FunctionLiteral* function,
623 CallKind call_kind,
624 InliningKind inlining_kind) {
625 return (closure->shared()->native() || !function->is_classic_mode()) &&
626 call_kind == CALL_AS_FUNCTION && inlining_kind != CONSTRUCT_CALL_RETURN;
627 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000628
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000629 HEnvironment* DiscardInlined(bool drop_extra) {
630 HEnvironment* outer = outer_;
631 while (outer->frame_type() != JS_FUNCTION) outer = outer->outer_;
632 if (drop_extra) outer->Drop(1);
633 return outer;
634 }
635
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000636 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000637
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000638 void ClearHistory() {
639 pop_count_ = 0;
640 push_count_ = 0;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000641 assigned_variables_.Clear();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000642 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000643
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000644 void SetValueAt(int index, HValue* value) {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000645 ASSERT(index < length());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000646 values_[index] = value;
647 }
648
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000649 // Map a variable to an environment index. Parameter indices are shifted
650 // by 1 (receiver is parameter index -1 but environment index 0).
651 // Stack-allocated local indices are shifted by the number of parameters.
652 int IndexFor(Variable* variable) const {
653 ASSERT(variable->IsStackAllocated());
654 int shift = variable->IsParameter()
655 ? 1
656 : parameter_count_ + specials_count_;
657 return variable->index() + shift;
658 }
659
660 bool is_local_index(int i) const {
661 return i >= first_local_index() &&
662 i < first_expression_index();
663 }
664
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000665 void PrintTo(StringStream* stream);
666 void PrintToStd();
667
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000668 Zone* zone() const { return zone_; }
669
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000670 private:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000671 HEnvironment(const HEnvironment* other, Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000672
ulan@chromium.org967e2702012-02-28 09:49:15 +0000673 HEnvironment(HEnvironment* outer,
674 Handle<JSFunction> closure,
675 FrameType frame_type,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000676 int arguments,
677 Zone* zone);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000678
ulan@chromium.org967e2702012-02-28 09:49:15 +0000679 // Create an artificial stub environment (e.g. for argument adaptor or
680 // constructor stub).
681 HEnvironment* CreateStubEnvironment(HEnvironment* outer,
682 Handle<JSFunction> target,
683 FrameType frame_type,
684 int arguments) const;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000685
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000686 // True if index is included in the expression stack part of the environment.
687 bool HasExpressionAt(int index) const;
688
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000689 void Initialize(int parameter_count, int local_count, int stack_height);
690 void Initialize(const HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000691
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000692 Handle<JSFunction> closure_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000693 // Value array [parameters] [specials] [locals] [temporaries].
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000694 ZoneList<HValue*> values_;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000695 GrowableBitVector assigned_variables_;
ulan@chromium.org967e2702012-02-28 09:49:15 +0000696 FrameType frame_type_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000697 int parameter_count_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000698 int specials_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000699 int local_count_;
700 HEnvironment* outer_;
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000701 HEnterInlined* entry_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000702 int pop_count_;
703 int push_count_;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000704 BailoutId ast_id_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000705 Zone* zone_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000706};
707
708
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000709class HOptimizedGraphBuilder;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000710
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000711enum ArgumentsAllowedFlag {
712 ARGUMENTS_NOT_ALLOWED,
713 ARGUMENTS_ALLOWED
714};
715
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000716
717class HIfContinuation;
718
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000719// This class is not BASE_EMBEDDED because our inlining implementation uses
720// new and delete.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000721class AstContext {
722 public:
723 bool IsEffect() const { return kind_ == Expression::kEffect; }
724 bool IsValue() const { return kind_ == Expression::kValue; }
725 bool IsTest() const { return kind_ == Expression::kTest; }
726
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000727 // 'Fill' this context with a hydrogen value. The value is assumed to
728 // have already been inserted in the instruction stream (or not need to
729 // be, e.g., HPhi). Call this function in tail position in the Visit
730 // functions for expressions.
731 virtual void ReturnValue(HValue* value) = 0;
732
733 // Add a hydrogen instruction to the instruction stream (recording an
734 // environment simulation if necessary) and then fill this context with
735 // the instruction as value.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000736 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id) = 0;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000737
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000738 // Finishes the current basic block and materialize a boolean for
739 // value context, nothing for effect, generate a branch for test context.
740 // Call this function in tail position in the Visit functions for
741 // expressions.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000742 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id) = 0;
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000743
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000744 // Finishes the current basic block and materialize a boolean for
745 // value context, nothing for effect, generate a branch for test context.
746 // Call this function in tail position in the Visit functions for
747 // expressions that use an IfBuilder.
748 virtual void ReturnContinuation(HIfContinuation* continuation,
749 BailoutId ast_id) = 0;
750
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000751 void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; }
752 bool is_for_typeof() { return for_typeof_; }
753
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000754 protected:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000755 AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000756 virtual ~AstContext();
757
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000758 HOptimizedGraphBuilder* owner() const { return owner_; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000759
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000760 inline Zone* zone() const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000761
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000762 // We want to be able to assert, in a context-specific way, that the stack
763 // height makes sense when the context is filled.
764#ifdef DEBUG
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000765 int original_length_;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000766#endif
767
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000768 private:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000769 HOptimizedGraphBuilder* owner_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000770 Expression::Context kind_;
771 AstContext* outer_;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000772 bool for_typeof_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000773};
774
775
776class EffectContext: public AstContext {
777 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000778 explicit EffectContext(HOptimizedGraphBuilder* owner)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000779 : AstContext(owner, Expression::kEffect) {
780 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000781 virtual ~EffectContext();
782
783 virtual void ReturnValue(HValue* value);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000784 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id);
785 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000786 virtual void ReturnContinuation(HIfContinuation* continuation,
787 BailoutId ast_id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000788};
789
790
791class ValueContext: public AstContext {
792 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000793 ValueContext(HOptimizedGraphBuilder* owner, ArgumentsAllowedFlag flag)
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000794 : AstContext(owner, Expression::kValue), flag_(flag) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000795 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000796 virtual ~ValueContext();
797
798 virtual void ReturnValue(HValue* value);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000799 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id);
800 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000801 virtual void ReturnContinuation(HIfContinuation* continuation,
802 BailoutId ast_id);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000803
804 bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
805
806 private:
807 ArgumentsAllowedFlag flag_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000808};
809
810
811class TestContext: public AstContext {
812 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000813 TestContext(HOptimizedGraphBuilder* owner,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000814 Expression* condition,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000815 HBasicBlock* if_true,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000816 HBasicBlock* if_false)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000817 : AstContext(owner, Expression::kTest),
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000818 condition_(condition),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000819 if_true_(if_true),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000820 if_false_(if_false) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000821 }
822
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000823 virtual void ReturnValue(HValue* value);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000824 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id);
825 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000826 virtual void ReturnContinuation(HIfContinuation* continuation,
827 BailoutId ast_id);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000828
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000829 static TestContext* cast(AstContext* context) {
830 ASSERT(context->IsTest());
831 return reinterpret_cast<TestContext*>(context);
832 }
833
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000834 Expression* condition() const { return condition_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000835 HBasicBlock* if_true() const { return if_true_; }
836 HBasicBlock* if_false() const { return if_false_; }
837
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000838 private:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000839 // Build the shared core part of the translation unpacking a value into
840 // control flow.
841 void BuildBranch(HValue* value);
842
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000843 Expression* condition_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000844 HBasicBlock* if_true_;
845 HBasicBlock* if_false_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000846};
847
848
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000849class FunctionState {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000850 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000851 FunctionState(HOptimizedGraphBuilder* owner,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000852 CompilationInfo* info,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000853 InliningKind inlining_kind);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000854 ~FunctionState();
855
856 CompilationInfo* compilation_info() { return compilation_info_; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000857 AstContext* call_context() { return call_context_; }
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000858 InliningKind inlining_kind() const { return inlining_kind_; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000859 HBasicBlock* function_return() { return function_return_; }
860 TestContext* test_context() { return test_context_; }
861 void ClearInlinedTestContext() {
862 delete test_context_;
863 test_context_ = NULL;
864 }
865
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000866 FunctionState* outer() { return outer_; }
867
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000868 HEnterInlined* entry() { return entry_; }
869 void set_entry(HEnterInlined* entry) { entry_ = entry; }
870
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000871 HArgumentsObject* arguments_object() { return arguments_object_; }
872 void set_arguments_object(HArgumentsObject* arguments_object) {
873 arguments_object_ = arguments_object;
874 }
875
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000876 HArgumentsElements* arguments_elements() { return arguments_elements_; }
877 void set_arguments_elements(HArgumentsElements* arguments_elements) {
878 arguments_elements_ = arguments_elements;
879 }
880
881 bool arguments_pushed() { return arguments_elements() != NULL; }
882
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000883 private:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000884 HOptimizedGraphBuilder* owner_;
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000885
886 CompilationInfo* compilation_info_;
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000887
888 // During function inlining, expression context of the call being
889 // inlined. NULL when not inlining.
890 AstContext* call_context_;
891
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000892 // The kind of call which is currently being inlined.
893 InliningKind inlining_kind_;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000894
ulan@chromium.org967e2702012-02-28 09:49:15 +0000895 // When inlining in an effect or value context, this is the return block.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000896 // It is NULL otherwise. When inlining in a test context, there are a
897 // pair of return blocks in the context. When not inlining, there is no
898 // local return point.
899 HBasicBlock* function_return_;
900
901 // When inlining a call in a test context, a context containing a pair of
902 // return blocks. NULL in all other cases.
903 TestContext* test_context_;
904
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000905 // When inlining HEnterInlined instruction corresponding to the function
906 // entry.
907 HEnterInlined* entry_;
908
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000909 HArgumentsObject* arguments_object_;
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000910 HArgumentsElements* arguments_elements_;
911
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000912 FunctionState* outer_;
913};
914
915
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000916class HIfContinuation {
917 public:
918 HIfContinuation() { continuation_captured_ = false; }
919 ~HIfContinuation() { ASSERT(!continuation_captured_); }
920
921 void Capture(HBasicBlock* true_branch,
922 HBasicBlock* false_branch,
923 int position) {
924 ASSERT(!continuation_captured_);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000925 true_branch_ = true_branch;
926 false_branch_ = false_branch;
927 position_ = position;
928 continuation_captured_ = true;
929 }
930
931 void Continue(HBasicBlock** true_branch,
932 HBasicBlock** false_branch,
933 int* position) {
934 ASSERT(continuation_captured_);
935 *true_branch = true_branch_;
936 *false_branch = false_branch_;
937 if (position != NULL) *position = position_;
938 continuation_captured_ = false;
939 }
940
941 bool IsTrueReachable() { return true_branch_ != NULL; }
942 bool IsFalseReachable() { return false_branch_ != NULL; }
943 bool TrueAndFalseReachable() {
944 return IsTrueReachable() || IsFalseReachable();
945 }
946
947 bool continuation_captured_;
948 HBasicBlock* true_branch_;
949 HBasicBlock* false_branch_;
950 int position_;
951};
952
953
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000954class HGraphBuilder {
955 public:
956 explicit HGraphBuilder(CompilationInfo* info)
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000957 : info_(info),
958 graph_(NULL),
959 current_block_(NULL),
960 no_side_effects_scope_count_(0) {}
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000961 virtual ~HGraphBuilder() {}
962
963 HBasicBlock* current_block() const { return current_block_; }
964 void set_current_block(HBasicBlock* block) { current_block_ = block; }
965 HEnvironment* environment() const {
966 return current_block()->last_environment();
967 }
968 Zone* zone() const { return info_->zone(); }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000969 HGraph* graph() const { return graph_; }
970 Isolate* isolate() const { return graph_->isolate(); }
danno@chromium.org41728482013-06-12 22:31:22 +0000971 CompilationInfo* top_info() { return info_; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000972
973 HGraph* CreateGraph();
974
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000975 // Bailout environment manipulation.
976 void Push(HValue* value) { environment()->Push(value); }
977 HValue* Pop() { return environment()->Pop(); }
978
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000979 // Adding instructions.
980 HInstruction* AddInstruction(HInstruction* instr);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000981
982 template<class I>
983 I* Add() { return static_cast<I*>(AddInstruction(new(zone()) I())); }
984
985 template<class I, class P1>
986 I* Add(P1 p1) {
987 return static_cast<I*>(AddInstruction(new(zone()) I(p1)));
988 }
989
990 template<class I, class P1, class P2>
991 I* Add(P1 p1, P2 p2) {
992 return static_cast<I*>(AddInstruction(new(zone()) I(p1, p2)));
993 }
994
995 template<class I, class P1, class P2, class P3>
996 I* Add(P1 p1, P2 p2, P3 p3) {
997 return static_cast<I*>(AddInstruction(new(zone()) I(p1, p2, p3)));
998 }
999
1000 template<class I, class P1, class P2, class P3, class P4>
1001 I* Add(P1 p1, P2 p2, P3 p3, P4 p4) {
1002 return static_cast<I*>(AddInstruction(new(zone()) I(p1, p2, p3, p4)));
1003 }
1004
1005 template<class I, class P1, class P2, class P3, class P4, class P5>
1006 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1007 return static_cast<I*>(AddInstruction(new(zone()) I(p1, p2, p3, p4, p5)));
1008 }
1009
1010 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1011 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1012 return static_cast<I*>(AddInstruction(
1013 new(zone()) I(p1, p2, p3, p4, p5, p6)));
1014 }
1015
1016 template<class I, class P1, class P2, class P3,
1017 class P4, class P5, class P6, class P7>
1018 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1019 return static_cast<I*>(AddInstruction(
1020 new(zone()) I(p1, p2, p3, p4, p5, p6, p7)));
1021 }
1022
1023 template<class I, class P1, class P2, class P3, class P4,
1024 class P5, class P6, class P7, class P8>
1025 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
1026 return static_cast<I*>(AddInstruction(
1027 new(zone()) I(p1, p2, p3, p4, p5, p6, p7, p8)));
1028 }
1029
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001030 void AddSimulate(BailoutId id,
1031 RemovableSimulate removable = FIXED_SIMULATE);
1032
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001033 HReturn* AddReturn(HValue* value);
1034
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001035 void IncrementInNoSideEffectsScope() {
1036 no_side_effects_scope_count_++;
1037 }
1038
1039 void DecrementInNoSideEffectsScope() {
1040 no_side_effects_scope_count_--;
1041 }
1042
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001043 protected:
1044 virtual bool BuildGraph() = 0;
1045
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001046 HBasicBlock* CreateBasicBlock(HEnvironment* env);
1047 HBasicBlock* CreateLoopHeaderBlock();
1048
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001049 HValue* BuildCheckHeapObject(HValue* object);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001050 HValue* BuildCheckMap(HValue* obj, Handle<Map> map);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001051
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001052 // Building common constructs
1053 HInstruction* BuildExternalArrayElementAccess(
1054 HValue* external_elements,
1055 HValue* checked_key,
1056 HValue* val,
1057 HValue* dependency,
1058 ElementsKind elements_kind,
1059 bool is_store);
1060
1061 HInstruction* BuildFastElementAccess(
1062 HValue* elements,
1063 HValue* checked_key,
1064 HValue* val,
1065 HValue* dependency,
1066 ElementsKind elements_kind,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001067 bool is_store,
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001068 LoadKeyedHoleMode load_mode,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001069 KeyedAccessStoreMode store_mode);
1070
1071 HValue* BuildCheckForCapacityGrow(HValue* object,
1072 HValue* elements,
1073 ElementsKind kind,
1074 HValue* length,
1075 HValue* key,
1076 bool is_js_array);
1077
1078 HValue* BuildCopyElementsOnWrite(HValue* object,
1079 HValue* elements,
1080 ElementsKind kind,
1081 HValue* length);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001082
1083 HInstruction* BuildUncheckedMonomorphicElementAccess(
1084 HValue* object,
1085 HValue* key,
1086 HValue* val,
1087 HCheckMaps* mapcheck,
1088 bool is_js_array,
1089 ElementsKind elements_kind,
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00001090 bool is_store,
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001091 LoadKeyedHoleMode load_mode,
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001092 KeyedAccessStoreMode store_mode);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001093
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001094 HLoadNamedField* AddLoad(
1095 HValue *object,
1096 HObjectAccess access,
1097 HValue *typecheck = NULL,
1098 Representation representation = Representation::Tagged());
1099
1100 HLoadNamedField* BuildLoadNamedField(
1101 HValue* object,
1102 HObjectAccess access,
1103 Representation representation);
1104
1105 HStoreNamedField* AddStore(
1106 HValue *object,
1107 HObjectAccess access,
1108 HValue *val,
1109 Representation representation = Representation::Tagged());
1110
1111 HStoreNamedField* AddStoreMapConstant(HValue *object, Handle<Map>);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001112
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001113 HLoadNamedField* AddLoadElements(HValue *object, HValue *typecheck = NULL);
1114
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001115 class IfBuilder {
1116 public:
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001117 explicit IfBuilder(HGraphBuilder* builder,
1118 int position = RelocInfo::kNoPosition);
1119 IfBuilder(HGraphBuilder* builder,
1120 HIfContinuation* continuation);
1121
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001122 ~IfBuilder() {
1123 if (!finished_) End();
1124 }
1125
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001126 HInstruction* IfCompare(
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001127 HValue* left,
1128 HValue* right,
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001129 Token::Value token);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001130
1131 HInstruction* IfCompareMap(HValue* left, Handle<Map> map);
1132
1133 template<class Condition>
1134 HInstruction* If(HValue *p) {
1135 HControlInstruction* compare = new(zone()) Condition(p);
1136 AddCompare(compare);
1137 return compare;
1138 }
1139
1140 template<class Condition, class P2>
1141 HInstruction* If(HValue* p1, P2 p2) {
1142 HControlInstruction* compare = new(zone()) Condition(p1, p2);
1143 AddCompare(compare);
1144 return compare;
1145 }
1146
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00001147 template<class Condition, class P2>
1148 HInstruction* IfNot(HValue* p1, P2 p2) {
1149 HControlInstruction* compare = new(zone()) Condition(p1, p2);
1150 AddCompare(compare);
1151 HBasicBlock* block0 = compare->SuccessorAt(0);
1152 HBasicBlock* block1 = compare->SuccessorAt(1);
1153 compare->SetSuccessorAt(0, block1);
1154 compare->SetSuccessorAt(1, block0);
1155 return compare;
1156 }
1157
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001158 HInstruction* OrIfCompare(
1159 HValue* p1,
1160 HValue* p2,
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001161 Token::Value token) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001162 Or();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001163 return IfCompare(p1, p2, token);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001164 }
1165
1166 HInstruction* OrIfCompareMap(HValue* left, Handle<Map> map) {
1167 Or();
1168 return IfCompareMap(left, map);
1169 }
1170
1171 template<class Condition>
1172 HInstruction* OrIf(HValue *p) {
1173 Or();
1174 return If<Condition>(p);
1175 }
1176
1177 template<class Condition, class P2>
1178 HInstruction* OrIf(HValue* p1, P2 p2) {
1179 Or();
1180 return If<Condition>(p1, p2);
1181 }
1182
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001183 HInstruction* AndIfCompare(
1184 HValue* p1,
1185 HValue* p2,
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001186 Token::Value token) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001187 And();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001188 return IfCompare(p1, p2, token);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001189 }
1190
1191 HInstruction* AndIfCompareMap(HValue* left, Handle<Map> map) {
1192 And();
1193 return IfCompareMap(left, map);
1194 }
1195
1196 template<class Condition>
1197 HInstruction* AndIf(HValue *p) {
1198 And();
1199 return If<Condition>(p);
1200 }
1201
1202 template<class Condition, class P2>
1203 HInstruction* AndIf(HValue* p1, P2 p2) {
1204 And();
1205 return If<Condition>(p1, p2);
1206 }
1207
1208 void Or();
1209 void And();
1210
1211 void CaptureContinuation(HIfContinuation* continuation);
1212
1213 void Then();
1214 void Else();
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001215 void End();
1216
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001217 void Deopt();
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00001218 void ElseDeopt() {
1219 Else();
1220 Deopt();
1221 End();
1222 }
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001223
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001224 void Return(HValue* value);
1225
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001226 private:
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001227 void AddCompare(HControlInstruction* compare);
1228
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001229 Zone* zone() { return builder_->zone(); }
1230
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001231 HGraphBuilder* builder_;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001232 int position_;
1233 bool finished_ : 1;
1234 bool did_then_ : 1;
1235 bool did_else_ : 1;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001236 bool did_and_ : 1;
1237 bool did_or_ : 1;
1238 bool captured_ : 1;
1239 bool needs_compare_ : 1;
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001240 HBasicBlock* first_true_block_;
1241 HBasicBlock* last_true_block_;
1242 HBasicBlock* first_false_block_;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001243 HBasicBlock* split_edge_merge_block_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001244 HBasicBlock* merge_block_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001245 };
1246
1247 class LoopBuilder {
1248 public:
1249 enum Direction {
1250 kPreIncrement,
1251 kPostIncrement,
1252 kPreDecrement,
1253 kPostDecrement
1254 };
1255
1256 LoopBuilder(HGraphBuilder* builder,
1257 HValue* context,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001258 Direction direction);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001259 ~LoopBuilder() {
1260 ASSERT(finished_);
1261 }
1262
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001263 HValue* BeginBody(
1264 HValue* initial,
1265 HValue* terminating,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00001266 Token::Value token);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001267 void EndBody();
1268
1269 private:
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001270 Zone* zone() { return builder_->zone(); }
1271
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001272 HGraphBuilder* builder_;
1273 HValue* context_;
1274 HInstruction* increment_;
1275 HPhi* phi_;
1276 HBasicBlock* header_block_;
1277 HBasicBlock* body_block_;
1278 HBasicBlock* exit_block_;
1279 Direction direction_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001280 bool finished_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001281 };
1282
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001283 class NoObservableSideEffectsScope {
1284 public:
1285 explicit NoObservableSideEffectsScope(HGraphBuilder* builder) :
1286 builder_(builder) {
1287 builder_->IncrementInNoSideEffectsScope();
1288 }
1289 ~NoObservableSideEffectsScope() {
1290 builder_->DecrementInNoSideEffectsScope();
1291 }
1292
1293 private:
1294 HGraphBuilder* builder_;
1295 };
1296
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001297 HValue* BuildNewElementsCapacity(HValue* context,
1298 HValue* old_capacity);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001299
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001300 void BuildNewSpaceArrayCheck(HValue* length,
1301 ElementsKind kind);
1302
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001303 class JSArrayBuilder {
1304 public:
1305 JSArrayBuilder(HGraphBuilder* builder,
1306 ElementsKind kind,
1307 HValue* allocation_site_payload,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001308 HValue* constructor_function,
1309 AllocationSiteOverrideMode override_mode);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001310
1311 JSArrayBuilder(HGraphBuilder* builder,
1312 ElementsKind kind,
1313 HValue* constructor_function);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001314
1315 HValue* AllocateEmptyArray();
1316 HValue* AllocateArray(HValue* capacity, HValue* length_field,
1317 bool fill_with_hole);
1318 HValue* GetElementsLocation() { return elements_location_; }
1319
1320 private:
1321 Zone* zone() const { return builder_->zone(); }
1322 int elements_size() const {
1323 return IsFastDoubleElementsKind(kind_) ? kDoubleSize : kPointerSize;
1324 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001325 HGraphBuilder* builder() { return builder_; }
1326 HGraph* graph() { return builder_->graph(); }
1327 int initial_capacity() {
1328 STATIC_ASSERT(JSArray::kPreallocatedArrayElements > 0);
1329 return JSArray::kPreallocatedArrayElements;
1330 }
1331
1332 HValue* EmitMapCode(HValue* context);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001333 HValue* EmitInternalMapCode();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001334 HValue* EstablishEmptyArrayAllocationSize();
1335 HValue* EstablishAllocationSize(HValue* length_node);
1336 HValue* AllocateArray(HValue* size_in_bytes, HValue* capacity,
1337 HValue* length_field, bool fill_with_hole);
1338
1339 HGraphBuilder* builder_;
1340 ElementsKind kind_;
1341 AllocationSiteMode mode_;
1342 HValue* allocation_site_payload_;
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001343 HValue* constructor_function_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001344 HInnerAllocatedObject* elements_location_;
1345 };
1346
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001347 HValue* BuildAllocateElements(HValue* context,
1348 ElementsKind kind,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001349 HValue* capacity);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001350
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001351 void BuildInitializeElementsHeader(HValue* elements,
1352 ElementsKind kind,
1353 HValue* capacity);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001354
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001355 HValue* BuildAllocateElementsAndInitializeElementsHeader(HValue* context,
1356 ElementsKind kind,
1357 HValue* capacity);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001358
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001359 // array must have been allocated with enough room for
1360 // 1) the JSArray, 2) a AllocationSiteInfo if mode requires it,
1361 // 3) a FixedArray or FixedDoubleArray.
1362 // A pointer to the Fixed(Double)Array is returned.
1363 HInnerAllocatedObject* BuildJSArrayHeader(HValue* array,
1364 HValue* array_map,
1365 AllocationSiteMode mode,
1366 HValue* allocation_site_payload,
1367 HValue* length_field);
1368
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001369 HValue* BuildGrowElementsCapacity(HValue* object,
1370 HValue* elements,
1371 ElementsKind kind,
1372 HValue* length,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001373 HValue* new_capacity);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001374
1375 void BuildFillElementsWithHole(HValue* context,
1376 HValue* elements,
1377 ElementsKind elements_kind,
1378 HValue* from,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001379 HValue* to);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001380
1381 void BuildCopyElements(HValue* context,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001382 HValue* from_elements,
1383 ElementsKind from_elements_kind,
1384 HValue* to_elements,
1385 ElementsKind to_elements_kind,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001386 HValue* length,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001387 HValue* capacity);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001388
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001389 HValue* BuildCloneShallowArray(HContext* context,
1390 HValue* boilerplate,
1391 AllocationSiteMode mode,
1392 ElementsKind kind,
1393 int length);
1394
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001395 void BuildCompareNil(
1396 HValue* value,
danno@chromium.org41728482013-06-12 22:31:22 +00001397 Handle<Type> type,
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001398 int position,
1399 HIfContinuation* continuation);
1400
1401 HValue* BuildCreateAllocationSiteInfo(HValue* previous_object,
1402 int previous_object_size,
1403 HValue* payload);
1404
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001405 HInstruction* BuildGetNativeContext(HValue* context);
1406 HInstruction* BuildGetArrayFunction(HValue* context);
1407
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001408 private:
1409 HGraphBuilder();
1410 CompilationInfo* info_;
1411 HGraph* graph_;
1412 HBasicBlock* current_block_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001413 int no_side_effects_scope_count_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001414};
1415
1416
1417class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001418 public:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001419 // A class encapsulating (lazily-allocated) break and continue blocks for
1420 // a breakable statement. Separated from BreakAndContinueScope so that it
1421 // can have a separate lifetime.
1422 class BreakAndContinueInfo BASE_EMBEDDED {
1423 public:
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001424 explicit BreakAndContinueInfo(BreakableStatement* target,
1425 int drop_extra = 0)
1426 : target_(target),
1427 break_block_(NULL),
1428 continue_block_(NULL),
1429 drop_extra_(drop_extra) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001430 }
1431
1432 BreakableStatement* target() { return target_; }
1433 HBasicBlock* break_block() { return break_block_; }
1434 void set_break_block(HBasicBlock* block) { break_block_ = block; }
1435 HBasicBlock* continue_block() { return continue_block_; }
1436 void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001437 int drop_extra() { return drop_extra_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001438
1439 private:
1440 BreakableStatement* target_;
1441 HBasicBlock* break_block_;
1442 HBasicBlock* continue_block_;
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001443 int drop_extra_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001444 };
1445
1446 // A helper class to maintain a stack of current BreakAndContinueInfo
1447 // structures mirroring BreakableStatement nesting.
1448 class BreakAndContinueScope BASE_EMBEDDED {
1449 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001450 BreakAndContinueScope(BreakAndContinueInfo* info,
1451 HOptimizedGraphBuilder* owner)
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001452 : info_(info), owner_(owner), next_(owner->break_scope()) {
1453 owner->set_break_scope(this);
1454 }
1455
1456 ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
1457
1458 BreakAndContinueInfo* info() { return info_; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001459 HOptimizedGraphBuilder* owner() { return owner_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001460 BreakAndContinueScope* next() { return next_; }
1461
1462 // Search the break stack for a break or continue target.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001463 enum BreakType { BREAK, CONTINUE };
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001464 HBasicBlock* Get(BreakableStatement* stmt, BreakType type, int* drop_extra);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001465
1466 private:
1467 BreakAndContinueInfo* info_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001468 HOptimizedGraphBuilder* owner_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001469 BreakAndContinueScope* next_;
1470 };
1471
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001472 explicit HOptimizedGraphBuilder(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001473
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001474 virtual bool BuildGraph();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001475
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001476 // Simple accessors.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001477 BreakAndContinueScope* break_scope() const { return break_scope_; }
1478 void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001479
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001480 bool inline_bailout() { return inline_bailout_; }
1481
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00001482 void AddSoftDeoptimize();
1483
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001484 void Bailout(const char* reason);
1485
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001486 HBasicBlock* CreateJoin(HBasicBlock* first,
1487 HBasicBlock* second,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001488 BailoutId join_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001489
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001490 FunctionState* function_state() const { return function_state_; }
1491
yangguo@chromium.org56454712012-02-16 15:33:53 +00001492 void VisitDeclarations(ZoneList<Declaration*>* declarations);
1493
verwaest@chromium.org178fb152012-07-18 11:21:48 +00001494 void* operator new(size_t size, Zone* zone) {
1495 return zone->New(static_cast<int>(size));
1496 }
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001497 void operator delete(void* pointer, Zone* zone) { }
1498 void operator delete(void* pointer) { }
verwaest@chromium.org178fb152012-07-18 11:21:48 +00001499
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001500 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
1501
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001502 private:
1503 // Type of a member function that generates inline code for a native function.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001504 typedef void (HOptimizedGraphBuilder::*InlineFunctionGenerator)
1505 (CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001506
1507 // Forward declarations for inner scope classes.
1508 class SubgraphScope;
1509
1510 static const InlineFunctionGenerator kInlineFunctionGenerators[];
1511
1512 static const int kMaxCallPolymorphism = 4;
1513 static const int kMaxLoadPolymorphism = 4;
1514 static const int kMaxStorePolymorphism = 4;
1515
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001516 // Even in the 'unlimited' case we have to have some limit in order not to
1517 // overflow the stack.
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +00001518 static const int kUnlimitedMaxInlinedSourceSize = 100000;
1519 static const int kUnlimitedMaxInlinedNodes = 10000;
1520 static const int kUnlimitedMaxInlinedNodesCumulative = 10000;
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001521
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001522 // Maximum depth and total number of elements and properties for literal
1523 // graphs to be considered for fast deep-copying.
1524 static const int kMaxFastLiteralDepth = 3;
1525 static const int kMaxFastLiteralProperties = 8;
1526
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001527 // Simple accessors.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001528 void set_function_state(FunctionState* state) { function_state_ = state; }
1529
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001530 AstContext* ast_context() const { return ast_context_; }
1531 void set_ast_context(AstContext* context) { ast_context_ = context; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001532
1533 // Accessors forwarded to the function state.
danno@chromium.org41728482013-06-12 22:31:22 +00001534 CompilationInfo* current_info() const {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001535 return function_state()->compilation_info();
1536 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001537 AstContext* call_context() const {
1538 return function_state()->call_context();
1539 }
1540 HBasicBlock* function_return() const {
1541 return function_state()->function_return();
1542 }
1543 TestContext* inlined_test_context() const {
1544 return function_state()->test_context();
1545 }
1546 void ClearInlinedTestContext() {
1547 function_state()->ClearInlinedTestContext();
1548 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001549 StrictModeFlag function_strict_mode_flag() {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001550 return function_state()->compilation_info()->is_classic_mode()
1551 ? kNonStrictMode : kStrictMode;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001552 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001553
1554 // Generators for inline runtime functions.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001555#define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001556 void Generate##Name(CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001557
1558 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
1559 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
1560#undef INLINE_FUNCTION_GENERATOR_DECLARATION
1561
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001562 void VisitDelete(UnaryOperation* expr);
1563 void VisitVoid(UnaryOperation* expr);
1564 void VisitTypeof(UnaryOperation* expr);
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001565 void VisitSub(UnaryOperation* expr);
1566 void VisitBitNot(UnaryOperation* expr);
1567 void VisitNot(UnaryOperation* expr);
1568
1569 void VisitComma(BinaryOperation* expr);
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00001570 void VisitLogicalExpression(BinaryOperation* expr);
1571 void VisitArithmeticExpression(BinaryOperation* expr);
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001572
rossberg@chromium.org2c067b12012-03-19 11:01:52 +00001573 bool PreProcessOsrEntry(IterationStatement* statement);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001574 // True iff. we are compiling for OSR and the statement is the entry.
1575 bool HasOsrEntryAt(IterationStatement* statement);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001576 void VisitLoopBody(IterationStatement* stmt,
ager@chromium.org04921a82011-06-27 13:21:41 +00001577 HBasicBlock* loop_entry,
1578 BreakAndContinueInfo* break_info);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +00001579
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001580 // Create a back edge in the flow graph. body_exit is the predecessor
1581 // block and loop_entry is the successor block. loop_successor is the
1582 // block where control flow exits the loop normally (e.g., via failure of
1583 // the condition) and break_block is the block where control flow breaks
1584 // from the loop. All blocks except loop_entry can be NULL. The return
1585 // value is the new successor block which is the join of loop_successor
1586 // and break_block, or NULL.
1587 HBasicBlock* CreateLoop(IterationStatement* statement,
1588 HBasicBlock* loop_entry,
1589 HBasicBlock* body_exit,
1590 HBasicBlock* loop_successor,
1591 HBasicBlock* break_block);
1592
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +00001593 HBasicBlock* JoinContinue(IterationStatement* statement,
1594 HBasicBlock* exit_block,
1595 HBasicBlock* continue_block);
1596
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001597 HValue* Top() const { return environment()->Top(); }
1598 void Drop(int n) { environment()->Drop(n); }
1599 void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001600 bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var,
1601 int index,
1602 HValue* value,
1603 HEnvironment* env) {
1604 if (!FLAG_analyze_environment_liveness) return false;
1605 // |this| and |arguments| are always live; zapping parameters isn't
1606 // safe because function.arguments can inspect them at any time.
1607 return !var->is_this() &&
1608 !var->is_arguments() &&
1609 !value->IsArgumentsObject() &&
1610 env->is_local_index(index);
1611 }
1612 void BindIfLive(Variable* var, HValue* value) {
1613 HEnvironment* env = environment();
1614 int index = env->IndexFor(var);
1615 env->Bind(index, value);
1616 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
1617 HEnvironmentMarker* bind =
1618 new(zone()) HEnvironmentMarker(HEnvironmentMarker::BIND, index);
1619 AddInstruction(bind);
1620#ifdef DEBUG
1621 bind->set_closure(env->closure());
1622#endif
1623 }
1624 }
1625 HValue* LookupAndMakeLive(Variable* var) {
1626 HEnvironment* env = environment();
1627 int index = env->IndexFor(var);
1628 HValue* value = env->Lookup(index);
1629 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
1630 HEnvironmentMarker* lookup =
1631 new(zone()) HEnvironmentMarker(HEnvironmentMarker::LOOKUP, index);
1632 AddInstruction(lookup);
1633#ifdef DEBUG
1634 lookup->set_closure(env->closure());
1635#endif
1636 }
1637 return value;
1638 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001639
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001640 // The value of the arguments object is allowed in some but not most value
1641 // contexts. (It's allowed in all effect contexts and disallowed in all
1642 // test contexts.)
1643 void VisitForValue(Expression* expr,
1644 ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001645 void VisitForTypeOf(Expression* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001646 void VisitForEffect(Expression* expr);
1647 void VisitForControl(Expression* expr,
1648 HBasicBlock* true_block,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001649 HBasicBlock* false_block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001650
verwaest@chromium.org753aee42012-07-17 16:15:42 +00001651 // Visit an argument subexpression and emit a push to the outgoing arguments.
1652 void VisitArgument(Expression* expr);
vegorov@chromium.org3cf47312011-06-29 13:20:01 +00001653
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001654 void VisitArgumentList(ZoneList<Expression*>* arguments);
1655
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001656 // Visit a list of expressions from left to right, each in a value context.
1657 void VisitExpressions(ZoneList<Expression*>* exprs);
1658
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001659 void PushAndAdd(HInstruction* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001660
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001661 // Remove the arguments from the bailout environment and emit instructions
1662 // to push them as outgoing parameters.
ulan@chromium.org967e2702012-02-28 09:49:15 +00001663 template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001664
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001665 static Representation ToRepresentation(TypeInfo info);
danno@chromium.org41728482013-06-12 22:31:22 +00001666 static Representation ToRepresentation(Handle<Type> type);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001667
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001668 void SetUpScope(Scope* scope);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001669 virtual void VisitStatements(ZoneList<Statement*>* statements);
1670
1671#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
1672 AST_NODE_LIST(DECLARE_VISIT)
1673#undef DECLARE_VISIT
1674
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001675 // Helpers for flow graph construction.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001676 enum GlobalPropertyAccess {
1677 kUseCell,
1678 kUseGeneric
1679 };
1680 GlobalPropertyAccess LookupGlobalProperty(Variable* var,
1681 LookupResult* lookup,
1682 bool is_store);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001683
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001684 void EnsureArgumentsArePushedForAccess();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001685 bool TryArgumentsAccess(Property* expr);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001686
1687 // Try to optimize fun.apply(receiver, arguments) pattern.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001688 bool TryCallApply(Call* expr);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001689
jkummerow@chromium.org212d9642012-05-11 15:02:09 +00001690 int InliningAstSize(Handle<JSFunction> target);
ulan@chromium.org967e2702012-02-28 09:49:15 +00001691 bool TryInline(CallKind call_kind,
1692 Handle<JSFunction> target,
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001693 int arguments_count,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001694 HValue* implicit_return_value,
1695 BailoutId ast_id,
1696 BailoutId return_id,
1697 InliningKind inlining_kind);
ulan@chromium.org967e2702012-02-28 09:49:15 +00001698
1699 bool TryInlineCall(Call* expr, bool drop_extra = false);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001700 bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value);
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00001701 bool TryInlineGetter(Handle<JSFunction> getter, Property* prop);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001702 bool TryInlineSetter(Handle<JSFunction> setter,
danno@chromium.orgb0deb652013-06-20 16:20:19 +00001703 BailoutId id,
1704 BailoutId assignment_id,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001705 HValue* implicit_return_value);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +00001706 bool TryInlineApply(Handle<JSFunction> function,
1707 Call* expr,
1708 int arguments_count);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001709 bool TryInlineBuiltinMethodCall(Call* expr,
ulan@chromium.org967e2702012-02-28 09:49:15 +00001710 HValue* receiver,
1711 Handle<Map> receiver_map,
1712 CheckType check_type);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001713 bool TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001714
1715 // If --trace-inlining, print a line of the inlining trace. Inlining
1716 // succeeded if the reason string is NULL and failed if there is a
1717 // non-NULL reason string.
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001718 void TraceInline(Handle<JSFunction> target,
1719 Handle<JSFunction> caller,
1720 const char* failure_reason);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001721
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001722 void HandleGlobalVariableAssignment(Variable* var,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001723 HValue* value,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001724 int position,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001725 BailoutId ast_id);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001726
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001727 void HandlePropertyAssignment(Assignment* expr);
1728 void HandleCompoundAssignment(Assignment* expr);
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001729 void HandlePolymorphicLoadNamedField(Property* expr,
1730 HValue* object,
1731 SmallMapList* types,
1732 Handle<String> name);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001733 HInstruction* TryLoadPolymorphicAsMonomorphic(Property* expr,
1734 HValue* object,
1735 SmallMapList* types,
1736 Handle<String> name);
danno@chromium.orgb0deb652013-06-20 16:20:19 +00001737 void HandlePolymorphicStoreNamedField(BailoutId id,
1738 int position,
1739 BailoutId assignment_id,
danno@chromium.orgfe578672013-06-15 14:38:35 +00001740 HValue* object,
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001741 HValue* value,
danno@chromium.orgfe578672013-06-15 14:38:35 +00001742 SmallMapList* types,
1743 Handle<String> name);
danno@chromium.orgb0deb652013-06-20 16:20:19 +00001744 bool TryStorePolymorphicAsMonomorphic(int position,
1745 BailoutId assignment_id,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001746 HValue* object,
1747 HValue* value,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001748 SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001749 Handle<String> name);
1750 void HandlePolymorphicCallNamed(Call* expr,
1751 HValue* receiver,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001752 SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001753 Handle<String> name);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001754 void HandleLiteralCompareTypeof(CompareOperation* expr,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001755 HTypeof* typeof_expr,
ager@chromium.org04921a82011-06-27 13:21:41 +00001756 Handle<String> check);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001757 void HandleLiteralCompareNil(CompareOperation* expr,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001758 HValue* value,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001759 NilValue nil);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001760
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001761 HInstruction* BuildStringCharCodeAt(HValue* context,
1762 HValue* string,
1763 HValue* index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001764 HInstruction* BuildBinaryOperation(BinaryOperation* expr,
1765 HValue* left,
1766 HValue* right);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001767 HInstruction* BuildIncrement(bool returns_original_input,
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001768 CountOperation* expr);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001769 HInstruction* BuildLoadKeyedGeneric(HValue* object,
1770 HValue* key);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001771
mstarzinger@chromium.orgc6d9cee2012-07-03 10:03:19 +00001772 HInstruction* TryBuildConsolidatedElementLoad(HValue* object,
1773 HValue* key,
1774 HValue* val,
1775 SmallMapList* maps);
1776
whesse@chromium.org7b260152011-06-20 15:33:18 +00001777 HInstruction* BuildMonomorphicElementAccess(HValue* object,
1778 HValue* key,
1779 HValue* val,
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00001780 HValue* dependency,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001781 Handle<Map> map,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001782 bool is_store,
1783 KeyedAccessStoreMode store_mode);
mstarzinger@chromium.orgc6d9cee2012-07-03 10:03:19 +00001784
whesse@chromium.org7b260152011-06-20 15:33:18 +00001785 HValue* HandlePolymorphicElementAccess(HValue* object,
1786 HValue* key,
1787 HValue* val,
1788 Expression* prop,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001789 BailoutId ast_id,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001790 int position,
1791 bool is_store,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001792 KeyedAccessStoreMode store_mode,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001793 bool* has_side_effects);
1794
1795 HValue* HandleKeyedElementAccess(HValue* obj,
1796 HValue* key,
1797 HValue* val,
1798 Expression* expr,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001799 BailoutId ast_id,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001800 int position,
1801 bool is_store,
1802 bool* has_side_effects);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001803
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00001804 HInstruction* BuildLoadNamedGeneric(HValue* object,
1805 Handle<String> name,
1806 Property* expr);
verwaest@chromium.orgb6d052d2012-07-27 08:03:27 +00001807 HInstruction* BuildCallGetter(HValue* object,
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001808 Handle<Map> map,
verwaest@chromium.orgde64f722012-08-16 15:44:54 +00001809 Handle<JSFunction> getter,
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001810 Handle<JSObject> holder);
verwaest@chromium.orgb6d052d2012-07-27 08:03:27 +00001811 HInstruction* BuildLoadNamedMonomorphic(HValue* object,
1812 Handle<String> name,
1813 Property* expr,
1814 Handle<Map> map);
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00001815
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001816 void AddCheckMap(HValue* object, Handle<Map> map);
1817
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001818 void AddCheckMapsWithTransitions(HValue* object,
1819 Handle<Map> map);
1820
danno@chromium.orgb0deb652013-06-20 16:20:19 +00001821 void BuildStoreNamed(Expression* expression,
1822 BailoutId id,
1823 int position,
1824 BailoutId assignment_id,
1825 Property* prop,
1826 HValue* object,
1827 HValue* value);
1828
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001829 HInstruction* BuildStoreNamedField(HValue* object,
1830 Handle<String> name,
1831 HValue* value,
verwaest@chromium.orgb6d052d2012-07-27 08:03:27 +00001832 Handle<Map> map,
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001833 LookupResult* lookup);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001834 HInstruction* BuildStoreNamedGeneric(HValue* object,
1835 Handle<String> name,
1836 HValue* value);
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00001837 HInstruction* BuildCallSetter(HValue* object,
1838 HValue* value,
1839 Handle<Map> map,
verwaest@chromium.orgde64f722012-08-16 15:44:54 +00001840 Handle<JSFunction> setter,
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00001841 Handle<JSObject> holder);
1842 HInstruction* BuildStoreNamedMonomorphic(HValue* object,
1843 Handle<String> name,
1844 HValue* value,
1845 Handle<Map> map);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001846 HInstruction* BuildStoreKeyedGeneric(HValue* object,
1847 HValue* key,
1848 HValue* value);
1849
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001850 HValue* BuildContextChainWalk(Variable* var);
1851
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001852 HInstruction* BuildThisFunction();
1853
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001854 HInstruction* BuildFastLiteral(HValue* context,
1855 Handle<JSObject> boilerplate_object,
1856 Handle<JSObject> original_boilerplate_object,
1857 int data_size,
1858 int pointer_size,
1859 AllocationSiteMode mode);
1860
1861 void BuildEmitDeepCopy(Handle<JSObject> boilerplat_object,
1862 Handle<JSObject> object,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001863 HInstruction* target,
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001864 int* offset,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001865 HInstruction* data_target,
1866 int* data_offset,
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001867 AllocationSiteMode mode);
1868
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001869 MUST_USE_RESULT HValue* BuildEmitObjectHeader(
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001870 Handle<JSObject> boilerplat_object,
1871 HInstruction* target,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001872 HInstruction* data_target,
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001873 int object_offset,
1874 int elements_offset,
1875 int elements_size);
1876
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001877 void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object,
1878 Handle<JSObject> original_boilerplate_object,
1879 HValue* object_properties,
1880 HInstruction* target,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001881 int* offset,
1882 HInstruction* data_target,
1883 int* data_offset);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001884
1885 void BuildEmitElements(Handle<FixedArrayBase> elements,
1886 Handle<FixedArrayBase> original_elements,
1887 ElementsKind kind,
1888 HValue* object_elements,
1889 HInstruction* target,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001890 int* offset,
1891 HInstruction* data_target,
1892 int* data_offset);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001893
1894 void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements,
1895 ElementsKind kind,
1896 HValue* object_elements);
1897
1898 void BuildEmitFixedArray(Handle<FixedArrayBase> elements,
1899 Handle<FixedArrayBase> original_elements,
1900 ElementsKind kind,
1901 HValue* object_elements,
1902 HInstruction* target,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001903 int* offset,
1904 HInstruction* data_target,
1905 int* data_offset);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001906
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001907 void AddCheckPrototypeMaps(Handle<JSObject> holder,
1908 Handle<Map> receiver_map);
1909
yangguo@chromium.org99aa4902012-07-06 16:21:55 +00001910 void AddCheckConstantFunction(Handle<JSObject> holder,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001911 HValue* receiver,
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001912 Handle<Map> receiver_map);
1913
1914 bool MatchRotateRight(HValue* left,
1915 HValue* right,
1916 HValue** operand,
1917 HValue** shift_amount);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001918
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001919 // The translation state of the currently-being-translated function.
1920 FunctionState* function_state_;
1921
1922 // The base of the function state stack.
1923 FunctionState initial_function_state_;
1924
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001925 // Expression context of the currently visited subexpression. NULL when
1926 // visiting statements.
1927 AstContext* ast_context_;
1928
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001929 // A stack of breakable statements entered.
1930 BreakAndContinueScope* break_scope_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001931
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001932 int inlined_count_;
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001933 ZoneList<Handle<Object> > globals_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001934
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001935 bool inline_bailout_;
1936
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001937 friend class FunctionState; // Pushes and pops the state stack.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001938 friend class AstContext; // Pushes and pops the AST context stack.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001939 friend class KeyedLoadFastElementStub;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001940
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001941 DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001942};
1943
1944
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001945Zone* AstContext::zone() const { return owner_->zone(); }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001946
1947
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001948class HStatistics: public Malloced {
1949 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001950 HStatistics()
1951 : timing_(5),
1952 names_(5),
1953 sizes_(5),
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001954 create_graph_(0),
1955 optimize_graph_(0),
1956 generate_code_(0),
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001957 total_size_(0),
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001958 full_code_gen_(0),
1959 source_size_(0) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001960
ulan@chromium.org750145a2013-03-07 15:14:13 +00001961 void Initialize(CompilationInfo* info);
1962 void Print();
1963 void SaveTiming(const char* name, int64_t ticks, unsigned size);
1964
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001965 void IncrementFullCodeGen(int64_t full_code_gen) {
1966 full_code_gen_ += full_code_gen;
1967 }
1968
ulan@chromium.org750145a2013-03-07 15:14:13 +00001969 void IncrementSubtotals(int64_t create_graph,
1970 int64_t optimize_graph,
1971 int64_t generate_code) {
1972 create_graph_ += create_graph;
1973 optimize_graph_ += optimize_graph;
1974 generate_code_ += generate_code;
1975 }
1976
1977 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001978 List<int64_t> timing_;
1979 List<const char*> names_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001980 List<unsigned> sizes_;
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001981 int64_t create_graph_;
1982 int64_t optimize_graph_;
1983 int64_t generate_code_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001984 unsigned total_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001985 int64_t full_code_gen_;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001986 double source_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001987};
1988
1989
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001990class HPhase : public CompilationPhase {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001991 public:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001992 HPhase(const char* name, HGraph* graph)
1993 : CompilationPhase(name, graph->info()),
1994 graph_(graph) { }
ulan@chromium.org750145a2013-03-07 15:14:13 +00001995 ~HPhase();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001996
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001997 protected:
1998 HGraph* graph() const { return graph_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001999
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002000 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002001 HGraph* graph_;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002002
2003 DISALLOW_COPY_AND_ASSIGN(HPhase);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002004};
2005
2006
2007class HTracer: public Malloced {
2008 public:
ulan@chromium.org750145a2013-03-07 15:14:13 +00002009 explicit HTracer(int isolate_id)
2010 : trace_(&string_allocator_), indent_(0) {
2011 OS::SNPrintF(filename_,
2012 "hydrogen-%d-%d.cfg",
2013 OS::GetCurrentProcessId(),
2014 isolate_id);
2015 WriteChars(filename_.start(), "", 0, false);
2016 }
2017
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002018 void TraceCompilation(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002019 void TraceHydrogen(const char* name, HGraph* graph);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00002020 void TraceLithium(const char* name, LChunk* chunk);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002021 void TraceLiveRanges(const char* name, LAllocator* allocator);
2022
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002023 private:
2024 class Tag BASE_EMBEDDED {
2025 public:
2026 Tag(HTracer* tracer, const char* name) {
2027 name_ = name;
2028 tracer_ = tracer;
2029 tracer->PrintIndent();
2030 tracer->trace_.Add("begin_%s\n", name);
2031 tracer->indent_++;
2032 }
2033
2034 ~Tag() {
2035 tracer_->indent_--;
2036 tracer_->PrintIndent();
2037 tracer_->trace_.Add("end_%s\n", name_);
2038 ASSERT(tracer_->indent_ >= 0);
2039 tracer_->FlushToFile();
2040 }
2041
2042 private:
2043 HTracer* tracer_;
2044 const char* name_;
2045 };
2046
mmassi@chromium.org7028c052012-06-13 11:51:58 +00002047 void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00002048 void Trace(const char* name, HGraph* graph, LChunk* chunk);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002049 void FlushToFile();
2050
2051 void PrintEmptyProperty(const char* name) {
2052 PrintIndent();
2053 trace_.Add("%s\n", name);
2054 }
2055
2056 void PrintStringProperty(const char* name, const char* value) {
2057 PrintIndent();
2058 trace_.Add("%s \"%s\"\n", name, value);
2059 }
2060
2061 void PrintLongProperty(const char* name, int64_t value) {
2062 PrintIndent();
2063 trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
2064 }
2065
2066 void PrintBlockProperty(const char* name, int block_id) {
2067 PrintIndent();
2068 trace_.Add("%s \"B%d\"\n", name, block_id);
2069 }
2070
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002071 void PrintIntProperty(const char* name, int value) {
2072 PrintIndent();
2073 trace_.Add("%s %d\n", name, value);
2074 }
2075
2076 void PrintIndent() {
2077 for (int i = 0; i < indent_; i++) {
2078 trace_.Add(" ");
2079 }
2080 }
2081
ulan@chromium.org750145a2013-03-07 15:14:13 +00002082 EmbeddedVector<char, 64> filename_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002083 HeapStringAllocator string_allocator_;
2084 StringStream trace_;
2085 int indent_;
2086};
2087
2088
2089} } // namespace v8::internal
2090
2091#endif // V8_HYDROGEN_H_