blob: a95424a1c9e455ffa4a9664770844aee75b28b7d [file] [log] [blame]
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001// Copyright 2012 the V8 project authors. All rights reserved.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_HYDROGEN_H_
29#define V8_HYDROGEN_H_
30
31#include "v8.h"
32
lrn@chromium.org1c092762011-05-09 09:42:16 +000033#include "allocation.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000034#include "ast.h"
35#include "compiler.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000036#include "hydrogen-instructions.h"
vegorov@chromium.org7304bca2011-05-16 12:14:13 +000037#include "type-info.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000038#include "zone.h"
danno@chromium.orgca29dd82013-04-26 11:59:48 +000039#include "scopes.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000040
41namespace v8 {
42namespace internal {
43
44// Forward declarations.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000045class BitVector;
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000046class FunctionState;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000047class HEnvironment;
48class HGraph;
49class HLoopInformation;
50class HTracer;
51class LAllocator;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000052class LChunk;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000053class LiveRange;
54
55
56class HBasicBlock: public ZoneObject {
57 public:
58 explicit HBasicBlock(HGraph* graph);
59 virtual ~HBasicBlock() { }
60
61 // Simple accessors.
62 int block_id() const { return block_id_; }
63 void set_block_id(int id) { block_id_ = id; }
64 HGraph* graph() const { return graph_; }
ulan@chromium.org750145a2013-03-07 15:14:13 +000065 Isolate* isolate() const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000066 const ZoneList<HPhi*>* phis() const { return &phis_; }
67 HInstruction* first() const { return first_; }
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +000068 HInstruction* last() const { return last_; }
69 void set_last(HInstruction* instr) { last_ = instr; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +000070 HInstruction* GetLastInstruction();
71 HControlInstruction* end() const { return end_; }
72 HLoopInformation* loop_information() const { return loop_information_; }
73 const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; }
74 bool HasPredecessor() const { return predecessors_.length() > 0; }
75 const ZoneList<HBasicBlock*>* dominated_blocks() const {
76 return &dominated_blocks_;
77 }
78 const ZoneList<int>* deleted_phis() const {
79 return &deleted_phis_;
80 }
81 void RecordDeletedPhi(int merge_index) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000082 deleted_phis_.Add(merge_index, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +000083 }
84 HBasicBlock* dominator() const { return dominator_; }
85 HEnvironment* last_environment() const { return last_environment_; }
86 int argument_count() const { return argument_count_; }
87 void set_argument_count(int count) { argument_count_ = count; }
88 int first_instruction_index() const { return first_instruction_index_; }
89 void set_first_instruction_index(int index) {
90 first_instruction_index_ = index;
91 }
92 int last_instruction_index() const { return last_instruction_index_; }
93 void set_last_instruction_index(int index) {
94 last_instruction_index_ = index;
95 }
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000096 bool is_osr_entry() { return is_osr_entry_; }
97 void set_osr_entry() { is_osr_entry_ = true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +000098
99 void AttachLoopInformation();
100 void DetachLoopInformation();
101 bool IsLoopHeader() const { return loop_information() != NULL; }
102 bool IsStartBlock() const { return block_id() == 0; }
103 void PostProcessLoopHeader(IterationStatement* stmt);
104
105 bool IsFinished() const { return end_ != NULL; }
106 void AddPhi(HPhi* phi);
107 void RemovePhi(HPhi* phi);
108 void AddInstruction(HInstruction* instr);
109 bool Dominates(HBasicBlock* other) const;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000110 int LoopNestingDepth() const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000111
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000112 void SetInitialEnvironment(HEnvironment* env);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000113 void ClearEnvironment() { last_environment_ = NULL; }
114 bool HasEnvironment() const { return last_environment_ != NULL; }
115 void UpdateEnvironment(HEnvironment* env) { last_environment_ = env; }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000116 HBasicBlock* parent_loop_header() const { return parent_loop_header_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000117
118 void set_parent_loop_header(HBasicBlock* block) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000119 ASSERT(parent_loop_header_ == NULL);
120 parent_loop_header_ = block;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000121 }
122
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000123 bool HasParentLoopHeader() const { return parent_loop_header_ != NULL; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000124
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000125 void SetJoinId(BailoutId ast_id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000126
127 void Finish(HControlInstruction* last);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000128 void FinishExit(HControlInstruction* instruction);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000129 void Goto(HBasicBlock* block,
130 FunctionState* state = NULL,
131 bool add_simulate = true);
132 void GotoNoSimulate(HBasicBlock* block) {
133 Goto(block, NULL, false);
134 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000135
136 int PredecessorIndexOf(HBasicBlock* predecessor) const;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000137 void AddSimulate(BailoutId ast_id,
138 RemovableSimulate removable = FIXED_SIMULATE) {
139 AddInstruction(CreateSimulate(ast_id, removable));
140 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000141 void AssignCommonDominator(HBasicBlock* other);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000142 void AssignLoopSuccessorDominators();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000143
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000144 void FinishExitWithDeoptimization(HDeoptimize::UseEnvironment has_uses) {
145 FinishExit(CreateDeoptimize(has_uses));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000146 }
147
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000148 // Add the inlined function exit sequence, adding an HLeaveInlined
149 // instruction and updating the bailout environment.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000150 void AddLeaveInlined(HValue* return_value, FunctionState* state);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000151
152 // If a target block is tagged as an inline function return, all
153 // predecessors should contain the inlined exit sequence:
154 //
155 // LeaveInlined
156 // Simulate (caller's environment)
157 // Goto (target block)
158 bool IsInlineReturnTarget() const { return is_inline_return_target_; }
159 void MarkAsInlineReturnTarget() { is_inline_return_target_ = true; }
160
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000161 bool IsDeoptimizing() const { return is_deoptimizing_; }
162 void MarkAsDeoptimizing() { is_deoptimizing_ = true; }
163
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000164 bool IsLoopSuccessorDominator() const {
165 return dominates_loop_successors_;
166 }
167 void MarkAsLoopSuccessorDominator() {
168 dominates_loop_successors_ = true;
169 }
170
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000171 inline Zone* zone() const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000172
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000173#ifdef DEBUG
174 void Verify();
175#endif
176
177 private:
178 void RegisterPredecessor(HBasicBlock* pred);
179 void AddDominatedBlock(HBasicBlock* block);
180
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000181 HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000182 HDeoptimize* CreateDeoptimize(HDeoptimize::UseEnvironment has_uses);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000183
184 int block_id_;
185 HGraph* graph_;
186 ZoneList<HPhi*> phis_;
187 HInstruction* first_;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000188 HInstruction* last_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000189 HControlInstruction* end_;
190 HLoopInformation* loop_information_;
191 ZoneList<HBasicBlock*> predecessors_;
192 HBasicBlock* dominator_;
193 ZoneList<HBasicBlock*> dominated_blocks_;
194 HEnvironment* last_environment_;
195 // Outgoing parameter count at block exit, set during lithium translation.
196 int argument_count_;
197 // Instruction indices into the lithium code stream.
198 int first_instruction_index_;
199 int last_instruction_index_;
200 ZoneList<int> deleted_phis_;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000201 HBasicBlock* parent_loop_header_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000202 bool is_inline_return_target_;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000203 bool is_deoptimizing_;
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000204 bool dominates_loop_successors_;
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000205 bool is_osr_entry_;
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000206};
207
208
209class HPredecessorIterator BASE_EMBEDDED {
210 public:
211 explicit HPredecessorIterator(HBasicBlock* block)
212 : predecessor_list_(block->predecessors()), current_(0) { }
213
214 bool Done() { return current_ >= predecessor_list_->length(); }
215 HBasicBlock* Current() { return predecessor_list_->at(current_); }
216 void Advance() { current_++; }
217
218 private:
219 const ZoneList<HBasicBlock*>* predecessor_list_;
220 int current_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000221};
222
223
224class HLoopInformation: public ZoneObject {
225 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000226 HLoopInformation(HBasicBlock* loop_header, Zone* zone)
227 : back_edges_(4, zone),
ager@chromium.org04921a82011-06-27 13:21:41 +0000228 loop_header_(loop_header),
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000229 blocks_(8, zone),
ager@chromium.org04921a82011-06-27 13:21:41 +0000230 stack_check_(NULL) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000231 blocks_.Add(loop_header, zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000232 }
233 virtual ~HLoopInformation() {}
234
235 const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; }
236 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
237 HBasicBlock* loop_header() const { return loop_header_; }
238 HBasicBlock* GetLastBackEdge() const;
239 void RegisterBackEdge(HBasicBlock* block);
240
ager@chromium.org04921a82011-06-27 13:21:41 +0000241 HStackCheck* stack_check() const { return stack_check_; }
242 void set_stack_check(HStackCheck* stack_check) {
243 stack_check_ = stack_check;
244 }
245
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000246 private:
247 void AddBlock(HBasicBlock* block);
248
249 ZoneList<HBasicBlock*> back_edges_;
250 HBasicBlock* loop_header_;
251 ZoneList<HBasicBlock*> blocks_;
ager@chromium.org04921a82011-06-27 13:21:41 +0000252 HStackCheck* stack_check_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000253};
254
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000255class BoundsCheckTable;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000256class HGraph: public ZoneObject {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000257 public:
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000258 explicit HGraph(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000259
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000260 Isolate* isolate() const { return isolate_; }
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000261 Zone* zone() const { return zone_; }
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000262 CompilationInfo* info() const { return info_; }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000263
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000264 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
265 const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000266 HBasicBlock* entry_block() const { return entry_block_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000267 HEnvironment* start_environment() const { return start_environment_; }
268
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000269 void FinalizeUniqueValueIds();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000270 void InitializeInferredTypes();
271 void InsertTypeConversions();
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000272 void MergeRemovableSimulates();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000273 void InsertRepresentationChanges();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000274 void MarkDeoptimizeOnUndefined();
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000275 void ComputeMinusZeroChecks();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000276 void ComputeSafeUint32Operations();
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000277 void GlobalValueNumbering();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000278 bool ProcessArgumentsObject();
279 void EliminateRedundantPhis();
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000280 void EliminateUnreachablePhis();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000281 void Canonicalize();
282 void OrderBlocks();
283 void AssignDominators();
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000284 void SetupInformativeDefinitions();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000285 void EliminateRedundantBoundsChecks();
ulan@chromium.org0e3f88b2012-05-22 09:16:05 +0000286 void DehoistSimpleArrayIndexComputations();
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +0000287 void DeadCodeElimination();
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000288 void RestoreActualValues();
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000289 void PropagateDeoptimizingMark();
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000290 void EliminateUnusedInstructions();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000291
292 // Returns false if there are phi-uses of the arguments-object
293 // which are not supported by the optimizing compiler.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000294 bool CheckArgumentsPhiUses();
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +0000295
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000296 // Returns false if there are phi-uses of an uninitialized const
297 // which are not supported by the optimizing compiler.
298 bool CheckConstPhiUses();
299
300 void CollectPhis();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000301
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000302 void set_undefined_constant(HConstant* constant) {
303 undefined_constant_.set(constant);
304 }
305 HConstant* GetConstantUndefined() const { return undefined_constant_.get(); }
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000306 HConstant* GetConstant0();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000307 HConstant* GetConstant1();
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000308 HConstant* GetConstantSmi0();
309 HConstant* GetConstantSmi1();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000310 HConstant* GetConstantMinus1();
311 HConstant* GetConstantTrue();
312 HConstant* GetConstantFalse();
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000313 HConstant* GetConstantHole();
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000314 HConstant* GetConstantNull();
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000315 HConstant* GetInvalidContext();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000316
317 HBasicBlock* CreateBasicBlock();
318 HArgumentsObject* GetArgumentsObject() const {
319 return arguments_object_.get();
320 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000321
322 void SetArgumentsObject(HArgumentsObject* object) {
323 arguments_object_.set(object);
324 }
325
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000326 int GetMaximumValueID() const { return values_.length(); }
327 int GetNextBlockID() { return next_block_id_++; }
328 int GetNextValueID(HValue* value) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000329 values_.Add(value, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000330 return values_.length() - 1;
331 }
332 HValue* LookupValue(int id) const {
333 if (id >= 0 && id < values_.length()) return values_[id];
334 return NULL;
335 }
336
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000337 bool Optimize(SmartArrayPointer<char>* bailout_reason);
338
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000339#ifdef DEBUG
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000340 void Verify(bool do_full_verify) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000341#endif
342
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000343 bool has_osr_loop_entry() {
344 return osr_loop_entry_.is_set();
345 }
346
347 HBasicBlock* osr_loop_entry() {
348 return osr_loop_entry_.get();
349 }
350
351 void set_osr_loop_entry(HBasicBlock* entry) {
352 osr_loop_entry_.set(entry);
353 }
354
355 ZoneList<HUnknownOSRValue*>* osr_values() {
356 return osr_values_.get();
357 }
358
359 void set_osr_values(ZoneList<HUnknownOSRValue*>* values) {
360 osr_values_.set(values);
361 }
362
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000363 int update_type_change_checksum(int delta) {
364 type_change_checksum_ += delta;
365 return type_change_checksum_;
366 }
367
368 bool use_optimistic_licm() {
369 return use_optimistic_licm_;
370 }
371
372 void set_use_optimistic_licm(bool value) {
373 use_optimistic_licm_ = value;
374 }
375
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000376 bool has_soft_deoptimize() {
377 return has_soft_deoptimize_;
378 }
379
380 void set_has_soft_deoptimize(bool value) {
381 has_soft_deoptimize_ = value;
382 }
383
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000384 void MarkRecursive() {
385 is_recursive_ = true;
386 }
387
388 bool is_recursive() const {
389 return is_recursive_;
390 }
391
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000392 void RecordUint32Instruction(HInstruction* instr) {
393 if (uint32_instructions_ == NULL) {
394 uint32_instructions_ = new(zone()) ZoneList<HInstruction*>(4, zone());
395 }
396 uint32_instructions_->Add(instr, zone());
397 }
398
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000399 private:
rossberg@chromium.org657d53b2012-07-12 11:06:03 +0000400 HConstant* GetConstantInt32(SetOncePointer<HConstant>* pointer,
401 int32_t integer_value);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000402 HConstant* GetConstantSmi(SetOncePointer<HConstant>* pointer,
403 int32_t integer_value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000404
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000405 void MarkAsDeoptimizingRecursively(HBasicBlock* block);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000406 void NullifyUnreachableInstructions();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000407 void InsertTypeConversions(HInstruction* instr);
408 void PropagateMinusZeroChecks(HValue* value, BitVector* visited);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000409 void RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000410 void InsertRepresentationChangeForUse(HValue* value,
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000411 HValue* use_value,
412 int use_index,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000413 Representation to);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000414 void InsertRepresentationChangesForValue(HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000415 void InferTypes(ZoneList<HValue*>* worklist);
416 void InitializeInferredTypes(int from_inclusive, int to_inclusive);
417 void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000418 void SetupInformativeDefinitionsInBlock(HBasicBlock* block);
419 void SetupInformativeDefinitionsRecursively(HBasicBlock* block);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000420 void EliminateRedundantBoundsChecks(HBasicBlock* bb, BoundsCheckTable* table);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000421
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000422 Isolate* isolate_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000423 int next_block_id_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000424 HBasicBlock* entry_block_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000425 HEnvironment* start_environment_;
426 ZoneList<HBasicBlock*> blocks_;
427 ZoneList<HValue*> values_;
428 ZoneList<HPhi*>* phi_list_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000429 ZoneList<HInstruction*>* uint32_instructions_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000430 SetOncePointer<HConstant> undefined_constant_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000431 SetOncePointer<HConstant> constant_0_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000432 SetOncePointer<HConstant> constant_1_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000433 SetOncePointer<HConstant> constant_smi_0_;
434 SetOncePointer<HConstant> constant_smi_1_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000435 SetOncePointer<HConstant> constant_minus1_;
436 SetOncePointer<HConstant> constant_true_;
437 SetOncePointer<HConstant> constant_false_;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000438 SetOncePointer<HConstant> constant_the_hole_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000439 SetOncePointer<HConstant> constant_null_;
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000440 SetOncePointer<HConstant> constant_invalid_context_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000441 SetOncePointer<HArgumentsObject> arguments_object_;
442
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000443 SetOncePointer<HBasicBlock> osr_loop_entry_;
444 SetOncePointer<ZoneList<HUnknownOSRValue*> > osr_values_;
445
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000446 CompilationInfo* info_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000447 Zone* zone_;
448
449 bool is_recursive_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000450 bool use_optimistic_licm_;
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000451 bool has_soft_deoptimize_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000452 int type_change_checksum_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000453
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000454 DISALLOW_COPY_AND_ASSIGN(HGraph);
455};
456
457
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000458Zone* HBasicBlock::zone() const { return graph_->zone(); }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000459
460
ulan@chromium.org967e2702012-02-28 09:49:15 +0000461// Type of stack frame an environment might refer to.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000462enum FrameType {
463 JS_FUNCTION,
464 JS_CONSTRUCT,
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +0000465 JS_GETTER,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000466 JS_SETTER,
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000467 ARGUMENTS_ADAPTOR,
468 STUB
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000469};
ulan@chromium.org967e2702012-02-28 09:49:15 +0000470
471
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000472class HEnvironment: public ZoneObject {
473 public:
474 HEnvironment(HEnvironment* outer,
475 Scope* scope,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000476 Handle<JSFunction> closure,
477 Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000478
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000479 HEnvironment(Zone* zone, int parameter_count);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000480
ulan@chromium.org6ff65142012-03-21 09:52:17 +0000481 HEnvironment* arguments_environment() {
482 return outer()->frame_type() == ARGUMENTS_ADAPTOR ? outer() : this;
483 }
484
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000485 // Simple accessors.
486 Handle<JSFunction> closure() const { return closure_; }
487 const ZoneList<HValue*>* values() const { return &values_; }
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000488 const GrowableBitVector* assigned_variables() const {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000489 return &assigned_variables_;
490 }
ulan@chromium.org967e2702012-02-28 09:49:15 +0000491 FrameType frame_type() const { return frame_type_; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000492 int parameter_count() const { return parameter_count_; }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000493 int specials_count() const { return specials_count_; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000494 int local_count() const { return local_count_; }
495 HEnvironment* outer() const { return outer_; }
496 int pop_count() const { return pop_count_; }
497 int push_count() const { return push_count_; }
498
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000499 BailoutId ast_id() const { return ast_id_; }
500 void set_ast_id(BailoutId id) { ast_id_ = id; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000501
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000502 HEnterInlined* entry() const { return entry_; }
503 void set_entry(HEnterInlined* entry) { entry_ = entry; }
504
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000505 int length() const { return values_.length(); }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000506 bool is_special_index(int i) const {
507 return i >= parameter_count() && i < parameter_count() + specials_count();
508 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000509
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000510 int first_expression_index() const {
511 return parameter_count() + specials_count() + local_count();
512 }
513
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000514 void Bind(Variable* variable, HValue* value) {
515 Bind(IndexFor(variable), value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000516 }
517
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000518 void Bind(int index, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000519
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000520 void BindContext(HValue* value) {
521 Bind(parameter_count(), value);
522 }
523
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000524 HValue* Lookup(Variable* variable) const {
525 return Lookup(IndexFor(variable));
526 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000527
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000528 HValue* Lookup(int index) const {
529 HValue* result = values_[index];
530 ASSERT(result != NULL);
531 return result;
532 }
533
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000534 HValue* LookupContext() const {
535 // Return first special.
536 return Lookup(parameter_count());
537 }
538
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000539 void Push(HValue* value) {
540 ASSERT(value != NULL);
541 ++push_count_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000542 values_.Add(value, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000543 }
544
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000545 HValue* Pop() {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000546 ASSERT(!ExpressionStackIsEmpty());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000547 if (push_count_ > 0) {
548 --push_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000549 } else {
550 ++pop_count_;
551 }
552 return values_.RemoveLast();
553 }
554
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000555 void Drop(int count);
556
557 HValue* Top() const { return ExpressionStackAt(0); }
558
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000559 bool ExpressionStackIsEmpty() const;
560
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000561 HValue* ExpressionStackAt(int index_from_top) const {
562 int index = length() - index_from_top - 1;
563 ASSERT(HasExpressionAt(index));
564 return values_[index];
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000565 }
566
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000567 void SetExpressionStackAt(int index_from_top, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000568
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000569 HEnvironment* Copy() const;
570 HEnvironment* CopyWithoutHistory() const;
571 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const;
572
573 // Create an "inlined version" of this environment, where the original
574 // environment is the outer environment but the top expression stack
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000575 // elements are moved to an inner environment as parameters.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000576 HEnvironment* CopyForInlining(Handle<JSFunction> target,
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000577 int arguments,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000578 FunctionLiteral* function,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000579 HConstant* undefined,
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000580 InliningKind inlining_kind,
581 bool undefined_receiver) const;
582
583 static bool UseUndefinedReceiver(Handle<JSFunction> closure,
584 FunctionLiteral* function,
585 CallKind call_kind,
586 InliningKind inlining_kind) {
587 return (closure->shared()->native() || !function->is_classic_mode()) &&
588 call_kind == CALL_AS_FUNCTION && inlining_kind != CONSTRUCT_CALL_RETURN;
589 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000590
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000591 HEnvironment* DiscardInlined(bool drop_extra) {
592 HEnvironment* outer = outer_;
593 while (outer->frame_type() != JS_FUNCTION) outer = outer->outer_;
594 if (drop_extra) outer->Drop(1);
595 return outer;
596 }
597
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000598 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000599
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000600 void ClearHistory() {
601 pop_count_ = 0;
602 push_count_ = 0;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000603 assigned_variables_.Clear();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000604 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000605
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000606 void SetValueAt(int index, HValue* value) {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000607 ASSERT(index < length());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000608 values_[index] = value;
609 }
610
611 void PrintTo(StringStream* stream);
612 void PrintToStd();
613
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000614 Zone* zone() const { return zone_; }
615
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000616 private:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000617 HEnvironment(const HEnvironment* other, Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000618
ulan@chromium.org967e2702012-02-28 09:49:15 +0000619 HEnvironment(HEnvironment* outer,
620 Handle<JSFunction> closure,
621 FrameType frame_type,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000622 int arguments,
623 Zone* zone);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000624
ulan@chromium.org967e2702012-02-28 09:49:15 +0000625 // Create an artificial stub environment (e.g. for argument adaptor or
626 // constructor stub).
627 HEnvironment* CreateStubEnvironment(HEnvironment* outer,
628 Handle<JSFunction> target,
629 FrameType frame_type,
630 int arguments) const;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000631
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000632 // True if index is included in the expression stack part of the environment.
633 bool HasExpressionAt(int index) const;
634
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000635 void Initialize(int parameter_count, int local_count, int stack_height);
636 void Initialize(const HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000637
638 // Map a variable to an environment index. Parameter indices are shifted
639 // by 1 (receiver is parameter index -1 but environment index 0).
640 // Stack-allocated local indices are shifted by the number of parameters.
641 int IndexFor(Variable* variable) const {
jkummerow@chromium.org486075a2011-09-07 12:44:28 +0000642 ASSERT(variable->IsStackAllocated());
643 int shift = variable->IsParameter()
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000644 ? 1
645 : parameter_count_ + specials_count_;
jkummerow@chromium.org486075a2011-09-07 12:44:28 +0000646 return variable->index() + shift;
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000647 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000648
649 Handle<JSFunction> closure_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000650 // Value array [parameters] [specials] [locals] [temporaries].
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000651 ZoneList<HValue*> values_;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000652 GrowableBitVector assigned_variables_;
ulan@chromium.org967e2702012-02-28 09:49:15 +0000653 FrameType frame_type_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000654 int parameter_count_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000655 int specials_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000656 int local_count_;
657 HEnvironment* outer_;
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000658 HEnterInlined* entry_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000659 int pop_count_;
660 int push_count_;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000661 BailoutId ast_id_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000662 Zone* zone_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000663};
664
665
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000666class HInferRepresentation BASE_EMBEDDED {
667 public:
668 explicit HInferRepresentation(HGraph* graph)
669 : graph_(graph),
670 worklist_(8, graph->zone()),
671 in_worklist_(graph->GetMaximumValueID(), graph->zone()) { }
672
673 void Analyze();
674 void AddToWorklist(HValue* current);
675
676 private:
677 Zone* zone() const { return graph_->zone(); }
678
679 HGraph* graph_;
680 ZoneList<HValue*> worklist_;
681 BitVector in_worklist_;
682};
683
684
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000685class HOptimizedGraphBuilder;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000686
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000687enum ArgumentsAllowedFlag {
688 ARGUMENTS_NOT_ALLOWED,
689 ARGUMENTS_ALLOWED
690};
691
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000692
693class HIfContinuation;
694
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000695// This class is not BASE_EMBEDDED because our inlining implementation uses
696// new and delete.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000697class AstContext {
698 public:
699 bool IsEffect() const { return kind_ == Expression::kEffect; }
700 bool IsValue() const { return kind_ == Expression::kValue; }
701 bool IsTest() const { return kind_ == Expression::kTest; }
702
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000703 // 'Fill' this context with a hydrogen value. The value is assumed to
704 // have already been inserted in the instruction stream (or not need to
705 // be, e.g., HPhi). Call this function in tail position in the Visit
706 // functions for expressions.
707 virtual void ReturnValue(HValue* value) = 0;
708
709 // Add a hydrogen instruction to the instruction stream (recording an
710 // environment simulation if necessary) and then fill this context with
711 // the instruction as value.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000712 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id) = 0;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000713
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000714 // Finishes the current basic block and materialize a boolean for
715 // value context, nothing for effect, generate a branch for test context.
716 // Call this function in tail position in the Visit functions for
717 // expressions.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000718 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id) = 0;
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000719
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000720 // Finishes the current basic block and materialize a boolean for
721 // value context, nothing for effect, generate a branch for test context.
722 // Call this function in tail position in the Visit functions for
723 // expressions that use an IfBuilder.
724 virtual void ReturnContinuation(HIfContinuation* continuation,
725 BailoutId ast_id) = 0;
726
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000727 void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; }
728 bool is_for_typeof() { return for_typeof_; }
729
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000730 protected:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000731 AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000732 virtual ~AstContext();
733
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000734 HOptimizedGraphBuilder* owner() const { return owner_; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000735
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000736 inline Zone* zone() const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000737
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000738 // We want to be able to assert, in a context-specific way, that the stack
739 // height makes sense when the context is filled.
740#ifdef DEBUG
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000741 int original_length_;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000742#endif
743
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000744 private:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000745 HOptimizedGraphBuilder* owner_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000746 Expression::Context kind_;
747 AstContext* outer_;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000748 bool for_typeof_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000749};
750
751
752class EffectContext: public AstContext {
753 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000754 explicit EffectContext(HOptimizedGraphBuilder* owner)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000755 : AstContext(owner, Expression::kEffect) {
756 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000757 virtual ~EffectContext();
758
759 virtual void ReturnValue(HValue* value);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000760 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id);
761 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000762 virtual void ReturnContinuation(HIfContinuation* continuation,
763 BailoutId ast_id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000764};
765
766
767class ValueContext: public AstContext {
768 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000769 ValueContext(HOptimizedGraphBuilder* owner, ArgumentsAllowedFlag flag)
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000770 : AstContext(owner, Expression::kValue), flag_(flag) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000771 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000772 virtual ~ValueContext();
773
774 virtual void ReturnValue(HValue* value);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000775 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id);
776 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000777 virtual void ReturnContinuation(HIfContinuation* continuation,
778 BailoutId ast_id);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000779
780 bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
781
782 private:
783 ArgumentsAllowedFlag flag_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000784};
785
786
787class TestContext: public AstContext {
788 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000789 TestContext(HOptimizedGraphBuilder* owner,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000790 Expression* condition,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000791 TypeFeedbackOracle* oracle,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000792 HBasicBlock* if_true,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000793 HBasicBlock* if_false)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000794 : AstContext(owner, Expression::kTest),
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000795 condition_(condition),
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000796 oracle_(oracle),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000797 if_true_(if_true),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000798 if_false_(if_false) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000799 }
800
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000801 virtual void ReturnValue(HValue* value);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000802 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id);
803 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000804 virtual void ReturnContinuation(HIfContinuation* continuation,
805 BailoutId ast_id);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000806
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000807 static TestContext* cast(AstContext* context) {
808 ASSERT(context->IsTest());
809 return reinterpret_cast<TestContext*>(context);
810 }
811
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000812 Expression* condition() const { return condition_; }
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000813 TypeFeedbackOracle* oracle() const { return oracle_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000814 HBasicBlock* if_true() const { return if_true_; }
815 HBasicBlock* if_false() const { return if_false_; }
816
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000817 private:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000818 // Build the shared core part of the translation unpacking a value into
819 // control flow.
820 void BuildBranch(HValue* value);
821
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000822 Expression* condition_;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000823 TypeFeedbackOracle* oracle_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000824 HBasicBlock* if_true_;
825 HBasicBlock* if_false_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000826};
827
828
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000829class FunctionState {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000830 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000831 FunctionState(HOptimizedGraphBuilder* owner,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000832 CompilationInfo* info,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000833 TypeFeedbackOracle* oracle,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000834 InliningKind inlining_kind);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000835 ~FunctionState();
836
837 CompilationInfo* compilation_info() { return compilation_info_; }
838 TypeFeedbackOracle* oracle() { return oracle_; }
839 AstContext* call_context() { return call_context_; }
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000840 InliningKind inlining_kind() const { return inlining_kind_; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000841 HBasicBlock* function_return() { return function_return_; }
842 TestContext* test_context() { return test_context_; }
843 void ClearInlinedTestContext() {
844 delete test_context_;
845 test_context_ = NULL;
846 }
847
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000848 FunctionState* outer() { return outer_; }
849
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000850 HEnterInlined* entry() { return entry_; }
851 void set_entry(HEnterInlined* entry) { entry_ = entry; }
852
853 HArgumentsElements* arguments_elements() { return arguments_elements_; }
854 void set_arguments_elements(HArgumentsElements* arguments_elements) {
855 arguments_elements_ = arguments_elements;
856 }
857
858 bool arguments_pushed() { return arguments_elements() != NULL; }
859
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000860 private:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000861 HOptimizedGraphBuilder* owner_;
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000862
863 CompilationInfo* compilation_info_;
864 TypeFeedbackOracle* oracle_;
865
866 // During function inlining, expression context of the call being
867 // inlined. NULL when not inlining.
868 AstContext* call_context_;
869
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000870 // The kind of call which is currently being inlined.
871 InliningKind inlining_kind_;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000872
ulan@chromium.org967e2702012-02-28 09:49:15 +0000873 // When inlining in an effect or value context, this is the return block.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000874 // It is NULL otherwise. When inlining in a test context, there are a
875 // pair of return blocks in the context. When not inlining, there is no
876 // local return point.
877 HBasicBlock* function_return_;
878
879 // When inlining a call in a test context, a context containing a pair of
880 // return blocks. NULL in all other cases.
881 TestContext* test_context_;
882
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000883 // When inlining HEnterInlined instruction corresponding to the function
884 // entry.
885 HEnterInlined* entry_;
886
887 HArgumentsElements* arguments_elements_;
888
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000889 FunctionState* outer_;
890};
891
892
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000893class HIfContinuation {
894 public:
895 HIfContinuation() { continuation_captured_ = false; }
896 ~HIfContinuation() { ASSERT(!continuation_captured_); }
897
898 void Capture(HBasicBlock* true_branch,
899 HBasicBlock* false_branch,
900 int position) {
901 ASSERT(!continuation_captured_);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000902 true_branch_ = true_branch;
903 false_branch_ = false_branch;
904 position_ = position;
905 continuation_captured_ = true;
906 }
907
908 void Continue(HBasicBlock** true_branch,
909 HBasicBlock** false_branch,
910 int* position) {
911 ASSERT(continuation_captured_);
912 *true_branch = true_branch_;
913 *false_branch = false_branch_;
914 if (position != NULL) *position = position_;
915 continuation_captured_ = false;
916 }
917
918 bool IsTrueReachable() { return true_branch_ != NULL; }
919 bool IsFalseReachable() { return false_branch_ != NULL; }
920 bool TrueAndFalseReachable() {
921 return IsTrueReachable() || IsFalseReachable();
922 }
923
924 bool continuation_captured_;
925 HBasicBlock* true_branch_;
926 HBasicBlock* false_branch_;
927 int position_;
928};
929
930
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000931class HGraphBuilder {
932 public:
933 explicit HGraphBuilder(CompilationInfo* info)
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000934 : info_(info),
935 graph_(NULL),
936 current_block_(NULL),
937 no_side_effects_scope_count_(0) {}
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000938 virtual ~HGraphBuilder() {}
939
940 HBasicBlock* current_block() const { return current_block_; }
941 void set_current_block(HBasicBlock* block) { current_block_ = block; }
942 HEnvironment* environment() const {
943 return current_block()->last_environment();
944 }
945 Zone* zone() const { return info_->zone(); }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000946 HGraph* graph() const { return graph_; }
947 Isolate* isolate() const { return graph_->isolate(); }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000948
949 HGraph* CreateGraph();
950
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000951 // Bailout environment manipulation.
952 void Push(HValue* value) { environment()->Push(value); }
953 HValue* Pop() { return environment()->Pop(); }
954
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000955 // Adding instructions.
956 HInstruction* AddInstruction(HInstruction* instr);
957 void AddSimulate(BailoutId id,
958 RemovableSimulate removable = FIXED_SIMULATE);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000959 HBoundsCheck* AddBoundsCheck(
960 HValue* index,
961 HValue* length,
962 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY,
963 Representation r = Representation::None());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000964
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000965 HReturn* AddReturn(HValue* value);
966
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000967 void IncrementInNoSideEffectsScope() {
968 no_side_effects_scope_count_++;
969 }
970
971 void DecrementInNoSideEffectsScope() {
972 no_side_effects_scope_count_--;
973 }
974
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000975 protected:
976 virtual bool BuildGraph() = 0;
977
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000978 HBasicBlock* CreateBasicBlock(HEnvironment* env);
979 HBasicBlock* CreateLoopHeaderBlock();
980
981 HValue* BuildCheckNonSmi(HValue* object);
982 HValue* BuildCheckMap(HValue* obj, Handle<Map> map);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000983
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000984 // Building common constructs
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000985 HLoadNamedField* DoBuildLoadNamedField(HValue* object,
986 bool inobject,
987 Representation representation,
988 int offset);
989
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000990 HInstruction* BuildExternalArrayElementAccess(
991 HValue* external_elements,
992 HValue* checked_key,
993 HValue* val,
994 HValue* dependency,
995 ElementsKind elements_kind,
996 bool is_store);
997
998 HInstruction* BuildFastElementAccess(
999 HValue* elements,
1000 HValue* checked_key,
1001 HValue* val,
1002 HValue* dependency,
1003 ElementsKind elements_kind,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001004 bool is_store,
1005 KeyedAccessStoreMode store_mode);
1006
1007 HValue* BuildCheckForCapacityGrow(HValue* object,
1008 HValue* elements,
1009 ElementsKind kind,
1010 HValue* length,
1011 HValue* key,
1012 bool is_js_array);
1013
1014 HValue* BuildCopyElementsOnWrite(HValue* object,
1015 HValue* elements,
1016 ElementsKind kind,
1017 HValue* length);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001018
1019 HInstruction* BuildUncheckedMonomorphicElementAccess(
1020 HValue* object,
1021 HValue* key,
1022 HValue* val,
1023 HCheckMaps* mapcheck,
1024 bool is_js_array,
1025 ElementsKind elements_kind,
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00001026 bool is_store,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001027 KeyedAccessStoreMode store_mode,
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00001028 Representation checked_index_representation = Representation::None());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001029
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001030 HInstruction* BuildStoreMap(HValue* object, HValue* map);
1031 HInstruction* BuildStoreMap(HValue* object, Handle<Map> map);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001032
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001033 HLoadNamedField* AddLoadElements(HValue *object, HValue *typecheck = NULL);
1034
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001035 class IfBuilder {
1036 public:
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001037 explicit IfBuilder(HGraphBuilder* builder,
1038 int position = RelocInfo::kNoPosition);
1039 IfBuilder(HGraphBuilder* builder,
1040 HIfContinuation* continuation);
1041
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001042 ~IfBuilder() {
1043 if (!finished_) End();
1044 }
1045
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001046 HInstruction* IfCompare(
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001047 HValue* left,
1048 HValue* right,
1049 Token::Value token,
1050 Representation input_representation = Representation::Integer32());
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001051
1052 HInstruction* IfCompareMap(HValue* left, Handle<Map> map);
1053
1054 template<class Condition>
1055 HInstruction* If(HValue *p) {
1056 HControlInstruction* compare = new(zone()) Condition(p);
1057 AddCompare(compare);
1058 return compare;
1059 }
1060
1061 template<class Condition, class P2>
1062 HInstruction* If(HValue* p1, P2 p2) {
1063 HControlInstruction* compare = new(zone()) Condition(p1, p2);
1064 AddCompare(compare);
1065 return compare;
1066 }
1067
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00001068 template<class Condition, class P2>
1069 HInstruction* IfNot(HValue* p1, P2 p2) {
1070 HControlInstruction* compare = new(zone()) Condition(p1, p2);
1071 AddCompare(compare);
1072 HBasicBlock* block0 = compare->SuccessorAt(0);
1073 HBasicBlock* block1 = compare->SuccessorAt(1);
1074 compare->SetSuccessorAt(0, block1);
1075 compare->SetSuccessorAt(1, block0);
1076 return compare;
1077 }
1078
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001079 HInstruction* OrIfCompare(
1080 HValue* p1,
1081 HValue* p2,
1082 Token::Value token,
1083 Representation input_representation = Representation::Integer32()) {
1084 Or();
1085 return IfCompare(p1, p2, token, input_representation);
1086 }
1087
1088 HInstruction* OrIfCompareMap(HValue* left, Handle<Map> map) {
1089 Or();
1090 return IfCompareMap(left, map);
1091 }
1092
1093 template<class Condition>
1094 HInstruction* OrIf(HValue *p) {
1095 Or();
1096 return If<Condition>(p);
1097 }
1098
1099 template<class Condition, class P2>
1100 HInstruction* OrIf(HValue* p1, P2 p2) {
1101 Or();
1102 return If<Condition>(p1, p2);
1103 }
1104
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001105 HInstruction* AndIfCompare(
1106 HValue* p1,
1107 HValue* p2,
1108 Token::Value token,
1109 Representation input_representation = Representation::Integer32()) {
1110 And();
1111 return IfCompare(p1, p2, token, input_representation);
1112 }
1113
1114 HInstruction* AndIfCompareMap(HValue* left, Handle<Map> map) {
1115 And();
1116 return IfCompareMap(left, map);
1117 }
1118
1119 template<class Condition>
1120 HInstruction* AndIf(HValue *p) {
1121 And();
1122 return If<Condition>(p);
1123 }
1124
1125 template<class Condition, class P2>
1126 HInstruction* AndIf(HValue* p1, P2 p2) {
1127 And();
1128 return If<Condition>(p1, p2);
1129 }
1130
1131 void Or();
1132 void And();
1133
1134 void CaptureContinuation(HIfContinuation* continuation);
1135
1136 void Then();
1137 void Else();
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001138 void End();
1139
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001140 void Deopt();
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00001141 void ElseDeopt() {
1142 Else();
1143 Deopt();
1144 End();
1145 }
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001146
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001147 void Return(HValue* value);
1148
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001149 private:
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001150 void AddCompare(HControlInstruction* compare);
1151
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001152 Zone* zone() { return builder_->zone(); }
1153
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001154 HGraphBuilder* builder_;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001155 int position_;
1156 bool finished_ : 1;
1157 bool did_then_ : 1;
1158 bool did_else_ : 1;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001159 bool did_and_ : 1;
1160 bool did_or_ : 1;
1161 bool captured_ : 1;
1162 bool needs_compare_ : 1;
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001163 HBasicBlock* first_true_block_;
1164 HBasicBlock* last_true_block_;
1165 HBasicBlock* first_false_block_;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001166 HBasicBlock* split_edge_merge_block_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001167 HBasicBlock* merge_block_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001168 };
1169
1170 class LoopBuilder {
1171 public:
1172 enum Direction {
1173 kPreIncrement,
1174 kPostIncrement,
1175 kPreDecrement,
1176 kPostDecrement
1177 };
1178
1179 LoopBuilder(HGraphBuilder* builder,
1180 HValue* context,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001181 Direction direction);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001182 ~LoopBuilder() {
1183 ASSERT(finished_);
1184 }
1185
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001186 HValue* BeginBody(
1187 HValue* initial,
1188 HValue* terminating,
1189 Token::Value token,
1190 Representation input_representation = Representation::Integer32());
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001191 void EndBody();
1192
1193 private:
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001194 Zone* zone() { return builder_->zone(); }
1195
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001196 HGraphBuilder* builder_;
1197 HValue* context_;
1198 HInstruction* increment_;
1199 HPhi* phi_;
1200 HBasicBlock* header_block_;
1201 HBasicBlock* body_block_;
1202 HBasicBlock* exit_block_;
1203 Direction direction_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001204 bool finished_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001205 };
1206
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001207 class NoObservableSideEffectsScope {
1208 public:
1209 explicit NoObservableSideEffectsScope(HGraphBuilder* builder) :
1210 builder_(builder) {
1211 builder_->IncrementInNoSideEffectsScope();
1212 }
1213 ~NoObservableSideEffectsScope() {
1214 builder_->DecrementInNoSideEffectsScope();
1215 }
1216
1217 private:
1218 HGraphBuilder* builder_;
1219 };
1220
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001221 HValue* BuildNewElementsCapacity(HValue* context,
1222 HValue* old_capacity);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001223
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001224 void BuildNewSpaceArrayCheck(HValue* length,
1225 ElementsKind kind);
1226
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001227 class JSArrayBuilder {
1228 public:
1229 JSArrayBuilder(HGraphBuilder* builder,
1230 ElementsKind kind,
1231 HValue* allocation_site_payload,
1232 AllocationSiteMode mode);
1233
1234 HValue* AllocateEmptyArray();
1235 HValue* AllocateArray(HValue* capacity, HValue* length_field,
1236 bool fill_with_hole);
1237 HValue* GetElementsLocation() { return elements_location_; }
1238
1239 private:
1240 Zone* zone() const { return builder_->zone(); }
1241 int elements_size() const {
1242 return IsFastDoubleElementsKind(kind_) ? kDoubleSize : kPointerSize;
1243 }
1244 HInstruction* AddInstruction(HInstruction* instr) {
1245 return builder_->AddInstruction(instr);
1246 }
1247 HGraphBuilder* builder() { return builder_; }
1248 HGraph* graph() { return builder_->graph(); }
1249 int initial_capacity() {
1250 STATIC_ASSERT(JSArray::kPreallocatedArrayElements > 0);
1251 return JSArray::kPreallocatedArrayElements;
1252 }
1253
1254 HValue* EmitMapCode(HValue* context);
1255 HValue* EstablishEmptyArrayAllocationSize();
1256 HValue* EstablishAllocationSize(HValue* length_node);
1257 HValue* AllocateArray(HValue* size_in_bytes, HValue* capacity,
1258 HValue* length_field, bool fill_with_hole);
1259
1260 HGraphBuilder* builder_;
1261 ElementsKind kind_;
1262 AllocationSiteMode mode_;
1263 HValue* allocation_site_payload_;
1264 HInnerAllocatedObject* elements_location_;
1265 };
1266
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001267 HValue* BuildAllocateElements(HValue* context,
1268 ElementsKind kind,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001269 HValue* capacity);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001270
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001271 void BuildInitializeElements(HValue* elements,
1272 ElementsKind kind,
1273 HValue* capacity);
1274
1275 HValue* BuildAllocateAndInitializeElements(HValue* context,
1276 ElementsKind kind,
1277 HValue* capacity);
1278
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001279 // array must have been allocated with enough room for
1280 // 1) the JSArray, 2) a AllocationSiteInfo if mode requires it,
1281 // 3) a FixedArray or FixedDoubleArray.
1282 // A pointer to the Fixed(Double)Array is returned.
1283 HInnerAllocatedObject* BuildJSArrayHeader(HValue* array,
1284 HValue* array_map,
1285 AllocationSiteMode mode,
1286 HValue* allocation_site_payload,
1287 HValue* length_field);
1288
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001289 HValue* BuildGrowElementsCapacity(HValue* object,
1290 HValue* elements,
1291 ElementsKind kind,
1292 HValue* length,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001293 HValue* new_capacity);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001294
1295 void BuildFillElementsWithHole(HValue* context,
1296 HValue* elements,
1297 ElementsKind elements_kind,
1298 HValue* from,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001299 HValue* to);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001300
1301 void BuildCopyElements(HValue* context,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001302 HValue* from_elements,
1303 ElementsKind from_elements_kind,
1304 HValue* to_elements,
1305 ElementsKind to_elements_kind,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001306 HValue* length,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001307 HValue* capacity);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001308
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001309 HValue* BuildCloneShallowArray(HContext* context,
1310 HValue* boilerplate,
1311 AllocationSiteMode mode,
1312 ElementsKind kind,
1313 int length);
1314
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001315 void BuildCompareNil(
1316 HValue* value,
1317 EqualityKind kind,
1318 CompareNilICStub::Types types,
1319 Handle<Map> map,
1320 int position,
1321 HIfContinuation* continuation);
1322
1323 HValue* BuildCreateAllocationSiteInfo(HValue* previous_object,
1324 int previous_object_size,
1325 HValue* payload);
1326
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001327 HInstruction* BuildGetNativeContext(HValue* context);
1328 HInstruction* BuildGetArrayFunction(HValue* context);
1329
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001330 private:
1331 HGraphBuilder();
1332 CompilationInfo* info_;
1333 HGraph* graph_;
1334 HBasicBlock* current_block_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001335 int no_side_effects_scope_count_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001336};
1337
1338
1339class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001340 public:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001341 enum BreakType { BREAK, CONTINUE };
erikcorry0ad885c2011-11-21 13:51:57 +00001342 enum SwitchType { UNKNOWN_SWITCH, SMI_SWITCH, STRING_SWITCH };
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001343
1344 // A class encapsulating (lazily-allocated) break and continue blocks for
1345 // a breakable statement. Separated from BreakAndContinueScope so that it
1346 // can have a separate lifetime.
1347 class BreakAndContinueInfo BASE_EMBEDDED {
1348 public:
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001349 explicit BreakAndContinueInfo(BreakableStatement* target,
1350 int drop_extra = 0)
1351 : target_(target),
1352 break_block_(NULL),
1353 continue_block_(NULL),
1354 drop_extra_(drop_extra) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001355 }
1356
1357 BreakableStatement* target() { return target_; }
1358 HBasicBlock* break_block() { return break_block_; }
1359 void set_break_block(HBasicBlock* block) { break_block_ = block; }
1360 HBasicBlock* continue_block() { return continue_block_; }
1361 void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001362 int drop_extra() { return drop_extra_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001363
1364 private:
1365 BreakableStatement* target_;
1366 HBasicBlock* break_block_;
1367 HBasicBlock* continue_block_;
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001368 int drop_extra_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001369 };
1370
1371 // A helper class to maintain a stack of current BreakAndContinueInfo
1372 // structures mirroring BreakableStatement nesting.
1373 class BreakAndContinueScope BASE_EMBEDDED {
1374 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001375 BreakAndContinueScope(BreakAndContinueInfo* info,
1376 HOptimizedGraphBuilder* owner)
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001377 : info_(info), owner_(owner), next_(owner->break_scope()) {
1378 owner->set_break_scope(this);
1379 }
1380
1381 ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
1382
1383 BreakAndContinueInfo* info() { return info_; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001384 HOptimizedGraphBuilder* owner() { return owner_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001385 BreakAndContinueScope* next() { return next_; }
1386
1387 // Search the break stack for a break or continue target.
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001388 HBasicBlock* Get(BreakableStatement* stmt, BreakType type, int* drop_extra);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001389
1390 private:
1391 BreakAndContinueInfo* info_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001392 HOptimizedGraphBuilder* owner_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001393 BreakAndContinueScope* next_;
1394 };
1395
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001396 HOptimizedGraphBuilder(CompilationInfo* info, TypeFeedbackOracle* oracle);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001397
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001398 virtual bool BuildGraph();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001399
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001400 // Simple accessors.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001401 BreakAndContinueScope* break_scope() const { return break_scope_; }
1402 void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001403
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001404 bool inline_bailout() { return inline_bailout_; }
1405
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00001406 void AddSoftDeoptimize();
1407
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001408 void Bailout(const char* reason);
1409
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001410 HBasicBlock* CreateJoin(HBasicBlock* first,
1411 HBasicBlock* second,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001412 BailoutId join_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001413
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001414 TypeFeedbackOracle* oracle() const { return function_state()->oracle(); }
1415
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001416 FunctionState* function_state() const { return function_state_; }
1417
yangguo@chromium.org56454712012-02-16 15:33:53 +00001418 void VisitDeclarations(ZoneList<Declaration*>* declarations);
1419
verwaest@chromium.org178fb152012-07-18 11:21:48 +00001420 void* operator new(size_t size, Zone* zone) {
1421 return zone->New(static_cast<int>(size));
1422 }
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001423 void operator delete(void* pointer, Zone* zone) { }
1424 void operator delete(void* pointer) { }
verwaest@chromium.org178fb152012-07-18 11:21:48 +00001425
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001426 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
1427
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001428 private:
1429 // Type of a member function that generates inline code for a native function.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001430 typedef void (HOptimizedGraphBuilder::*InlineFunctionGenerator)
1431 (CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001432
1433 // Forward declarations for inner scope classes.
1434 class SubgraphScope;
1435
1436 static const InlineFunctionGenerator kInlineFunctionGenerators[];
1437
1438 static const int kMaxCallPolymorphism = 4;
1439 static const int kMaxLoadPolymorphism = 4;
1440 static const int kMaxStorePolymorphism = 4;
1441
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001442 // Even in the 'unlimited' case we have to have some limit in order not to
1443 // overflow the stack.
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +00001444 static const int kUnlimitedMaxInlinedSourceSize = 100000;
1445 static const int kUnlimitedMaxInlinedNodes = 10000;
1446 static const int kUnlimitedMaxInlinedNodesCumulative = 10000;
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001447
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001448 // Maximum depth and total number of elements and properties for literal
1449 // graphs to be considered for fast deep-copying.
1450 static const int kMaxFastLiteralDepth = 3;
1451 static const int kMaxFastLiteralProperties = 8;
1452
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001453 // Simple accessors.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001454 void set_function_state(FunctionState* state) { function_state_ = state; }
1455
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001456 AstContext* ast_context() const { return ast_context_; }
1457 void set_ast_context(AstContext* context) { ast_context_ = context; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001458
1459 // Accessors forwarded to the function state.
1460 CompilationInfo* info() const {
1461 return function_state()->compilation_info();
1462 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001463 AstContext* call_context() const {
1464 return function_state()->call_context();
1465 }
1466 HBasicBlock* function_return() const {
1467 return function_state()->function_return();
1468 }
1469 TestContext* inlined_test_context() const {
1470 return function_state()->test_context();
1471 }
1472 void ClearInlinedTestContext() {
1473 function_state()->ClearInlinedTestContext();
1474 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001475 StrictModeFlag function_strict_mode_flag() {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001476 return function_state()->compilation_info()->is_classic_mode()
1477 ? kNonStrictMode : kStrictMode;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001478 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001479
1480 // Generators for inline runtime functions.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001481#define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001482 void Generate##Name(CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001483
1484 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
1485 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
1486#undef INLINE_FUNCTION_GENERATOR_DECLARATION
1487
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001488 void VisitDelete(UnaryOperation* expr);
1489 void VisitVoid(UnaryOperation* expr);
1490 void VisitTypeof(UnaryOperation* expr);
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001491 void VisitSub(UnaryOperation* expr);
1492 void VisitBitNot(UnaryOperation* expr);
1493 void VisitNot(UnaryOperation* expr);
1494
1495 void VisitComma(BinaryOperation* expr);
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00001496 void VisitLogicalExpression(BinaryOperation* expr);
1497 void VisitArithmeticExpression(BinaryOperation* expr);
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001498
rossberg@chromium.org2c067b12012-03-19 11:01:52 +00001499 bool PreProcessOsrEntry(IterationStatement* statement);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001500 // True iff. we are compiling for OSR and the statement is the entry.
1501 bool HasOsrEntryAt(IterationStatement* statement);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001502 void VisitLoopBody(IterationStatement* stmt,
ager@chromium.org04921a82011-06-27 13:21:41 +00001503 HBasicBlock* loop_entry,
1504 BreakAndContinueInfo* break_info);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +00001505
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001506 // Create a back edge in the flow graph. body_exit is the predecessor
1507 // block and loop_entry is the successor block. loop_successor is the
1508 // block where control flow exits the loop normally (e.g., via failure of
1509 // the condition) and break_block is the block where control flow breaks
1510 // from the loop. All blocks except loop_entry can be NULL. The return
1511 // value is the new successor block which is the join of loop_successor
1512 // and break_block, or NULL.
1513 HBasicBlock* CreateLoop(IterationStatement* statement,
1514 HBasicBlock* loop_entry,
1515 HBasicBlock* body_exit,
1516 HBasicBlock* loop_successor,
1517 HBasicBlock* break_block);
1518
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +00001519 HBasicBlock* JoinContinue(IterationStatement* statement,
1520 HBasicBlock* exit_block,
1521 HBasicBlock* continue_block);
1522
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001523 HValue* Top() const { return environment()->Top(); }
1524 void Drop(int n) { environment()->Drop(n); }
1525 void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
1526
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001527 // The value of the arguments object is allowed in some but not most value
1528 // contexts. (It's allowed in all effect contexts and disallowed in all
1529 // test contexts.)
1530 void VisitForValue(Expression* expr,
1531 ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001532 void VisitForTypeOf(Expression* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001533 void VisitForEffect(Expression* expr);
1534 void VisitForControl(Expression* expr,
1535 HBasicBlock* true_block,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001536 HBasicBlock* false_block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001537
verwaest@chromium.org753aee42012-07-17 16:15:42 +00001538 // Visit an argument subexpression and emit a push to the outgoing arguments.
1539 void VisitArgument(Expression* expr);
vegorov@chromium.org3cf47312011-06-29 13:20:01 +00001540
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001541 void VisitArgumentList(ZoneList<Expression*>* arguments);
1542
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001543 // Visit a list of expressions from left to right, each in a value context.
1544 void VisitExpressions(ZoneList<Expression*>* exprs);
1545
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001546 void AddPhi(HPhi* phi);
1547
1548 void PushAndAdd(HInstruction* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001549
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001550 // Remove the arguments from the bailout environment and emit instructions
1551 // to push them as outgoing parameters.
ulan@chromium.org967e2702012-02-28 09:49:15 +00001552 template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001553
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001554 static Representation ToRepresentation(TypeInfo info);
1555
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001556 void SetUpScope(Scope* scope);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001557 virtual void VisitStatements(ZoneList<Statement*>* statements);
1558
1559#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
1560 AST_NODE_LIST(DECLARE_VISIT)
1561#undef DECLARE_VISIT
1562
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001563 // Helpers for flow graph construction.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001564 enum GlobalPropertyAccess {
1565 kUseCell,
1566 kUseGeneric
1567 };
1568 GlobalPropertyAccess LookupGlobalProperty(Variable* var,
1569 LookupResult* lookup,
1570 bool is_store);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001571
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001572 void EnsureArgumentsArePushedForAccess();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001573 bool TryArgumentsAccess(Property* expr);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001574
1575 // Try to optimize fun.apply(receiver, arguments) pattern.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001576 bool TryCallApply(Call* expr);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001577
jkummerow@chromium.org212d9642012-05-11 15:02:09 +00001578 int InliningAstSize(Handle<JSFunction> target);
ulan@chromium.org967e2702012-02-28 09:49:15 +00001579 bool TryInline(CallKind call_kind,
1580 Handle<JSFunction> target,
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001581 int arguments_count,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001582 HValue* implicit_return_value,
1583 BailoutId ast_id,
1584 BailoutId return_id,
1585 InliningKind inlining_kind);
ulan@chromium.org967e2702012-02-28 09:49:15 +00001586
1587 bool TryInlineCall(Call* expr, bool drop_extra = false);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001588 bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value);
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00001589 bool TryInlineGetter(Handle<JSFunction> getter, Property* prop);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001590 bool TryInlineSetter(Handle<JSFunction> setter,
1591 Assignment* assignment,
1592 HValue* implicit_return_value);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +00001593 bool TryInlineApply(Handle<JSFunction> function,
1594 Call* expr,
1595 int arguments_count);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001596 bool TryInlineBuiltinMethodCall(Call* expr,
ulan@chromium.org967e2702012-02-28 09:49:15 +00001597 HValue* receiver,
1598 Handle<Map> receiver_map,
1599 CheckType check_type);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001600 bool TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001601
1602 // If --trace-inlining, print a line of the inlining trace. Inlining
1603 // succeeded if the reason string is NULL and failed if there is a
1604 // non-NULL reason string.
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001605 void TraceInline(Handle<JSFunction> target,
1606 Handle<JSFunction> caller,
1607 const char* failure_reason);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001608
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001609 void HandleGlobalVariableAssignment(Variable* var,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001610 HValue* value,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001611 int position,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001612 BailoutId ast_id);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001613
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001614 void HandlePropertyAssignment(Assignment* expr);
1615 void HandleCompoundAssignment(Assignment* expr);
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001616 void HandlePolymorphicLoadNamedField(Property* expr,
1617 HValue* object,
1618 SmallMapList* types,
1619 Handle<String> name);
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001620 bool HandlePolymorphicArrayLengthLoad(Property* expr,
1621 HValue* object,
1622 SmallMapList* types,
1623 Handle<String> name);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001624 void HandlePolymorphicStoreNamedField(Assignment* expr,
1625 HValue* object,
1626 HValue* value,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001627 SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001628 Handle<String> name);
1629 void HandlePolymorphicCallNamed(Call* expr,
1630 HValue* receiver,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001631 SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001632 Handle<String> name);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001633 void HandleLiteralCompareTypeof(CompareOperation* expr,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001634 HTypeof* typeof_expr,
ager@chromium.org04921a82011-06-27 13:21:41 +00001635 Handle<String> check);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001636 void HandleLiteralCompareNil(CompareOperation* expr,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001637 HValue* value,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001638 NilValue nil);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001639
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001640 HInstruction* BuildStringCharCodeAt(HValue* context,
1641 HValue* string,
1642 HValue* index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001643 HInstruction* BuildBinaryOperation(BinaryOperation* expr,
1644 HValue* left,
1645 HValue* right);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001646 HInstruction* BuildIncrement(bool returns_original_input,
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001647 CountOperation* expr);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001648 HInstruction* BuildLoadKeyedGeneric(HValue* object,
1649 HValue* key);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001650
mstarzinger@chromium.orgc6d9cee2012-07-03 10:03:19 +00001651 HInstruction* TryBuildConsolidatedElementLoad(HValue* object,
1652 HValue* key,
1653 HValue* val,
1654 SmallMapList* maps);
1655
whesse@chromium.org7b260152011-06-20 15:33:18 +00001656 HInstruction* BuildMonomorphicElementAccess(HValue* object,
1657 HValue* key,
1658 HValue* val,
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00001659 HValue* dependency,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001660 Handle<Map> map,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001661 bool is_store,
1662 KeyedAccessStoreMode store_mode);
mstarzinger@chromium.orgc6d9cee2012-07-03 10:03:19 +00001663
whesse@chromium.org7b260152011-06-20 15:33:18 +00001664 HValue* HandlePolymorphicElementAccess(HValue* object,
1665 HValue* key,
1666 HValue* val,
1667 Expression* prop,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001668 BailoutId ast_id,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001669 int position,
1670 bool is_store,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001671 KeyedAccessStoreMode store_mode,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001672 bool* has_side_effects);
1673
1674 HValue* HandleKeyedElementAccess(HValue* obj,
1675 HValue* key,
1676 HValue* val,
1677 Expression* expr,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001678 BailoutId ast_id,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001679 int position,
1680 bool is_store,
1681 bool* has_side_effects);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001682
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00001683 HLoadNamedField* BuildLoadNamedField(HValue* object,
1684 Handle<Map> map,
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001685 LookupResult* result);
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00001686 HInstruction* BuildLoadNamedGeneric(HValue* object,
1687 Handle<String> name,
1688 Property* expr);
verwaest@chromium.orgb6d052d2012-07-27 08:03:27 +00001689 HInstruction* BuildCallGetter(HValue* object,
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001690 Handle<Map> map,
verwaest@chromium.orgde64f722012-08-16 15:44:54 +00001691 Handle<JSFunction> getter,
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001692 Handle<JSObject> holder);
verwaest@chromium.orgb6d052d2012-07-27 08:03:27 +00001693 HInstruction* BuildLoadNamedMonomorphic(HValue* object,
1694 Handle<String> name,
1695 Property* expr,
1696 Handle<Map> map);
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00001697
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001698 void AddCheckMap(HValue* object, Handle<Map> map);
1699
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001700 void AddCheckMapsWithTransitions(HValue* object,
1701 Handle<Map> map);
1702
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001703 HInstruction* BuildStoreNamedField(HValue* object,
1704 Handle<String> name,
1705 HValue* value,
verwaest@chromium.orgb6d052d2012-07-27 08:03:27 +00001706 Handle<Map> map,
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001707 LookupResult* lookup);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001708 HInstruction* BuildStoreNamedGeneric(HValue* object,
1709 Handle<String> name,
1710 HValue* value);
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00001711 HInstruction* BuildCallSetter(HValue* object,
1712 HValue* value,
1713 Handle<Map> map,
verwaest@chromium.orgde64f722012-08-16 15:44:54 +00001714 Handle<JSFunction> setter,
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00001715 Handle<JSObject> holder);
1716 HInstruction* BuildStoreNamedMonomorphic(HValue* object,
1717 Handle<String> name,
1718 HValue* value,
1719 Handle<Map> map);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001720 HInstruction* BuildStoreKeyedGeneric(HValue* object,
1721 HValue* key,
1722 HValue* value);
1723
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001724 HValue* BuildContextChainWalk(Variable* var);
1725
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001726 HInstruction* BuildThisFunction();
1727
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001728 HInstruction* BuildFastLiteral(HValue* context,
1729 Handle<JSObject> boilerplate_object,
1730 Handle<JSObject> original_boilerplate_object,
1731 int data_size,
1732 int pointer_size,
1733 AllocationSiteMode mode);
1734
1735 void BuildEmitDeepCopy(Handle<JSObject> boilerplat_object,
1736 Handle<JSObject> object,
1737 HInstruction* result,
1738 int* offset,
1739 AllocationSiteMode mode);
1740
1741 MUST_USE_RESULT HValue* BuildCopyObjectHeader(
1742 Handle<JSObject> boilerplat_object,
1743 HInstruction* target,
1744 int object_offset,
1745 int elements_offset,
1746 int elements_size);
1747
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001748 void AddCheckPrototypeMaps(Handle<JSObject> holder,
1749 Handle<Map> receiver_map);
1750
yangguo@chromium.org99aa4902012-07-06 16:21:55 +00001751 void AddCheckConstantFunction(Handle<JSObject> holder,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001752 HValue* receiver,
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001753 Handle<Map> receiver_map);
1754
1755 bool MatchRotateRight(HValue* left,
1756 HValue* right,
1757 HValue** operand,
1758 HValue** shift_amount);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001759
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001760 // The translation state of the currently-being-translated function.
1761 FunctionState* function_state_;
1762
1763 // The base of the function state stack.
1764 FunctionState initial_function_state_;
1765
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001766 // Expression context of the currently visited subexpression. NULL when
1767 // visiting statements.
1768 AstContext* ast_context_;
1769
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001770 // A stack of breakable statements entered.
1771 BreakAndContinueScope* break_scope_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001772
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001773 int inlined_count_;
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001774 ZoneList<Handle<Object> > globals_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001775
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001776 bool inline_bailout_;
1777
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001778 friend class FunctionState; // Pushes and pops the state stack.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001779 friend class AstContext; // Pushes and pops the AST context stack.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001780 friend class KeyedLoadFastElementStub;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001781
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001782 DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001783};
1784
1785
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001786Zone* AstContext::zone() const { return owner_->zone(); }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001787
1788
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001789class HValueMap: public ZoneObject {
1790 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001791 explicit HValueMap(Zone* zone)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001792 : array_size_(0),
1793 lists_size_(0),
1794 count_(0),
1795 present_flags_(0),
1796 array_(NULL),
1797 lists_(NULL),
1798 free_list_head_(kNil) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001799 ResizeLists(kInitialSize, zone);
1800 Resize(kInitialSize, zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001801 }
1802
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001803 void Kill(GVNFlagSet flags);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001804
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001805 void Add(HValue* value, Zone* zone) {
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001806 present_flags_.Add(value->gvn_flags());
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001807 Insert(value, zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001808 }
1809
1810 HValue* Lookup(HValue* value) const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001811
1812 HValueMap* Copy(Zone* zone) const {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001813 return new(zone) HValueMap(zone, this);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001814 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001815
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001816 bool IsEmpty() const { return count_ == 0; }
1817
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001818 private:
1819 // A linked list of HValue* values. Stored in arrays.
1820 struct HValueMapListElement {
1821 HValue* value;
1822 int next; // Index in the array of the next list element.
1823 };
1824 static const int kNil = -1; // The end of a linked list
1825
1826 // Must be a power of 2.
1827 static const int kInitialSize = 16;
1828
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001829 HValueMap(Zone* zone, const HValueMap* other);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001830
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001831 void Resize(int new_size, Zone* zone);
1832 void ResizeLists(int new_size, Zone* zone);
1833 void Insert(HValue* value, Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001834 uint32_t Bound(uint32_t value) const { return value & (array_size_ - 1); }
1835
1836 int array_size_;
1837 int lists_size_;
1838 int count_; // The number of values stored in the HValueMap.
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001839 GVNFlagSet present_flags_; // All flags that are in any value in the
1840 // HValueMap.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001841 HValueMapListElement* array_; // Primary store - contains the first value
1842 // with a given hash. Colliding elements are stored in linked lists.
1843 HValueMapListElement* lists_; // The linked lists containing hash collisions.
1844 int free_list_head_; // Unused elements in lists_ are on the free list.
1845};
1846
1847
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001848class HSideEffectMap BASE_EMBEDDED {
1849 public:
1850 HSideEffectMap();
1851 explicit HSideEffectMap(HSideEffectMap* other);
rossberg@chromium.org400388e2012-06-06 09:29:22 +00001852 HSideEffectMap& operator= (const HSideEffectMap& other);
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001853
1854 void Kill(GVNFlagSet flags);
1855
1856 void Store(GVNFlagSet flags, HInstruction* instr);
1857
1858 bool IsEmpty() const { return count_ == 0; }
1859
1860 inline HInstruction* operator[](int i) const {
1861 ASSERT(0 <= i);
1862 ASSERT(i < kNumberOfTrackedSideEffects);
1863 return data_[i];
1864 }
1865 inline HInstruction* at(int i) const { return operator[](i); }
1866
1867 private:
1868 int count_;
1869 HInstruction* data_[kNumberOfTrackedSideEffects];
1870};
1871
1872
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001873class HStatistics: public Malloced {
1874 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001875 HStatistics()
1876 : timing_(5),
1877 names_(5),
1878 sizes_(5),
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001879 create_graph_(0),
1880 optimize_graph_(0),
1881 generate_code_(0),
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001882 total_size_(0),
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001883 full_code_gen_(0),
1884 source_size_(0) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001885
ulan@chromium.org750145a2013-03-07 15:14:13 +00001886 void Initialize(CompilationInfo* info);
1887 void Print();
1888 void SaveTiming(const char* name, int64_t ticks, unsigned size);
1889
1890 void IncrementSubtotals(int64_t create_graph,
1891 int64_t optimize_graph,
1892 int64_t generate_code) {
1893 create_graph_ += create_graph;
1894 optimize_graph_ += optimize_graph;
1895 generate_code_ += generate_code;
1896 }
1897
1898 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001899 List<int64_t> timing_;
1900 List<const char*> names_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001901 List<unsigned> sizes_;
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001902 int64_t create_graph_;
1903 int64_t optimize_graph_;
1904 int64_t generate_code_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001905 unsigned total_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001906 int64_t full_code_gen_;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001907 double source_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001908};
1909
1910
1911class HPhase BASE_EMBEDDED {
1912 public:
1913 static const char* const kFullCodeGen;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001914
ulan@chromium.org750145a2013-03-07 15:14:13 +00001915 HPhase(const char* name, Isolate* isolate);
1916 HPhase(const char* name, HGraph* graph);
1917 HPhase(const char* name, LChunk* chunk);
1918 HPhase(const char* name, LAllocator* allocator);
1919 ~HPhase();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001920
1921 private:
ulan@chromium.org750145a2013-03-07 15:14:13 +00001922 void Init(Isolate* isolate,
1923 const char* name,
1924 HGraph* graph,
1925 LChunk* chunk,
1926 LAllocator* allocator);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001927
ulan@chromium.org750145a2013-03-07 15:14:13 +00001928 Isolate* isolate_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001929 const char* name_;
1930 HGraph* graph_;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00001931 LChunk* chunk_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001932 LAllocator* allocator_;
ulan@chromium.org750145a2013-03-07 15:14:13 +00001933 int64_t start_ticks_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001934 unsigned start_allocation_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001935};
1936
1937
1938class HTracer: public Malloced {
1939 public:
ulan@chromium.org750145a2013-03-07 15:14:13 +00001940 explicit HTracer(int isolate_id)
1941 : trace_(&string_allocator_), indent_(0) {
1942 OS::SNPrintF(filename_,
1943 "hydrogen-%d-%d.cfg",
1944 OS::GetCurrentProcessId(),
1945 isolate_id);
1946 WriteChars(filename_.start(), "", 0, false);
1947 }
1948
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001949 void TraceCompilation(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001950 void TraceHydrogen(const char* name, HGraph* graph);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00001951 void TraceLithium(const char* name, LChunk* chunk);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001952 void TraceLiveRanges(const char* name, LAllocator* allocator);
1953
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001954 private:
1955 class Tag BASE_EMBEDDED {
1956 public:
1957 Tag(HTracer* tracer, const char* name) {
1958 name_ = name;
1959 tracer_ = tracer;
1960 tracer->PrintIndent();
1961 tracer->trace_.Add("begin_%s\n", name);
1962 tracer->indent_++;
1963 }
1964
1965 ~Tag() {
1966 tracer_->indent_--;
1967 tracer_->PrintIndent();
1968 tracer_->trace_.Add("end_%s\n", name_);
1969 ASSERT(tracer_->indent_ >= 0);
1970 tracer_->FlushToFile();
1971 }
1972
1973 private:
1974 HTracer* tracer_;
1975 const char* name_;
1976 };
1977
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001978 void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00001979 void Trace(const char* name, HGraph* graph, LChunk* chunk);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001980 void FlushToFile();
1981
1982 void PrintEmptyProperty(const char* name) {
1983 PrintIndent();
1984 trace_.Add("%s\n", name);
1985 }
1986
1987 void PrintStringProperty(const char* name, const char* value) {
1988 PrintIndent();
1989 trace_.Add("%s \"%s\"\n", name, value);
1990 }
1991
1992 void PrintLongProperty(const char* name, int64_t value) {
1993 PrintIndent();
1994 trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
1995 }
1996
1997 void PrintBlockProperty(const char* name, int block_id) {
1998 PrintIndent();
1999 trace_.Add("%s \"B%d\"\n", name, block_id);
2000 }
2001
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002002 void PrintIntProperty(const char* name, int value) {
2003 PrintIndent();
2004 trace_.Add("%s %d\n", name, value);
2005 }
2006
2007 void PrintIndent() {
2008 for (int i = 0; i < indent_; i++) {
2009 trace_.Add(" ");
2010 }
2011 }
2012
ulan@chromium.org750145a2013-03-07 15:14:13 +00002013 EmbeddedVector<char, 64> filename_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002014 HeapStringAllocator string_allocator_;
2015 StringStream trace_;
2016 int indent_;
2017};
2018
2019
2020} } // namespace v8::internal
2021
2022#endif // V8_HYDROGEN_H_