blob: ca3fb4349b67a180218a856faa1cc81cb5a411ee [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
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +000033#include "accessors.h"
lrn@chromium.org1c092762011-05-09 09:42:16 +000034#include "allocation.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000035#include "ast.h"
36#include "compiler.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000037#include "hydrogen-instructions.h"
38#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;
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000050class HOsrBuilder;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000051class HTracer;
52class LAllocator;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000053class LChunk;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000054class LiveRange;
55
56
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +000057class HBasicBlock V8_FINAL : public ZoneObject {
kasperl@chromium.orga5551262010-12-07 12:49:48 +000058 public:
59 explicit HBasicBlock(HGraph* graph);
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +000060 ~HBasicBlock() { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +000061
62 // Simple accessors.
63 int block_id() const { return block_id_; }
64 void set_block_id(int id) { block_id_ = id; }
65 HGraph* graph() const { return graph_; }
ulan@chromium.org750145a2013-03-07 15:14:13 +000066 Isolate* isolate() const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000067 const ZoneList<HPhi*>* phis() const { return &phis_; }
68 HInstruction* first() const { return first_; }
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +000069 HInstruction* last() const { return last_; }
70 void set_last(HInstruction* instr) { last_ = instr; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +000071 HControlInstruction* end() const { return end_; }
72 HLoopInformation* loop_information() const { return loop_information_; }
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +000073 HLoopInformation* current_loop() const {
74 return IsLoopHeader() ? loop_information()
75 : (parent_loop_header() != NULL
76 ? parent_loop_header()->loop_information() : NULL);
77 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +000078 const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; }
79 bool HasPredecessor() const { return predecessors_.length() > 0; }
80 const ZoneList<HBasicBlock*>* dominated_blocks() const {
81 return &dominated_blocks_;
82 }
83 const ZoneList<int>* deleted_phis() const {
84 return &deleted_phis_;
85 }
86 void RecordDeletedPhi(int merge_index) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000087 deleted_phis_.Add(merge_index, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +000088 }
89 HBasicBlock* dominator() const { return dominator_; }
90 HEnvironment* last_environment() const { return last_environment_; }
91 int argument_count() const { return argument_count_; }
92 void set_argument_count(int count) { argument_count_ = count; }
93 int first_instruction_index() const { return first_instruction_index_; }
94 void set_first_instruction_index(int index) {
95 first_instruction_index_ = index;
96 }
97 int last_instruction_index() const { return last_instruction_index_; }
98 void set_last_instruction_index(int index) {
99 last_instruction_index_ = index;
100 }
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000101 bool is_osr_entry() { return is_osr_entry_; }
102 void set_osr_entry() { is_osr_entry_ = true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000103
104 void AttachLoopInformation();
105 void DetachLoopInformation();
106 bool IsLoopHeader() const { return loop_information() != NULL; }
107 bool IsStartBlock() const { return block_id() == 0; }
108 void PostProcessLoopHeader(IterationStatement* stmt);
109
110 bool IsFinished() const { return end_ != NULL; }
111 void AddPhi(HPhi* phi);
112 void RemovePhi(HPhi* phi);
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +0000113 void AddInstruction(HInstruction* instr, int position);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000114 bool Dominates(HBasicBlock* other) const;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000115 int LoopNestingDepth() const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000116
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000117 void SetInitialEnvironment(HEnvironment* env);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000118 void ClearEnvironment() {
119 ASSERT(IsFinished());
120 ASSERT(end()->SuccessorCount() == 0);
121 last_environment_ = NULL;
122 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000123 bool HasEnvironment() const { return last_environment_ != NULL; }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000124 void UpdateEnvironment(HEnvironment* env);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000125 HBasicBlock* parent_loop_header() const { return parent_loop_header_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000126
127 void set_parent_loop_header(HBasicBlock* block) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000128 ASSERT(parent_loop_header_ == NULL);
129 parent_loop_header_ = block;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000130 }
131
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000132 bool HasParentLoopHeader() const { return parent_loop_header_ != NULL; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000133
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000134 void SetJoinId(BailoutId ast_id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000135
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000136 int PredecessorIndexOf(HBasicBlock* predecessor) const;
danno@chromium.orgad75d6f2013-08-12 16:57:59 +0000137 HPhi* AddNewPhi(int merged_index);
138 HSimulate* AddNewSimulate(BailoutId ast_id,
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +0000139 int position,
danno@chromium.orgad75d6f2013-08-12 16:57:59 +0000140 RemovableSimulate removable = FIXED_SIMULATE) {
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000141 HSimulate* instr = CreateSimulate(ast_id, removable);
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +0000142 AddInstruction(instr, position);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000143 return instr;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000144 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000145 void AssignCommonDominator(HBasicBlock* other);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000146 void AssignLoopSuccessorDominators();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000147
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000148 // If a target block is tagged as an inline function return, all
149 // predecessors should contain the inlined exit sequence:
150 //
151 // LeaveInlined
152 // Simulate (caller's environment)
153 // Goto (target block)
154 bool IsInlineReturnTarget() const { return is_inline_return_target_; }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000155 void MarkAsInlineReturnTarget(HBasicBlock* inlined_entry_block) {
156 is_inline_return_target_ = true;
157 inlined_entry_block_ = inlined_entry_block;
158 }
159 HBasicBlock* inlined_entry_block() { return inlined_entry_block_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000160
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000161 bool IsDeoptimizing() const {
162 return end() != NULL && end()->IsDeoptimize();
163 }
164
165 void MarkUnreachable();
166 bool IsUnreachable() const { return !is_reachable_; }
167 bool IsReachable() const { return is_reachable_; }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000168
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000169 bool IsLoopSuccessorDominator() const {
170 return dominates_loop_successors_;
171 }
172 void MarkAsLoopSuccessorDominator() {
173 dominates_loop_successors_ = true;
174 }
175
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000176 inline Zone* zone() const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000177
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000178#ifdef DEBUG
179 void Verify();
180#endif
181
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +0000182 protected:
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000183 friend class HGraphBuilder;
184
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +0000185 HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable);
186 void Finish(HControlInstruction* last, int position);
187 void FinishExit(HControlInstruction* instruction, int position);
188 void Goto(HBasicBlock* block,
189 int position,
190 FunctionState* state = NULL,
191 bool add_simulate = true);
192 void GotoNoSimulate(HBasicBlock* block, int position) {
193 Goto(block, position, NULL, false);
194 }
195
196 // Add the inlined function exit sequence, adding an HLeaveInlined
197 // instruction and updating the bailout environment.
198 void AddLeaveInlined(HValue* return_value,
199 FunctionState* state,
200 int position);
201
202 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000203 void RegisterPredecessor(HBasicBlock* pred);
204 void AddDominatedBlock(HBasicBlock* block);
205
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000206 int block_id_;
207 HGraph* graph_;
208 ZoneList<HPhi*> phis_;
209 HInstruction* first_;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000210 HInstruction* last_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000211 HControlInstruction* end_;
212 HLoopInformation* loop_information_;
213 ZoneList<HBasicBlock*> predecessors_;
214 HBasicBlock* dominator_;
215 ZoneList<HBasicBlock*> dominated_blocks_;
216 HEnvironment* last_environment_;
217 // Outgoing parameter count at block exit, set during lithium translation.
218 int argument_count_;
219 // Instruction indices into the lithium code stream.
220 int first_instruction_index_;
221 int last_instruction_index_;
222 ZoneList<int> deleted_phis_;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000223 HBasicBlock* parent_loop_header_;
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000224 // For blocks marked as inline return target: the block with HEnterInlined.
225 HBasicBlock* inlined_entry_block_;
226 bool is_inline_return_target_ : 1;
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000227 bool is_reachable_ : 1;
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000228 bool dominates_loop_successors_ : 1;
229 bool is_osr_entry_ : 1;
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000230};
231
232
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000233class HPredecessorIterator V8_FINAL BASE_EMBEDDED {
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000234 public:
235 explicit HPredecessorIterator(HBasicBlock* block)
236 : predecessor_list_(block->predecessors()), current_(0) { }
237
238 bool Done() { return current_ >= predecessor_list_->length(); }
239 HBasicBlock* Current() { return predecessor_list_->at(current_); }
240 void Advance() { current_++; }
241
242 private:
243 const ZoneList<HBasicBlock*>* predecessor_list_;
244 int current_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000245};
246
247
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000248class HInstructionIterator V8_FINAL BASE_EMBEDDED {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000249 public:
danno@chromium.org169691d2013-07-15 08:01:13 +0000250 explicit HInstructionIterator(HBasicBlock* block)
251 : instr_(block->first()) {
252 next_ = Done() ? NULL : instr_->next();
253 }
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000254
danno@chromium.org169691d2013-07-15 08:01:13 +0000255 inline bool Done() const { return instr_ == NULL; }
256 inline HInstruction* Current() { return instr_; }
257 inline void Advance() {
258 instr_ = next_;
259 next_ = Done() ? NULL : instr_->next();
260 }
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000261
262 private:
263 HInstruction* instr_;
danno@chromium.org169691d2013-07-15 08:01:13 +0000264 HInstruction* next_;
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000265};
266
267
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000268class HLoopInformation V8_FINAL : public ZoneObject {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000269 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000270 HLoopInformation(HBasicBlock* loop_header, Zone* zone)
271 : back_edges_(4, zone),
ager@chromium.org04921a82011-06-27 13:21:41 +0000272 loop_header_(loop_header),
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000273 blocks_(8, zone),
ager@chromium.org04921a82011-06-27 13:21:41 +0000274 stack_check_(NULL) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000275 blocks_.Add(loop_header, zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000276 }
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000277 ~HLoopInformation() {}
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000278
279 const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; }
280 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
281 HBasicBlock* loop_header() const { return loop_header_; }
282 HBasicBlock* GetLastBackEdge() const;
283 void RegisterBackEdge(HBasicBlock* block);
284
ager@chromium.org04921a82011-06-27 13:21:41 +0000285 HStackCheck* stack_check() const { return stack_check_; }
286 void set_stack_check(HStackCheck* stack_check) {
287 stack_check_ = stack_check;
288 }
289
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000290 bool IsNestedInThisLoop(HLoopInformation* other) {
291 while (other != NULL) {
292 if (other == this) {
293 return true;
294 }
295 other = other->parent_loop();
296 }
297 return false;
298 }
299 HLoopInformation* parent_loop() {
300 HBasicBlock* parent_header = loop_header()->parent_loop_header();
301 return parent_header != NULL ? parent_header->loop_information() : NULL;
302 }
303
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000304 private:
305 void AddBlock(HBasicBlock* block);
306
307 ZoneList<HBasicBlock*> back_edges_;
308 HBasicBlock* loop_header_;
309 ZoneList<HBasicBlock*> blocks_;
ager@chromium.org04921a82011-06-27 13:21:41 +0000310 HStackCheck* stack_check_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000311};
312
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000313
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000314class BoundsCheckTable;
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000315class InductionVariableBlocksTable;
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000316class HGraph V8_FINAL : public ZoneObject {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000317 public:
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000318 explicit HGraph(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000319
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000320 Isolate* isolate() const { return isolate_; }
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000321 Zone* zone() const { return zone_; }
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000322 CompilationInfo* info() const { return info_; }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000323
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000324 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
325 const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000326 HBasicBlock* entry_block() const { return entry_block_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000327 HEnvironment* start_environment() const { return start_environment_; }
328
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +0000329 void FinalizeUniqueness();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000330 bool ProcessArgumentsObject();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000331 void OrderBlocks();
332 void AssignDominators();
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000333 void RestoreActualValues();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000334
335 // Returns false if there are phi-uses of the arguments-object
336 // which are not supported by the optimizing compiler.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000337 bool CheckArgumentsPhiUses();
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +0000338
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000339 // Returns false if there are phi-uses of an uninitialized const
340 // which are not supported by the optimizing compiler.
341 bool CheckConstPhiUses();
342
343 void CollectPhis();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000344
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +0000345 HConstant* GetConstantUndefined();
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000346 HConstant* GetConstant0();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000347 HConstant* GetConstant1();
348 HConstant* GetConstantMinus1();
349 HConstant* GetConstantTrue();
350 HConstant* GetConstantFalse();
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000351 HConstant* GetConstantHole();
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000352 HConstant* GetConstantNull();
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000353 HConstant* GetInvalidContext();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000354
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000355 bool IsConstantUndefined(HConstant* constant);
356 bool IsConstant0(HConstant* constant);
357 bool IsConstant1(HConstant* constant);
358 bool IsConstantMinus1(HConstant* constant);
359 bool IsConstantTrue(HConstant* constant);
360 bool IsConstantFalse(HConstant* constant);
361 bool IsConstantHole(HConstant* constant);
362 bool IsConstantNull(HConstant* constant);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000363 bool IsStandardConstant(HConstant* constant);
364
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000365 HBasicBlock* CreateBasicBlock();
366 HArgumentsObject* GetArgumentsObject() const {
367 return arguments_object_.get();
368 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000369
370 void SetArgumentsObject(HArgumentsObject* object) {
371 arguments_object_.set(object);
372 }
373
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000374 int GetMaximumValueID() const { return values_.length(); }
375 int GetNextBlockID() { return next_block_id_++; }
376 int GetNextValueID(HValue* value) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000377 ASSERT(!disallow_adding_new_values_);
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000378 values_.Add(value, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000379 return values_.length() - 1;
380 }
381 HValue* LookupValue(int id) const {
382 if (id >= 0 && id < values_.length()) return values_[id];
383 return NULL;
384 }
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000385 void DisallowAddingNewValues() {
386 disallow_adding_new_values_ = true;
387 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000388
danno@chromium.org59400602013-08-13 17:09:37 +0000389 bool Optimize(BailoutReason* bailout_reason);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000390
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000391#ifdef DEBUG
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000392 void Verify(bool do_full_verify) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000393#endif
394
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +0000395 bool has_osr() {
396 return osr_ != NULL;
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000397 }
398
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +0000399 void set_osr(HOsrBuilder* osr) {
400 osr_ = osr;
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000401 }
402
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +0000403 HOsrBuilder* osr() {
404 return osr_;
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000405 }
406
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000407 int update_type_change_checksum(int delta) {
408 type_change_checksum_ += delta;
409 return type_change_checksum_;
410 }
411
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000412 void update_maximum_environment_size(int environment_size) {
413 if (environment_size > maximum_environment_size_) {
414 maximum_environment_size_ = environment_size;
415 }
416 }
417 int maximum_environment_size() { return maximum_environment_size_; }
418
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000419 bool use_optimistic_licm() {
420 return use_optimistic_licm_;
421 }
422
423 void set_use_optimistic_licm(bool value) {
424 use_optimistic_licm_ = value;
425 }
426
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000427 void MarkRecursive() {
428 is_recursive_ = true;
429 }
430
431 bool is_recursive() const {
432 return is_recursive_;
433 }
434
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000435 void MarkDependsOnEmptyArrayProtoElements() {
danno@chromium.org41728482013-06-12 22:31:22 +0000436 // Add map dependency if not already added.
437 if (depends_on_empty_array_proto_elements_) return;
438 isolate()->initial_object_prototype()->map()->AddDependentCompilationInfo(
439 DependentCode::kElementsCantBeAddedGroup, info());
440 isolate()->initial_array_prototype()->map()->AddDependentCompilationInfo(
441 DependentCode::kElementsCantBeAddedGroup, info());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000442 depends_on_empty_array_proto_elements_ = true;
443 }
444
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000445 bool depends_on_empty_array_proto_elements() {
446 return depends_on_empty_array_proto_elements_;
447 }
448
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000449 bool has_uint32_instructions() {
450 ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
451 return uint32_instructions_ != NULL;
452 }
453
454 ZoneList<HInstruction*>* uint32_instructions() {
455 ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
456 return uint32_instructions_;
457 }
458
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000459 void RecordUint32Instruction(HInstruction* instr) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000460 ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000461 if (uint32_instructions_ == NULL) {
462 uint32_instructions_ = new(zone()) ZoneList<HInstruction*>(4, zone());
463 }
464 uint32_instructions_->Add(instr, zone());
465 }
466
danno@chromium.orgad75d6f2013-08-12 16:57:59 +0000467 void IncrementInNoSideEffectsScope() { no_side_effects_scope_count_++; }
468 void DecrementInNoSideEffectsScope() { no_side_effects_scope_count_--; }
469 bool IsInsideNoSideEffectsScope() { return no_side_effects_scope_count_ > 0; }
470
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000471 private:
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +0000472 HConstant* ReinsertConstantIfNecessary(HConstant* constant);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +0000473 HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
474 int32_t integer_value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000475
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000476 template<class Phase>
477 void Run() {
478 Phase phase(this);
479 phase.Run();
480 }
481
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000482 void EliminateRedundantBoundsChecksUsingInductionVariables();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000483
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000484 Isolate* isolate_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000485 int next_block_id_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000486 HBasicBlock* entry_block_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000487 HEnvironment* start_environment_;
488 ZoneList<HBasicBlock*> blocks_;
489 ZoneList<HValue*> values_;
490 ZoneList<HPhi*>* phi_list_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000491 ZoneList<HInstruction*>* uint32_instructions_;
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +0000492 SetOncePointer<HConstant> constant_undefined_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000493 SetOncePointer<HConstant> constant_0_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000494 SetOncePointer<HConstant> constant_1_;
495 SetOncePointer<HConstant> constant_minus1_;
496 SetOncePointer<HConstant> constant_true_;
497 SetOncePointer<HConstant> constant_false_;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000498 SetOncePointer<HConstant> constant_the_hole_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000499 SetOncePointer<HConstant> constant_null_;
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000500 SetOncePointer<HConstant> constant_invalid_context_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000501 SetOncePointer<HArgumentsObject> arguments_object_;
502
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +0000503 HOsrBuilder* osr_;
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000504
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000505 CompilationInfo* info_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000506 Zone* zone_;
507
508 bool is_recursive_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000509 bool use_optimistic_licm_;
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000510 bool depends_on_empty_array_proto_elements_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000511 int type_change_checksum_;
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000512 int maximum_environment_size_;
danno@chromium.orgad75d6f2013-08-12 16:57:59 +0000513 int no_side_effects_scope_count_;
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000514 bool disallow_adding_new_values_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000515
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000516 DISALLOW_COPY_AND_ASSIGN(HGraph);
517};
518
519
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000520Zone* HBasicBlock::zone() const { return graph_->zone(); }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000521
522
ulan@chromium.org967e2702012-02-28 09:49:15 +0000523// Type of stack frame an environment might refer to.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000524enum FrameType {
525 JS_FUNCTION,
526 JS_CONSTRUCT,
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +0000527 JS_GETTER,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000528 JS_SETTER,
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000529 ARGUMENTS_ADAPTOR,
530 STUB
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000531};
ulan@chromium.org967e2702012-02-28 09:49:15 +0000532
533
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000534class HEnvironment V8_FINAL : public ZoneObject {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000535 public:
536 HEnvironment(HEnvironment* outer,
537 Scope* scope,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000538 Handle<JSFunction> closure,
539 Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000540
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000541 HEnvironment(Zone* zone, int parameter_count);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000542
ulan@chromium.org6ff65142012-03-21 09:52:17 +0000543 HEnvironment* arguments_environment() {
544 return outer()->frame_type() == ARGUMENTS_ADAPTOR ? outer() : this;
545 }
546
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000547 // Simple accessors.
548 Handle<JSFunction> closure() const { return closure_; }
549 const ZoneList<HValue*>* values() const { return &values_; }
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000550 const GrowableBitVector* assigned_variables() const {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000551 return &assigned_variables_;
552 }
ulan@chromium.org967e2702012-02-28 09:49:15 +0000553 FrameType frame_type() const { return frame_type_; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000554 int parameter_count() const { return parameter_count_; }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000555 int specials_count() const { return specials_count_; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000556 int local_count() const { return local_count_; }
557 HEnvironment* outer() const { return outer_; }
558 int pop_count() const { return pop_count_; }
559 int push_count() const { return push_count_; }
560
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000561 BailoutId ast_id() const { return ast_id_; }
562 void set_ast_id(BailoutId id) { ast_id_ = id; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000563
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000564 HEnterInlined* entry() const { return entry_; }
565 void set_entry(HEnterInlined* entry) { entry_ = entry; }
566
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000567 int length() const { return values_.length(); }
568
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000569 int first_expression_index() const {
570 return parameter_count() + specials_count() + local_count();
571 }
572
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000573 int first_local_index() const {
574 return parameter_count() + specials_count();
575 }
576
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000577 void Bind(Variable* variable, HValue* value) {
578 Bind(IndexFor(variable), value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000579 }
580
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000581 void Bind(int index, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000582
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000583 void BindContext(HValue* value) {
584 Bind(parameter_count(), value);
585 }
586
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000587 HValue* Lookup(Variable* variable) const {
588 return Lookup(IndexFor(variable));
589 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000590
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000591 HValue* Lookup(int index) const {
592 HValue* result = values_[index];
593 ASSERT(result != NULL);
594 return result;
595 }
596
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000597 HValue* context() const {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000598 // Return first special.
599 return Lookup(parameter_count());
600 }
601
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000602 void Push(HValue* value) {
603 ASSERT(value != NULL);
604 ++push_count_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000605 values_.Add(value, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000606 }
607
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000608 HValue* Pop() {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000609 ASSERT(!ExpressionStackIsEmpty());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000610 if (push_count_ > 0) {
611 --push_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000612 } else {
613 ++pop_count_;
614 }
615 return values_.RemoveLast();
616 }
617
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000618 void Drop(int count);
619
620 HValue* Top() const { return ExpressionStackAt(0); }
621
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000622 bool ExpressionStackIsEmpty() const;
623
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000624 HValue* ExpressionStackAt(int index_from_top) const {
625 int index = length() - index_from_top - 1;
626 ASSERT(HasExpressionAt(index));
627 return values_[index];
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000628 }
629
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000630 void SetExpressionStackAt(int index_from_top, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000631
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000632 HEnvironment* Copy() const;
633 HEnvironment* CopyWithoutHistory() const;
634 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const;
635
636 // Create an "inlined version" of this environment, where the original
637 // environment is the outer environment but the top expression stack
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000638 // elements are moved to an inner environment as parameters.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000639 HEnvironment* CopyForInlining(Handle<JSFunction> target,
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000640 int arguments,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000641 FunctionLiteral* function,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000642 HConstant* undefined,
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000643 InliningKind inlining_kind,
644 bool undefined_receiver) const;
645
646 static bool UseUndefinedReceiver(Handle<JSFunction> closure,
647 FunctionLiteral* function,
648 CallKind call_kind,
649 InliningKind inlining_kind) {
650 return (closure->shared()->native() || !function->is_classic_mode()) &&
651 call_kind == CALL_AS_FUNCTION && inlining_kind != CONSTRUCT_CALL_RETURN;
652 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000653
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000654 HEnvironment* DiscardInlined(bool drop_extra) {
655 HEnvironment* outer = outer_;
656 while (outer->frame_type() != JS_FUNCTION) outer = outer->outer_;
657 if (drop_extra) outer->Drop(1);
658 return outer;
659 }
660
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000661 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000662
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000663 void ClearHistory() {
664 pop_count_ = 0;
665 push_count_ = 0;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000666 assigned_variables_.Clear();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000667 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000668
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000669 void SetValueAt(int index, HValue* value) {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000670 ASSERT(index < length());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000671 values_[index] = value;
672 }
673
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000674 // Map a variable to an environment index. Parameter indices are shifted
675 // by 1 (receiver is parameter index -1 but environment index 0).
676 // Stack-allocated local indices are shifted by the number of parameters.
677 int IndexFor(Variable* variable) const {
678 ASSERT(variable->IsStackAllocated());
679 int shift = variable->IsParameter()
680 ? 1
681 : parameter_count_ + specials_count_;
682 return variable->index() + shift;
683 }
684
685 bool is_local_index(int i) const {
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +0000686 return i >= first_local_index() && i < first_expression_index();
687 }
688
689 bool is_parameter_index(int i) const {
690 return i >= 0 && i < parameter_count();
691 }
692
693 bool is_special_index(int i) const {
694 return i >= parameter_count() && i < parameter_count() + specials_count();
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000695 }
696
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000697 void PrintTo(StringStream* stream);
698 void PrintToStd();
699
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000700 Zone* zone() const { return zone_; }
701
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000702 private:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000703 HEnvironment(const HEnvironment* other, Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000704
ulan@chromium.org967e2702012-02-28 09:49:15 +0000705 HEnvironment(HEnvironment* outer,
706 Handle<JSFunction> closure,
707 FrameType frame_type,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000708 int arguments,
709 Zone* zone);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000710
ulan@chromium.org967e2702012-02-28 09:49:15 +0000711 // Create an artificial stub environment (e.g. for argument adaptor or
712 // constructor stub).
713 HEnvironment* CreateStubEnvironment(HEnvironment* outer,
714 Handle<JSFunction> target,
715 FrameType frame_type,
716 int arguments) const;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000717
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000718 // True if index is included in the expression stack part of the environment.
719 bool HasExpressionAt(int index) const;
720
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000721 void Initialize(int parameter_count, int local_count, int stack_height);
722 void Initialize(const HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000723
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000724 Handle<JSFunction> closure_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000725 // Value array [parameters] [specials] [locals] [temporaries].
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000726 ZoneList<HValue*> values_;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000727 GrowableBitVector assigned_variables_;
ulan@chromium.org967e2702012-02-28 09:49:15 +0000728 FrameType frame_type_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000729 int parameter_count_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000730 int specials_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000731 int local_count_;
732 HEnvironment* outer_;
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000733 HEnterInlined* entry_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000734 int pop_count_;
735 int push_count_;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000736 BailoutId ast_id_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000737 Zone* zone_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000738};
739
740
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000741class HOptimizedGraphBuilder;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000742
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000743enum ArgumentsAllowedFlag {
744 ARGUMENTS_NOT_ALLOWED,
745 ARGUMENTS_ALLOWED
746};
747
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000748
749class HIfContinuation;
750
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000751// This class is not BASE_EMBEDDED because our inlining implementation uses
752// new and delete.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000753class AstContext {
754 public:
755 bool IsEffect() const { return kind_ == Expression::kEffect; }
756 bool IsValue() const { return kind_ == Expression::kValue; }
757 bool IsTest() const { return kind_ == Expression::kTest; }
758
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000759 // 'Fill' this context with a hydrogen value. The value is assumed to
760 // have already been inserted in the instruction stream (or not need to
761 // be, e.g., HPhi). Call this function in tail position in the Visit
762 // functions for expressions.
763 virtual void ReturnValue(HValue* value) = 0;
764
765 // Add a hydrogen instruction to the instruction stream (recording an
766 // environment simulation if necessary) and then fill this context with
767 // the instruction as value.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000768 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id) = 0;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000769
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000770 // Finishes the current basic block and materialize a boolean for
771 // value context, nothing for effect, generate a branch for test context.
772 // Call this function in tail position in the Visit functions for
773 // expressions.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000774 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id) = 0;
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000775
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000776 // Finishes the current basic block and materialize a boolean for
777 // value context, nothing for effect, generate a branch for test context.
778 // Call this function in tail position in the Visit functions for
779 // expressions that use an IfBuilder.
780 virtual void ReturnContinuation(HIfContinuation* continuation,
781 BailoutId ast_id) = 0;
782
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000783 void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; }
784 bool is_for_typeof() { return for_typeof_; }
785
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000786 protected:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000787 AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000788 virtual ~AstContext();
789
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000790 HOptimizedGraphBuilder* owner() const { return owner_; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000791
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000792 inline Zone* zone() const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000793
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000794 // We want to be able to assert, in a context-specific way, that the stack
795 // height makes sense when the context is filled.
796#ifdef DEBUG
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000797 int original_length_;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000798#endif
799
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000800 private:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000801 HOptimizedGraphBuilder* owner_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000802 Expression::Context kind_;
803 AstContext* outer_;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000804 bool for_typeof_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000805};
806
807
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000808class EffectContext V8_FINAL : public AstContext {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000809 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000810 explicit EffectContext(HOptimizedGraphBuilder* owner)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000811 : AstContext(owner, Expression::kEffect) {
812 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000813 virtual ~EffectContext();
814
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000815 virtual void ReturnValue(HValue* value) V8_OVERRIDE;
816 virtual void ReturnInstruction(HInstruction* instr,
817 BailoutId ast_id) V8_OVERRIDE;
818 virtual void ReturnControl(HControlInstruction* instr,
819 BailoutId ast_id) V8_OVERRIDE;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000820 virtual void ReturnContinuation(HIfContinuation* continuation,
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000821 BailoutId ast_id) V8_OVERRIDE;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000822};
823
824
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000825class ValueContext V8_FINAL : public AstContext {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000826 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000827 ValueContext(HOptimizedGraphBuilder* owner, ArgumentsAllowedFlag flag)
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000828 : AstContext(owner, Expression::kValue), flag_(flag) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000829 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000830 virtual ~ValueContext();
831
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000832 virtual void ReturnValue(HValue* value) V8_OVERRIDE;
833 virtual void ReturnInstruction(HInstruction* instr,
834 BailoutId ast_id) V8_OVERRIDE;
835 virtual void ReturnControl(HControlInstruction* instr,
836 BailoutId ast_id) V8_OVERRIDE;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000837 virtual void ReturnContinuation(HIfContinuation* continuation,
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000838 BailoutId ast_id) V8_OVERRIDE;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000839
840 bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
841
842 private:
843 ArgumentsAllowedFlag flag_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000844};
845
846
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000847class TestContext V8_FINAL : public AstContext {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000848 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000849 TestContext(HOptimizedGraphBuilder* owner,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000850 Expression* condition,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000851 HBasicBlock* if_true,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000852 HBasicBlock* if_false)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000853 : AstContext(owner, Expression::kTest),
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000854 condition_(condition),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000855 if_true_(if_true),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000856 if_false_(if_false) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000857 }
858
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000859 virtual void ReturnValue(HValue* value) V8_OVERRIDE;
860 virtual void ReturnInstruction(HInstruction* instr,
861 BailoutId ast_id) V8_OVERRIDE;
862 virtual void ReturnControl(HControlInstruction* instr,
863 BailoutId ast_id) V8_OVERRIDE;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000864 virtual void ReturnContinuation(HIfContinuation* continuation,
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000865 BailoutId ast_id) V8_OVERRIDE;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000866
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000867 static TestContext* cast(AstContext* context) {
868 ASSERT(context->IsTest());
869 return reinterpret_cast<TestContext*>(context);
870 }
871
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000872 Expression* condition() const { return condition_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000873 HBasicBlock* if_true() const { return if_true_; }
874 HBasicBlock* if_false() const { return if_false_; }
875
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000876 private:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000877 // Build the shared core part of the translation unpacking a value into
878 // control flow.
879 void BuildBranch(HValue* value);
880
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000881 Expression* condition_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000882 HBasicBlock* if_true_;
883 HBasicBlock* if_false_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000884};
885
886
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000887class FunctionState V8_FINAL {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000888 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000889 FunctionState(HOptimizedGraphBuilder* owner,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000890 CompilationInfo* info,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000891 InliningKind inlining_kind);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000892 ~FunctionState();
893
894 CompilationInfo* compilation_info() { return compilation_info_; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000895 AstContext* call_context() { return call_context_; }
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000896 InliningKind inlining_kind() const { return inlining_kind_; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000897 HBasicBlock* function_return() { return function_return_; }
898 TestContext* test_context() { return test_context_; }
899 void ClearInlinedTestContext() {
900 delete test_context_;
901 test_context_ = NULL;
902 }
903
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000904 FunctionState* outer() { return outer_; }
905
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000906 HEnterInlined* entry() { return entry_; }
907 void set_entry(HEnterInlined* entry) { entry_ = entry; }
908
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000909 HArgumentsObject* arguments_object() { return arguments_object_; }
910 void set_arguments_object(HArgumentsObject* arguments_object) {
911 arguments_object_ = arguments_object;
912 }
913
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000914 HArgumentsElements* arguments_elements() { return arguments_elements_; }
915 void set_arguments_elements(HArgumentsElements* arguments_elements) {
916 arguments_elements_ = arguments_elements;
917 }
918
919 bool arguments_pushed() { return arguments_elements() != NULL; }
920
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000921 private:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000922 HOptimizedGraphBuilder* owner_;
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000923
924 CompilationInfo* compilation_info_;
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000925
926 // During function inlining, expression context of the call being
927 // inlined. NULL when not inlining.
928 AstContext* call_context_;
929
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000930 // The kind of call which is currently being inlined.
931 InliningKind inlining_kind_;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000932
ulan@chromium.org967e2702012-02-28 09:49:15 +0000933 // When inlining in an effect or value context, this is the return block.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000934 // It is NULL otherwise. When inlining in a test context, there are a
935 // pair of return blocks in the context. When not inlining, there is no
936 // local return point.
937 HBasicBlock* function_return_;
938
939 // When inlining a call in a test context, a context containing a pair of
940 // return blocks. NULL in all other cases.
941 TestContext* test_context_;
942
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000943 // When inlining HEnterInlined instruction corresponding to the function
944 // entry.
945 HEnterInlined* entry_;
946
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000947 HArgumentsObject* arguments_object_;
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000948 HArgumentsElements* arguments_elements_;
949
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000950 FunctionState* outer_;
951};
952
953
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000954class HIfContinuation V8_FINAL {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000955 public:
machenbach@chromium.orgea468882013-11-18 08:53:19 +0000956 HIfContinuation()
957 : continuation_captured_(false),
958 true_branch_(NULL),
959 false_branch_(NULL) {}
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000960 HIfContinuation(HBasicBlock* true_branch,
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +0000961 HBasicBlock* false_branch)
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000962 : continuation_captured_(true), true_branch_(true_branch),
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +0000963 false_branch_(false_branch) {}
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000964 ~HIfContinuation() { ASSERT(!continuation_captured_); }
965
966 void Capture(HBasicBlock* true_branch,
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +0000967 HBasicBlock* false_branch) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000968 ASSERT(!continuation_captured_);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000969 true_branch_ = true_branch;
970 false_branch_ = false_branch;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000971 continuation_captured_ = true;
972 }
973
974 void Continue(HBasicBlock** true_branch,
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +0000975 HBasicBlock** false_branch) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000976 ASSERT(continuation_captured_);
977 *true_branch = true_branch_;
978 *false_branch = false_branch_;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000979 continuation_captured_ = false;
980 }
981
982 bool IsTrueReachable() { return true_branch_ != NULL; }
983 bool IsFalseReachable() { return false_branch_ != NULL; }
984 bool TrueAndFalseReachable() {
985 return IsTrueReachable() || IsFalseReachable();
986 }
987
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000988 HBasicBlock* true_branch() const { return true_branch_; }
989 HBasicBlock* false_branch() const { return false_branch_; }
990
991 private:
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000992 bool continuation_captured_;
993 HBasicBlock* true_branch_;
994 HBasicBlock* false_branch_;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000995};
996
997
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000998class HAllocationMode V8_FINAL BASE_EMBEDDED {
999 public:
1000 explicit HAllocationMode(Handle<AllocationSite> feedback_site)
1001 : current_site_(NULL), feedback_site_(feedback_site),
1002 pretenure_flag_(NOT_TENURED) {}
1003 explicit HAllocationMode(HValue* current_site)
1004 : current_site_(current_site), pretenure_flag_(NOT_TENURED) {}
1005 explicit HAllocationMode(PretenureFlag pretenure_flag)
1006 : current_site_(NULL), pretenure_flag_(pretenure_flag) {}
1007
1008 HValue* current_site() const { return current_site_; }
1009 Handle<AllocationSite> feedback_site() const { return feedback_site_; }
1010
1011 bool CreateAllocationMementos() const V8_WARN_UNUSED_RESULT {
1012 return current_site() != NULL;
1013 }
1014
1015 PretenureFlag GetPretenureMode() const V8_WARN_UNUSED_RESULT {
1016 if (!feedback_site().is_null()) return feedback_site()->GetPretenureMode();
1017 return pretenure_flag_;
1018 }
1019
1020 private:
1021 HValue* current_site_;
1022 Handle<AllocationSite> feedback_site_;
1023 PretenureFlag pretenure_flag_;
1024};
1025
1026
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001027class HGraphBuilder {
1028 public:
1029 explicit HGraphBuilder(CompilationInfo* info)
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001030 : info_(info),
1031 graph_(NULL),
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001032 current_block_(NULL),
1033 position_(RelocInfo::kNoPosition) {}
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001034 virtual ~HGraphBuilder() {}
1035
1036 HBasicBlock* current_block() const { return current_block_; }
1037 void set_current_block(HBasicBlock* block) { current_block_ = block; }
1038 HEnvironment* environment() const {
1039 return current_block()->last_environment();
1040 }
1041 Zone* zone() const { return info_->zone(); }
ulan@chromium.org750145a2013-03-07 15:14:13 +00001042 HGraph* graph() const { return graph_; }
1043 Isolate* isolate() const { return graph_->isolate(); }
danno@chromium.org41728482013-06-12 22:31:22 +00001044 CompilationInfo* top_info() { return info_; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001045
1046 HGraph* CreateGraph();
1047
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001048 // Bailout environment manipulation.
1049 void Push(HValue* value) { environment()->Push(value); }
1050 HValue* Pop() { return environment()->Pop(); }
1051
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001052 virtual HValue* context() = 0;
1053
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001054 // Adding instructions.
1055 HInstruction* AddInstruction(HInstruction* instr);
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001056 void FinishCurrentBlock(HControlInstruction* last);
1057 void FinishExitCurrentBlock(HControlInstruction* instruction);
1058
1059 void Goto(HBasicBlock* from,
1060 HBasicBlock* target,
1061 FunctionState* state = NULL,
1062 bool add_simulate = true) {
1063 from->Goto(target, position_, state, add_simulate);
1064 }
1065 void Goto(HBasicBlock* target,
1066 FunctionState* state = NULL,
1067 bool add_simulate = true) {
1068 Goto(current_block(), target, state, add_simulate);
1069 }
1070 void GotoNoSimulate(HBasicBlock* from, HBasicBlock* target) {
1071 Goto(from, target, NULL, false);
1072 }
1073 void GotoNoSimulate(HBasicBlock* target) {
1074 Goto(target, NULL, false);
1075 }
1076 void AddLeaveInlined(HBasicBlock* block,
1077 HValue* return_value,
1078 FunctionState* state) {
1079 block->AddLeaveInlined(return_value, state, position_);
1080 }
1081 void AddLeaveInlined(HValue* return_value, FunctionState* state) {
1082 return AddLeaveInlined(current_block(), return_value, state);
1083 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001084
1085 template<class I>
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001086 HInstruction* NewUncasted() { return I::New(zone(), context()); }
1087
1088 template<class I>
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001089 I* New() { return I::New(zone(), context()); }
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001090
1091 template<class I>
1092 HInstruction* AddUncasted() { return AddInstruction(NewUncasted<I>());}
1093
1094 template<class I>
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001095 I* Add() { return AddInstructionTyped(New<I>());}
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001096
1097 template<class I, class P1>
1098 HInstruction* NewUncasted(P1 p1) {
1099 return I::New(zone(), context(), p1);
1100 }
1101
1102 template<class I, class P1>
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001103 I* New(P1 p1) { return I::New(zone(), context(), p1); }
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001104
1105 template<class I, class P1>
1106 HInstruction* AddUncasted(P1 p1) {
1107 HInstruction* result = AddInstruction(NewUncasted<I>(p1));
1108 // Specializations must have their parameters properly casted
1109 // to avoid landing here.
1110 ASSERT(!result->IsReturn() && !result->IsSimulate() &&
1111 !result->IsDeoptimize());
1112 return result;
1113 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001114
1115 template<class I, class P1>
1116 I* Add(P1 p1) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001117 I* result = AddInstructionTyped(New<I>(p1));
1118 // Specializations must have their parameters properly casted
1119 // to avoid landing here.
1120 ASSERT(!result->IsReturn() && !result->IsSimulate() &&
1121 !result->IsDeoptimize());
1122 return result;
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001123 }
1124
1125 template<class I, class P1, class P2>
1126 HInstruction* NewUncasted(P1 p1, P2 p2) {
1127 return I::New(zone(), context(), p1, p2);
1128 }
1129
1130 template<class I, class P1, class P2>
1131 I* New(P1 p1, P2 p2) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001132 return I::New(zone(), context(), p1, p2);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001133 }
1134
1135 template<class I, class P1, class P2>
1136 HInstruction* AddUncasted(P1 p1, P2 p2) {
1137 HInstruction* result = AddInstruction(NewUncasted<I>(p1, p2));
1138 // Specializations must have their parameters properly casted
1139 // to avoid landing here.
1140 ASSERT(!result->IsSimulate());
1141 return result;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001142 }
1143
1144 template<class I, class P1, class P2>
1145 I* Add(P1 p1, P2 p2) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001146 I* result = AddInstructionTyped(New<I>(p1, p2));
1147 // Specializations must have their parameters properly casted
1148 // to avoid landing here.
1149 ASSERT(!result->IsSimulate());
1150 return result;
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001151 }
1152
1153 template<class I, class P1, class P2, class P3>
1154 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3) {
1155 return I::New(zone(), context(), p1, p2, p3);
1156 }
1157
1158 template<class I, class P1, class P2, class P3>
1159 I* New(P1 p1, P2 p2, P3 p3) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001160 return I::New(zone(), context(), p1, p2, p3);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001161 }
1162
1163 template<class I, class P1, class P2, class P3>
1164 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3) {
1165 return AddInstruction(NewUncasted<I>(p1, p2, p3));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001166 }
1167
1168 template<class I, class P1, class P2, class P3>
1169 I* Add(P1 p1, P2 p2, P3 p3) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001170 return AddInstructionTyped(New<I>(p1, p2, p3));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001171 }
1172
1173 template<class I, class P1, class P2, class P3, class P4>
1174 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
1175 return I::New(zone(), context(), p1, p2, p3, p4);
1176 }
1177
1178 template<class I, class P1, class P2, class P3, class P4>
1179 I* New(P1 p1, P2 p2, P3 p3, P4 p4) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001180 return I::New(zone(), context(), p1, p2, p3, p4);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001181 }
1182
1183 template<class I, class P1, class P2, class P3, class P4>
1184 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
1185 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001186 }
1187
1188 template<class I, class P1, class P2, class P3, class P4>
1189 I* Add(P1 p1, P2 p2, P3 p3, P4 p4) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001190 return AddInstructionTyped(New<I>(p1, p2, p3, p4));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001191 }
1192
1193 template<class I, class P1, class P2, class P3, class P4, class P5>
1194 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1195 return I::New(zone(), context(), p1, p2, p3, p4, p5);
1196 }
1197
1198 template<class I, class P1, class P2, class P3, class P4, class P5>
1199 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001200 return I::New(zone(), context(), p1, p2, p3, p4, p5);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001201 }
1202
1203 template<class I, class P1, class P2, class P3, class P4, class P5>
1204 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1205 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001206 }
1207
1208 template<class I, class P1, class P2, class P3, class P4, class P5>
1209 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001210 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001211 }
1212
1213 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1214 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1215 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6);
1216 }
1217
1218 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1219 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001220 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001221 }
1222
1223 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1224 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1225 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001226 }
1227
1228 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1229 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001230 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001231 }
1232
1233 template<class I, class P1, class P2, class P3, class P4,
1234 class P5, class P6, class P7>
1235 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1236 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7);
1237 }
1238
1239 template<class I, class P1, class P2, class P3, class P4,
1240 class P5, class P6, class P7>
1241 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001242 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001243 }
1244
1245 template<class I, class P1, class P2, class P3,
1246 class P4, class P5, class P6, class P7>
1247 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1248 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001249 }
1250
1251 template<class I, class P1, class P2, class P3,
1252 class P4, class P5, class P6, class P7>
1253 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001254 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001255 }
1256
1257 template<class I, class P1, class P2, class P3, class P4,
1258 class P5, class P6, class P7, class P8>
1259 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
1260 P5 p5, P6 p6, P7 p7, P8 p8) {
1261 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8);
1262 }
1263
1264 template<class I, class P1, class P2, class P3, class P4,
1265 class P5, class P6, class P7, class P8>
1266 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001267 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001268 }
1269
1270 template<class I, class P1, class P2, class P3, class P4,
1271 class P5, class P6, class P7, class P8>
1272 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
1273 P5 p5, P6 p6, P7 p7, P8 p8) {
1274 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001275 }
1276
1277 template<class I, class P1, class P2, class P3, class P4,
1278 class P5, class P6, class P7, class P8>
1279 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001280 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7, p8));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001281 }
1282
danno@chromium.orgad75d6f2013-08-12 16:57:59 +00001283 void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001284
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001285 int position() const { return position_; }
1286
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001287 protected:
1288 virtual bool BuildGraph() = 0;
1289
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001290 HBasicBlock* CreateBasicBlock(HEnvironment* env);
1291 HBasicBlock* CreateLoopHeaderBlock();
1292
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001293 HValue* BuildCheckHeapObject(HValue* object);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001294 HValue* BuildCheckMap(HValue* obj, Handle<Map> map);
machenbach@chromium.org90dca012013-11-22 10:04:21 +00001295 HValue* BuildCheckString(HValue* string);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001296 HValue* BuildWrapReceiver(HValue* object, HValue* function);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001297
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001298 // Building common constructs
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001299 HValue* BuildCheckForCapacityGrow(HValue* object,
1300 HValue* elements,
1301 ElementsKind kind,
1302 HValue* length,
1303 HValue* key,
hpayer@chromium.org71ea97f2013-12-19 16:03:26 +00001304 bool is_js_array,
1305 bool is_store);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001306
1307 HValue* BuildCopyElementsOnWrite(HValue* object,
1308 HValue* elements,
1309 ElementsKind kind,
1310 HValue* length);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001311
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00001312 void BuildTransitionElementsKind(HValue* object,
1313 HValue* map,
1314 ElementsKind from_kind,
1315 ElementsKind to_kind,
1316 bool is_jsarray);
1317
bmeurer@chromium.orge7a07452013-10-21 13:27:29 +00001318 HValue* BuildNumberToString(HValue* object, Handle<Type> type);
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +00001319
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001320 HValue* BuildUncheckedDictionaryElementLoad(HValue* receiver,
1321 HValue* key);
1322
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001323 // Allocates a new object according with the given allocation properties.
1324 HAllocate* BuildAllocate(HValue* object_size,
1325 HType type,
1326 InstanceType instance_type,
1327 HAllocationMode allocation_mode);
1328 // Computes the sum of two string lengths, taking care of overflow handling.
1329 HValue* BuildAddStringLengths(HValue* left_length, HValue* right_length);
1330 // Creates a cons string using the two input strings.
1331 HValue* BuildCreateConsString(HValue* length,
1332 HValue* left,
1333 HValue* right,
1334 HAllocationMode allocation_mode);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00001335 // Copies characters from one sequential string to another.
1336 void BuildCopySeqStringChars(HValue* src,
1337 HValue* src_offset,
1338 String::Encoding src_encoding,
1339 HValue* dst,
1340 HValue* dst_offset,
1341 String::Encoding dst_encoding,
1342 HValue* length);
1343 // Both operands are non-empty strings.
1344 HValue* BuildUncheckedStringAdd(HValue* left,
1345 HValue* right,
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001346 HAllocationMode allocation_mode);
1347 // Add two strings using allocation mode, validating type feedback.
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00001348 HValue* BuildStringAdd(HValue* left,
1349 HValue* right,
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001350 HAllocationMode allocation_mode);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00001351
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001352 HInstruction* BuildUncheckedMonomorphicElementAccess(
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001353 HValue* checked_object,
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001354 HValue* key,
1355 HValue* val,
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001356 bool is_js_array,
1357 ElementsKind elements_kind,
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00001358 bool is_store,
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001359 LoadKeyedHoleMode load_mode,
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001360 KeyedAccessStoreMode store_mode);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001361
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +00001362 HInstruction* AddElementAccess(
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00001363 HValue* elements,
1364 HValue* checked_key,
1365 HValue* val,
1366 HValue* dependency,
1367 ElementsKind elements_kind,
1368 bool is_store,
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +00001369 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE);
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00001370
verwaest@chromium.orgec6855e2013-08-22 12:26:58 +00001371 HLoadNamedField* BuildLoadNamedField(HValue* object, HObjectAccess access);
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +00001372 HInstruction* AddLoadNamedField(HValue* object, HObjectAccess access);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001373 HInstruction* AddLoadStringInstanceType(HValue* string);
1374 HInstruction* AddLoadStringLength(HValue* string);
1375 HStoreNamedField* AddStoreMapNoWriteBarrier(HValue* object, HValue* map) {
1376 HStoreNamedField* store_map = Add<HStoreNamedField>(
1377 object, HObjectAccess::ForMap(), map);
1378 store_map->SkipWriteBarrier();
1379 return store_map;
1380 }
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00001381 HStoreNamedField* AddStoreMapConstant(HValue* object, Handle<Map> map);
1382 HStoreNamedField* AddStoreMapConstantNoWriteBarrier(HValue* object,
1383 Handle<Map> map) {
1384 HStoreNamedField* store_map = AddStoreMapConstant(object, map);
1385 store_map->SkipWriteBarrier();
1386 return store_map;
1387 }
verwaest@chromium.orgec6855e2013-08-22 12:26:58 +00001388 HLoadNamedField* AddLoadElements(HValue* object);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001389
1390 bool MatchRotateRight(HValue* left,
1391 HValue* right,
1392 HValue** operand,
1393 HValue** shift_amount);
1394
machenbach@chromium.org7ff76072013-11-21 09:47:43 +00001395 HValue* BuildBinaryOperation(Token::Value op,
1396 HValue* left,
1397 HValue* right,
1398 Handle<Type> left_type,
1399 Handle<Type> right_type,
1400 Handle<Type> result_type,
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001401 Maybe<int> fixed_right_arg,
1402 HAllocationMode allocation_mode);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001403
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00001404 HLoadNamedField* AddLoadFixedArrayLength(HValue *object);
1405
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001406 HValue* AddLoadJSBuiltin(Builtins::JavaScript builtin);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001407
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001408 HValue* EnforceNumberType(HValue* number, Handle<Type> expected);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001409 HValue* TruncateToNumber(HValue* value, Handle<Type>* expected);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001410
danno@chromium.org59400602013-08-13 17:09:37 +00001411 void FinishExitWithHardDeoptimization(const char* reason,
1412 HBasicBlock* continuation);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001413
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001414 void AddIncrementCounter(StatsCounter* counter);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001415
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001416 class IfBuilder V8_FINAL {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001417 public:
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001418 explicit IfBuilder(HGraphBuilder* builder);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001419 IfBuilder(HGraphBuilder* builder,
1420 HIfContinuation* continuation);
1421
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001422 ~IfBuilder() {
1423 if (!finished_) End();
1424 }
1425
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001426 template<class Condition>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001427 Condition* If(HValue *p) {
1428 Condition* compare = builder()->New<Condition>(p);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001429 AddCompare(compare);
1430 return compare;
1431 }
1432
1433 template<class Condition, class P2>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001434 Condition* If(HValue* p1, P2 p2) {
1435 Condition* compare = builder()->New<Condition>(p1, p2);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001436 AddCompare(compare);
1437 return compare;
1438 }
1439
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001440 template<class Condition, class P2, class P3>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001441 Condition* If(HValue* p1, P2 p2, P3 p3) {
1442 Condition* compare = builder()->New<Condition>(p1, p2, p3);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001443 AddCompare(compare);
1444 return compare;
1445 }
1446
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001447 template<class Condition>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001448 Condition* IfNot(HValue* p) {
1449 Condition* compare = If<Condition>(p);
1450 compare->Not();
1451 return compare;
1452 }
1453
1454 template<class Condition, class P2>
1455 Condition* IfNot(HValue* p1, P2 p2) {
1456 Condition* compare = If<Condition>(p1, p2);
1457 compare->Not();
1458 return compare;
1459 }
1460
1461 template<class Condition, class P2, class P3>
1462 Condition* IfNot(HValue* p1, P2 p2, P3 p3) {
1463 Condition* compare = If<Condition>(p1, p2, p3);
1464 compare->Not();
1465 return compare;
1466 }
1467
1468 template<class Condition>
1469 Condition* OrIf(HValue *p) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001470 Or();
1471 return If<Condition>(p);
1472 }
1473
1474 template<class Condition, class P2>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001475 Condition* OrIf(HValue* p1, P2 p2) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001476 Or();
1477 return If<Condition>(p1, p2);
1478 }
1479
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001480 template<class Condition, class P2, class P3>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001481 Condition* OrIf(HValue* p1, P2 p2, P3 p3) {
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001482 Or();
1483 return If<Condition>(p1, p2, p3);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001484 }
1485
1486 template<class Condition>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001487 Condition* AndIf(HValue *p) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001488 And();
1489 return If<Condition>(p);
1490 }
1491
1492 template<class Condition, class P2>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001493 Condition* AndIf(HValue* p1, P2 p2) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001494 And();
1495 return If<Condition>(p1, p2);
1496 }
1497
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001498 template<class Condition, class P2, class P3>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001499 Condition* AndIf(HValue* p1, P2 p2, P3 p3) {
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001500 And();
1501 return If<Condition>(p1, p2, p3);
1502 }
1503
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001504 void Or();
1505 void And();
1506
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001507 // Captures the current state of this IfBuilder in the specified
1508 // continuation and ends this IfBuilder.
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001509 void CaptureContinuation(HIfContinuation* continuation);
1510
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001511 // Joins the specified continuation from this IfBuilder and ends this
1512 // IfBuilder. This appends a Goto instruction from the true branch of
1513 // this IfBuilder to the true branch of the continuation unless the
1514 // true branch of this IfBuilder is already finished. And vice versa
1515 // for the false branch.
1516 //
1517 // The basic idea is as follows: You have several nested IfBuilder's
1518 // that you want to join based on two possible outcomes (i.e. success
1519 // and failure, or whatever). You can do this easily using this method
1520 // now, for example:
1521 //
1522 // HIfContinuation cont(graph()->CreateBasicBlock(),
1523 // graph()->CreateBasicBlock());
1524 // ...
1525 // IfBuilder if_whatever(this);
1526 // if_whatever.If<Condition>(arg);
1527 // if_whatever.Then();
1528 // ...
1529 // if_whatever.Else();
1530 // ...
1531 // if_whatever.JoinContinuation(&cont);
1532 // ...
1533 // IfBuilder if_something(this);
1534 // if_something.If<Condition>(arg1, arg2);
1535 // if_something.Then();
1536 // ...
1537 // if_something.Else();
1538 // ...
1539 // if_something.JoinContinuation(&cont);
1540 // ...
1541 // IfBuilder if_finally(this, &cont);
1542 // if_finally.Then();
1543 // // continues after then code of if_whatever or if_something.
1544 // ...
1545 // if_finally.Else();
1546 // // continues after else code of if_whatever or if_something.
1547 // ...
1548 // if_finally.End();
1549 void JoinContinuation(HIfContinuation* continuation);
1550
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001551 void Then();
1552 void Else();
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001553 void End();
1554
danno@chromium.org59400602013-08-13 17:09:37 +00001555 void Deopt(const char* reason);
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001556 void ThenDeopt(const char* reason) {
1557 Then();
1558 Deopt(reason);
1559 }
danno@chromium.org59400602013-08-13 17:09:37 +00001560 void ElseDeopt(const char* reason) {
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00001561 Else();
danno@chromium.org59400602013-08-13 17:09:37 +00001562 Deopt(reason);
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00001563 }
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001564
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001565 void Return(HValue* value);
1566
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001567 private:
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001568 HControlInstruction* AddCompare(HControlInstruction* compare);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001569
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001570 HGraphBuilder* builder() const { return builder_; }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001571
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001572 void AddMergeAtJoinBlock(bool deopt);
1573
1574 void Finish();
1575 void Finish(HBasicBlock** then_continuation,
1576 HBasicBlock** else_continuation);
1577
1578 class MergeAtJoinBlock : public ZoneObject {
1579 public:
1580 MergeAtJoinBlock(HBasicBlock* block,
1581 bool deopt,
1582 MergeAtJoinBlock* next)
1583 : block_(block),
1584 deopt_(deopt),
1585 next_(next) {}
1586 HBasicBlock* block_;
1587 bool deopt_;
1588 MergeAtJoinBlock* next_;
1589 };
1590
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001591 HGraphBuilder* builder_;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001592 bool finished_ : 1;
1593 bool did_then_ : 1;
1594 bool did_else_ : 1;
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001595 bool did_else_if_ : 1;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001596 bool did_and_ : 1;
1597 bool did_or_ : 1;
1598 bool captured_ : 1;
1599 bool needs_compare_ : 1;
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001600 bool pending_merge_block_ : 1;
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001601 HBasicBlock* first_true_block_;
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001602 HBasicBlock* first_false_block_;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001603 HBasicBlock* split_edge_merge_block_;
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001604 MergeAtJoinBlock* merge_at_join_blocks_;
1605 int normal_merge_at_join_block_count_;
1606 int deopt_merge_at_join_block_count_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001607 };
1608
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001609 class LoopBuilder V8_FINAL {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001610 public:
1611 enum Direction {
1612 kPreIncrement,
1613 kPostIncrement,
1614 kPreDecrement,
1615 kPostDecrement
1616 };
1617
1618 LoopBuilder(HGraphBuilder* builder,
1619 HValue* context,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001620 Direction direction);
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001621 LoopBuilder(HGraphBuilder* builder,
1622 HValue* context,
1623 Direction direction,
1624 HValue* increment_amount);
1625
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001626 ~LoopBuilder() {
1627 ASSERT(finished_);
1628 }
1629
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001630 HValue* BeginBody(
1631 HValue* initial,
1632 HValue* terminating,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00001633 Token::Value token);
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001634
1635 void Break();
1636
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001637 void EndBody();
1638
1639 private:
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001640 Zone* zone() { return builder_->zone(); }
1641
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001642 HGraphBuilder* builder_;
1643 HValue* context_;
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001644 HValue* increment_amount_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001645 HInstruction* increment_;
1646 HPhi* phi_;
1647 HBasicBlock* header_block_;
1648 HBasicBlock* body_block_;
1649 HBasicBlock* exit_block_;
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001650 HBasicBlock* exit_trampoline_block_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001651 Direction direction_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001652 bool finished_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001653 };
1654
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001655 HValue* BuildNewElementsCapacity(HValue* old_capacity);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001656
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001657 void BuildNewSpaceArrayCheck(HValue* length,
1658 ElementsKind kind);
1659
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001660 class JSArrayBuilder V8_FINAL {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001661 public:
1662 JSArrayBuilder(HGraphBuilder* builder,
1663 ElementsKind kind,
1664 HValue* allocation_site_payload,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001665 HValue* constructor_function,
1666 AllocationSiteOverrideMode override_mode);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001667
1668 JSArrayBuilder(HGraphBuilder* builder,
1669 ElementsKind kind,
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001670 HValue* constructor_function = NULL);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001671
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +00001672 enum FillMode {
1673 DONT_FILL_WITH_HOLE,
1674 FILL_WITH_HOLE
1675 };
1676
1677 ElementsKind kind() { return kind_; }
1678
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001679 HValue* AllocateEmptyArray();
1680 HValue* AllocateArray(HValue* capacity, HValue* length_field,
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +00001681 FillMode fill_mode = FILL_WITH_HOLE);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001682 HValue* GetElementsLocation() { return elements_location_; }
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001683 HValue* EmitMapCode();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001684
1685 private:
1686 Zone* zone() const { return builder_->zone(); }
1687 int elements_size() const {
1688 return IsFastDoubleElementsKind(kind_) ? kDoubleSize : kPointerSize;
1689 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001690 HGraphBuilder* builder() { return builder_; }
1691 HGraph* graph() { return builder_->graph(); }
1692 int initial_capacity() {
1693 STATIC_ASSERT(JSArray::kPreallocatedArrayElements > 0);
1694 return JSArray::kPreallocatedArrayElements;
1695 }
1696
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001697 HValue* EmitInternalMapCode();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001698 HValue* EstablishEmptyArrayAllocationSize();
1699 HValue* EstablishAllocationSize(HValue* length_node);
1700 HValue* AllocateArray(HValue* size_in_bytes, HValue* capacity,
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +00001701 HValue* length_field,
1702 FillMode fill_mode = FILL_WITH_HOLE);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001703
1704 HGraphBuilder* builder_;
1705 ElementsKind kind_;
1706 AllocationSiteMode mode_;
1707 HValue* allocation_site_payload_;
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001708 HValue* constructor_function_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001709 HInnerAllocatedObject* elements_location_;
1710 };
1711
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +00001712 HValue* BuildAllocateArrayFromLength(JSArrayBuilder* array_builder,
1713 HValue* length_argument);
1714
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001715 HValue* BuildAllocateElements(ElementsKind kind,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001716 HValue* capacity);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001717
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001718 void BuildInitializeElementsHeader(HValue* elements,
1719 ElementsKind kind,
1720 HValue* capacity);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001721
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001722 HValue* BuildAllocateElementsAndInitializeElementsHeader(ElementsKind kind,
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001723 HValue* capacity);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001724
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001725 // array must have been allocated with enough room for
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00001726 // 1) the JSArray, 2) a AllocationMemento if mode requires it,
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001727 // 3) a FixedArray or FixedDoubleArray.
1728 // A pointer to the Fixed(Double)Array is returned.
1729 HInnerAllocatedObject* BuildJSArrayHeader(HValue* array,
1730 HValue* array_map,
1731 AllocationSiteMode mode,
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001732 ElementsKind elements_kind,
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001733 HValue* allocation_site_payload,
1734 HValue* length_field);
1735
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001736 HValue* BuildGrowElementsCapacity(HValue* object,
1737 HValue* elements,
1738 ElementsKind kind,
danno@chromium.orgbee51992013-07-10 14:57:15 +00001739 ElementsKind new_kind,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001740 HValue* length,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001741 HValue* new_capacity);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001742
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001743 void BuildFillElementsWithHole(HValue* elements,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001744 ElementsKind elements_kind,
1745 HValue* from,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001746 HValue* to);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001747
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001748 void BuildCopyElements(HValue* from_elements,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001749 ElementsKind from_elements_kind,
1750 HValue* to_elements,
1751 ElementsKind to_elements_kind,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001752 HValue* length,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001753 HValue* capacity);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001754
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001755 HValue* BuildCloneShallowArray(HValue* boilerplate,
danno@chromium.orgbee51992013-07-10 14:57:15 +00001756 HValue* allocation_site,
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001757 AllocationSiteMode mode,
1758 ElementsKind kind,
1759 int length);
1760
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001761 HValue* BuildElementIndexHash(HValue* index);
1762
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001763 void BuildCompareNil(
1764 HValue* value,
danno@chromium.org41728482013-06-12 22:31:22 +00001765 Handle<Type> type,
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001766 HIfContinuation* continuation);
1767
machenbach@chromium.orgce9c5142013-12-03 08:00:39 +00001768 void BuildCreateAllocationMemento(HValue* previous_object,
1769 HValue* previous_object_size,
1770 HValue* payload);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001771
verwaest@chromium.orgec6855e2013-08-22 12:26:58 +00001772 HInstruction* BuildConstantMapCheck(Handle<JSObject> constant,
1773 CompilationInfo* info);
1774 HInstruction* BuildCheckPrototypeMaps(Handle<JSObject> prototype,
1775 Handle<JSObject> holder);
danno@chromium.org59400602013-08-13 17:09:37 +00001776
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001777 HInstruction* BuildGetNativeContext();
1778 HInstruction* BuildGetArrayFunction();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001779
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001780 protected:
1781 void SetSourcePosition(int position) {
1782 ASSERT(position != RelocInfo::kNoPosition);
1783 position_ = position;
1784 }
1785
machenbach@chromium.org37be4082013-11-26 13:50:38 +00001786 template <typename ViewClass>
1787 void BuildArrayBufferViewInitialization(HValue* obj,
1788 HValue* buffer,
1789 HValue* byte_offset,
1790 HValue* byte_length);
1791
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001792 private:
1793 HGraphBuilder();
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001794
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001795 HValue* BuildUncheckedDictionaryElementLoadHelper(
1796 HValue* elements,
1797 HValue* key,
1798 HValue* hash,
1799 HValue* mask,
1800 int current_probe);
1801
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001802 void PadEnvironmentForContinuation(HBasicBlock* from,
1803 HBasicBlock* continuation);
1804
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001805 template <class I>
1806 I* AddInstructionTyped(I* instr) {
1807 return I::cast(AddInstruction(instr));
1808 }
1809
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001810 CompilationInfo* info_;
1811 HGraph* graph_;
1812 HBasicBlock* current_block_;
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001813 int position_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001814};
1815
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001816
1817template<>
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001818inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>(
danno@chromium.org59400602013-08-13 17:09:37 +00001819 const char* reason, Deoptimizer::BailoutType type) {
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001820 if (type == Deoptimizer::SOFT) {
1821 isolate()->counters()->soft_deopts_requested()->Increment();
1822 if (FLAG_always_opt) return NULL;
1823 }
1824 if (current_block()->IsDeoptimizing()) return NULL;
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001825 HBasicBlock* after_deopt_block = CreateBasicBlock(
1826 current_block()->last_environment());
1827 HDeoptimize* instr = New<HDeoptimize>(reason, type, after_deopt_block);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001828 if (type == Deoptimizer::SOFT) {
1829 isolate()->counters()->soft_deopts_inserted()->Increment();
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001830 }
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001831 FinishCurrentBlock(instr);
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001832 set_current_block(after_deopt_block);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001833 return instr;
1834}
1835
1836
1837template<>
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001838inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>(
danno@chromium.org59400602013-08-13 17:09:37 +00001839 const char* reason, Deoptimizer::BailoutType type) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001840 return Add<HDeoptimize>(reason, type);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001841}
1842
1843
1844template<>
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001845inline HSimulate* HGraphBuilder::Add<HSimulate>(
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001846 BailoutId id,
1847 RemovableSimulate removable) {
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001848 HSimulate* instr = current_block()->CreateSimulate(id, removable);
1849 AddInstruction(instr);
1850 return instr;
1851}
1852
1853
1854template<>
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001855inline HSimulate* HGraphBuilder::Add<HSimulate>(
1856 BailoutId id) {
1857 return Add<HSimulate>(id, FIXED_SIMULATE);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001858}
1859
1860
1861template<>
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001862inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(BailoutId id) {
1863 return Add<HSimulate>(id, FIXED_SIMULATE);
1864}
1865
1866
1867template<>
1868inline HReturn* HGraphBuilder::Add<HReturn>(HValue* value) {
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001869 int num_parameters = graph()->info()->num_parameters();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001870 HValue* params = AddUncasted<HConstant>(num_parameters);
1871 HReturn* return_instruction = New<HReturn>(value, params);
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001872 FinishExitCurrentBlock(return_instruction);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001873 return return_instruction;
1874}
1875
1876
1877template<>
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001878inline HReturn* HGraphBuilder::Add<HReturn>(HConstant* value) {
1879 return Add<HReturn>(static_cast<HValue*>(value));
1880}
1881
1882template<>
1883inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HValue* value) {
1884 return Add<HReturn>(value);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001885}
1886
1887
1888template<>
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001889inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HConstant* value) {
1890 return Add<HReturn>(value);
1891}
1892
1893
1894template<>
1895inline HCallRuntime* HGraphBuilder::Add<HCallRuntime>(
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +00001896 Handle<String> name,
1897 const Runtime::Function* c_function,
1898 int argument_count) {
1899 HCallRuntime* instr = New<HCallRuntime>(name, c_function, argument_count);
1900 if (graph()->info()->IsStub()) {
1901 // When compiling code stubs, we don't want to save all double registers
1902 // upon entry to the stub, but instead have the call runtime instruction
1903 // save the double registers only on-demand (in the fallback case).
1904 instr->set_save_doubles(kSaveFPRegs);
1905 }
1906 AddInstruction(instr);
1907 return instr;
1908}
1909
1910
1911template<>
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001912inline HInstruction* HGraphBuilder::AddUncasted<HCallRuntime>(
1913 Handle<String> name,
1914 const Runtime::Function* c_function,
1915 int argument_count) {
1916 return Add<HCallRuntime>(name, c_function, argument_count);
1917}
1918
1919
1920template<>
1921inline HContext* HGraphBuilder::New<HContext>() {
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001922 return HContext::New(zone());
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001923}
1924
1925
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00001926template<>
1927inline HInstruction* HGraphBuilder::NewUncasted<HContext>() {
1928 return New<HContext>();
1929}
1930
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001931class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001932 public:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001933 // A class encapsulating (lazily-allocated) break and continue blocks for
1934 // a breakable statement. Separated from BreakAndContinueScope so that it
1935 // can have a separate lifetime.
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001936 class BreakAndContinueInfo V8_FINAL BASE_EMBEDDED {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001937 public:
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001938 explicit BreakAndContinueInfo(BreakableStatement* target,
1939 int drop_extra = 0)
1940 : target_(target),
1941 break_block_(NULL),
1942 continue_block_(NULL),
1943 drop_extra_(drop_extra) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001944 }
1945
1946 BreakableStatement* target() { return target_; }
1947 HBasicBlock* break_block() { return break_block_; }
1948 void set_break_block(HBasicBlock* block) { break_block_ = block; }
1949 HBasicBlock* continue_block() { return continue_block_; }
1950 void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001951 int drop_extra() { return drop_extra_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001952
1953 private:
1954 BreakableStatement* target_;
1955 HBasicBlock* break_block_;
1956 HBasicBlock* continue_block_;
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001957 int drop_extra_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001958 };
1959
1960 // A helper class to maintain a stack of current BreakAndContinueInfo
1961 // structures mirroring BreakableStatement nesting.
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001962 class BreakAndContinueScope V8_FINAL BASE_EMBEDDED {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001963 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001964 BreakAndContinueScope(BreakAndContinueInfo* info,
1965 HOptimizedGraphBuilder* owner)
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001966 : info_(info), owner_(owner), next_(owner->break_scope()) {
1967 owner->set_break_scope(this);
1968 }
1969
1970 ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
1971
1972 BreakAndContinueInfo* info() { return info_; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001973 HOptimizedGraphBuilder* owner() { return owner_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001974 BreakAndContinueScope* next() { return next_; }
1975
1976 // Search the break stack for a break or continue target.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001977 enum BreakType { BREAK, CONTINUE };
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001978 HBasicBlock* Get(BreakableStatement* stmt, BreakType type, int* drop_extra);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001979
1980 private:
1981 BreakAndContinueInfo* info_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001982 HOptimizedGraphBuilder* owner_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001983 BreakAndContinueScope* next_;
1984 };
1985
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001986 explicit HOptimizedGraphBuilder(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001987
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001988 virtual bool BuildGraph() V8_OVERRIDE;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001989
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001990 // Simple accessors.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001991 BreakAndContinueScope* break_scope() const { return break_scope_; }
1992 void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001993
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001994 bool inline_bailout() { return inline_bailout_; }
1995
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001996 HValue* context() { return environment()->context(); }
1997
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00001998 HOsrBuilder* osr() const { return osr_; }
1999
danno@chromium.org59400602013-08-13 17:09:37 +00002000 void Bailout(BailoutReason reason);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00002001
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002002 HBasicBlock* CreateJoin(HBasicBlock* first,
2003 HBasicBlock* second,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002004 BailoutId join_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002005
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002006 FunctionState* function_state() const { return function_state_; }
2007
yangguo@chromium.org56454712012-02-16 15:33:53 +00002008 void VisitDeclarations(ZoneList<Declaration*>* declarations);
2009
verwaest@chromium.org178fb152012-07-18 11:21:48 +00002010 void* operator new(size_t size, Zone* zone) {
2011 return zone->New(static_cast<int>(size));
2012 }
yangguo@chromium.org304cc332012-07-24 07:59:48 +00002013 void operator delete(void* pointer, Zone* zone) { }
2014 void operator delete(void* pointer) { }
verwaest@chromium.org178fb152012-07-18 11:21:48 +00002015
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002016 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
2017
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00002018 protected:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002019 // Type of a member function that generates inline code for a native function.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002020 typedef void (HOptimizedGraphBuilder::*InlineFunctionGenerator)
2021 (CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002022
2023 // Forward declarations for inner scope classes.
2024 class SubgraphScope;
2025
2026 static const InlineFunctionGenerator kInlineFunctionGenerators[];
2027
2028 static const int kMaxCallPolymorphism = 4;
2029 static const int kMaxLoadPolymorphism = 4;
2030 static const int kMaxStorePolymorphism = 4;
2031
danno@chromium.orgfa458e42012-02-01 10:48:36 +00002032 // Even in the 'unlimited' case we have to have some limit in order not to
2033 // overflow the stack.
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +00002034 static const int kUnlimitedMaxInlinedSourceSize = 100000;
2035 static const int kUnlimitedMaxInlinedNodes = 10000;
2036 static const int kUnlimitedMaxInlinedNodesCumulative = 10000;
danno@chromium.orgfa458e42012-02-01 10:48:36 +00002037
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002038 // Maximum depth and total number of elements and properties for literal
2039 // graphs to be considered for fast deep-copying.
2040 static const int kMaxFastLiteralDepth = 3;
2041 static const int kMaxFastLiteralProperties = 8;
2042
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002043 // Simple accessors.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002044 void set_function_state(FunctionState* state) { function_state_ = state; }
2045
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002046 AstContext* ast_context() const { return ast_context_; }
2047 void set_ast_context(AstContext* context) { ast_context_ = context; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002048
2049 // Accessors forwarded to the function state.
danno@chromium.org41728482013-06-12 22:31:22 +00002050 CompilationInfo* current_info() const {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002051 return function_state()->compilation_info();
2052 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002053 AstContext* call_context() const {
2054 return function_state()->call_context();
2055 }
2056 HBasicBlock* function_return() const {
2057 return function_state()->function_return();
2058 }
2059 TestContext* inlined_test_context() const {
2060 return function_state()->test_context();
2061 }
2062 void ClearInlinedTestContext() {
2063 function_state()->ClearInlinedTestContext();
2064 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002065 StrictModeFlag function_strict_mode_flag() {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002066 return function_state()->compilation_info()->is_classic_mode()
2067 ? kNonStrictMode : kStrictMode;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00002068 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002069
2070 // Generators for inline runtime functions.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002071#define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002072 void Generate##Name(CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002073
2074 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
2075 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
2076#undef INLINE_FUNCTION_GENERATOR_DECLARATION
2077
karlklose@chromium.org83a47282011-05-11 11:54:09 +00002078 void VisitDelete(UnaryOperation* expr);
2079 void VisitVoid(UnaryOperation* expr);
2080 void VisitTypeof(UnaryOperation* expr);
karlklose@chromium.org83a47282011-05-11 11:54:09 +00002081 void VisitNot(UnaryOperation* expr);
2082
2083 void VisitComma(BinaryOperation* expr);
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00002084 void VisitLogicalExpression(BinaryOperation* expr);
2085 void VisitArithmeticExpression(BinaryOperation* expr);
karlklose@chromium.org83a47282011-05-11 11:54:09 +00002086
rossberg@chromium.org2c067b12012-03-19 11:01:52 +00002087 bool PreProcessOsrEntry(IterationStatement* statement);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002088 void VisitLoopBody(IterationStatement* stmt,
ager@chromium.org04921a82011-06-27 13:21:41 +00002089 HBasicBlock* loop_entry,
2090 BreakAndContinueInfo* break_info);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +00002091
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002092 // Create a back edge in the flow graph. body_exit is the predecessor
2093 // block and loop_entry is the successor block. loop_successor is the
2094 // block where control flow exits the loop normally (e.g., via failure of
2095 // the condition) and break_block is the block where control flow breaks
2096 // from the loop. All blocks except loop_entry can be NULL. The return
2097 // value is the new successor block which is the join of loop_successor
2098 // and break_block, or NULL.
2099 HBasicBlock* CreateLoop(IterationStatement* statement,
2100 HBasicBlock* loop_entry,
2101 HBasicBlock* body_exit,
2102 HBasicBlock* loop_successor,
2103 HBasicBlock* break_block);
2104
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00002105 // Build a loop entry
2106 HBasicBlock* BuildLoopEntry();
2107
2108 // Builds a loop entry respectful of OSR requirements
2109 HBasicBlock* BuildLoopEntry(IterationStatement* statement);
2110
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +00002111 HBasicBlock* JoinContinue(IterationStatement* statement,
2112 HBasicBlock* exit_block,
2113 HBasicBlock* continue_block);
2114
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002115 HValue* Top() const { return environment()->Top(); }
2116 void Drop(int n) { environment()->Drop(n); }
2117 void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002118 bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var,
2119 int index,
2120 HValue* value,
2121 HEnvironment* env) {
2122 if (!FLAG_analyze_environment_liveness) return false;
2123 // |this| and |arguments| are always live; zapping parameters isn't
2124 // safe because function.arguments can inspect them at any time.
2125 return !var->is_this() &&
2126 !var->is_arguments() &&
2127 !value->IsArgumentsObject() &&
2128 env->is_local_index(index);
2129 }
2130 void BindIfLive(Variable* var, HValue* value) {
2131 HEnvironment* env = environment();
2132 int index = env->IndexFor(var);
2133 env->Bind(index, value);
2134 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
2135 HEnvironmentMarker* bind =
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +00002136 Add<HEnvironmentMarker>(HEnvironmentMarker::BIND, index);
2137 USE(bind);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002138#ifdef DEBUG
2139 bind->set_closure(env->closure());
2140#endif
2141 }
2142 }
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +00002143
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002144 HValue* LookupAndMakeLive(Variable* var) {
2145 HEnvironment* env = environment();
2146 int index = env->IndexFor(var);
2147 HValue* value = env->Lookup(index);
2148 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
2149 HEnvironmentMarker* lookup =
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +00002150 Add<HEnvironmentMarker>(HEnvironmentMarker::LOOKUP, index);
2151 USE(lookup);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002152#ifdef DEBUG
2153 lookup->set_closure(env->closure());
2154#endif
2155 }
2156 return value;
2157 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002158
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00002159 // The value of the arguments object is allowed in some but not most value
2160 // contexts. (It's allowed in all effect contexts and disallowed in all
2161 // test contexts.)
2162 void VisitForValue(Expression* expr,
2163 ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002164 void VisitForTypeOf(Expression* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002165 void VisitForEffect(Expression* expr);
2166 void VisitForControl(Expression* expr,
2167 HBasicBlock* true_block,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002168 HBasicBlock* false_block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002169
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002170 // Visit an argument subexpression and emit a push to the outgoing arguments.
2171 void VisitArgument(Expression* expr);
vegorov@chromium.org3cf47312011-06-29 13:20:01 +00002172
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002173 void VisitArgumentList(ZoneList<Expression*>* arguments);
2174
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002175 // Visit a list of expressions from left to right, each in a value context.
2176 void VisitExpressions(ZoneList<Expression*>* exprs);
2177
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002178 // Remove the arguments from the bailout environment and emit instructions
2179 // to push them as outgoing parameters.
ulan@chromium.org967e2702012-02-28 09:49:15 +00002180 template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002181
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00002182 void SetUpScope(Scope* scope);
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00002183 virtual void VisitStatements(ZoneList<Statement*>* statements) V8_OVERRIDE;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002184
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00002185#define DECLARE_VISIT(type) virtual void Visit##type(type* node) V8_OVERRIDE;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002186 AST_NODE_LIST(DECLARE_VISIT)
2187#undef DECLARE_VISIT
2188
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00002189 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002190 // Helpers for flow graph construction.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002191 enum GlobalPropertyAccess {
2192 kUseCell,
2193 kUseGeneric
2194 };
2195 GlobalPropertyAccess LookupGlobalProperty(Variable* var,
2196 LookupResult* lookup,
2197 bool is_store);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002198
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002199 void EnsureArgumentsArePushedForAccess();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002200 bool TryArgumentsAccess(Property* expr);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00002201
2202 // Try to optimize fun.apply(receiver, arguments) pattern.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002203 bool TryCallApply(Call* expr);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00002204
jkummerow@chromium.org212d9642012-05-11 15:02:09 +00002205 int InliningAstSize(Handle<JSFunction> target);
ulan@chromium.org967e2702012-02-28 09:49:15 +00002206 bool TryInline(CallKind call_kind,
2207 Handle<JSFunction> target,
yangguo@chromium.org304cc332012-07-24 07:59:48 +00002208 int arguments_count,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002209 HValue* implicit_return_value,
2210 BailoutId ast_id,
2211 BailoutId return_id,
2212 InliningKind inlining_kind);
ulan@chromium.org967e2702012-02-28 09:49:15 +00002213
2214 bool TryInlineCall(Call* expr, bool drop_extra = false);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002215 bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +00002216 bool TryInlineGetter(Handle<JSFunction> getter,
2217 BailoutId ast_id,
2218 BailoutId return_id);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002219 bool TryInlineSetter(Handle<JSFunction> setter,
danno@chromium.orgb0deb652013-06-20 16:20:19 +00002220 BailoutId id,
2221 BailoutId assignment_id,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002222 HValue* implicit_return_value);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +00002223 bool TryInlineApply(Handle<JSFunction> function,
2224 Call* expr,
2225 int arguments_count);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00002226 bool TryInlineBuiltinMethodCall(Call* expr,
ulan@chromium.org967e2702012-02-28 09:49:15 +00002227 HValue* receiver,
2228 Handle<Map> receiver_map,
2229 CheckType check_type);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00002230 bool TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002231
2232 // If --trace-inlining, print a line of the inlining trace. Inlining
2233 // succeeded if the reason string is NULL and failed if there is a
2234 // non-NULL reason string.
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002235 void TraceInline(Handle<JSFunction> target,
2236 Handle<JSFunction> caller,
2237 const char* failure_reason);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002238
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002239 void HandleGlobalVariableAssignment(Variable* var,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002240 HValue* value,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002241 BailoutId ast_id);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002242
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002243 void HandlePropertyAssignment(Assignment* expr);
2244 void HandleCompoundAssignment(Assignment* expr);
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00002245 void HandlePolymorphicLoadNamedField(BailoutId ast_id,
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +00002246 BailoutId return_id,
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002247 HValue* object,
2248 SmallMapList* types,
2249 Handle<String> name);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002250
machenbach@chromium.org37be4082013-11-26 13:50:38 +00002251 void VisitTypedArrayInitialize(CallRuntime* expr);
2252
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +00002253 bool IsCallNewArrayInlineable(CallNew* expr);
2254 void BuildInlinedCallNewArray(CallNew* expr);
2255
machenbach@chromium.orgaf9cfcb2013-11-19 11:05:18 +00002256 void VisitDataViewInitialize(CallRuntime* expr);
2257
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002258 class PropertyAccessInfo {
2259 public:
2260 PropertyAccessInfo(Isolate* isolate, Handle<Map> map, Handle<String> name)
2261 : lookup_(isolate),
2262 map_(map),
2263 name_(name),
2264 access_(HObjectAccess::ForMap()) { }
2265
2266 // Checkes whether this PropertyAccessInfo can be handled as a monomorphic
2267 // load named. It additionally fills in the fields necessary to generate the
2268 // lookup code.
2269 bool CanLoadMonomorphic();
2270
2271 // Checks whether all types behave uniform when loading name. If all maps
2272 // behave the same, a single monomorphic load instruction can be emitted,
2273 // guarded by a single map-checks instruction that whether the receiver is
2274 // an instance of any of the types.
2275 // This method skips the first type in types, assuming that this
2276 // PropertyAccessInfo is built for types->first().
2277 bool CanLoadAsMonomorphic(SmallMapList* types);
2278
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +00002279 bool IsJSObjectFieldAccessor() {
2280 int offset; // unused
2281 return Accessors::IsJSObjectFieldAccessor(map_, name_, &offset);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002282 }
2283
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +00002284 bool GetJSObjectFieldAccess(HObjectAccess* access) {
2285 if (IsStringLength()) {
2286 *access = HObjectAccess::ForStringLength();
2287 return true;
2288 } else if (IsArrayLength()) {
2289 *access = HObjectAccess::ForArrayLength(map_->elements_kind());
2290 return true;
2291 } else {
2292 int offset;
2293 if (Accessors::IsJSObjectFieldAccessor(map_, name_, &offset)) {
2294 *access = HObjectAccess::ForJSObjectOffset(offset);
2295 return true;
2296 }
2297 return false;
2298 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002299 }
2300
2301 bool has_holder() { return !holder_.is_null(); }
2302
2303 LookupResult* lookup() { return &lookup_; }
2304 Handle<Map> map() { return map_; }
2305 Handle<JSObject> holder() { return holder_; }
2306 Handle<JSFunction> accessor() { return accessor_; }
2307 Handle<Object> constant() { return constant_; }
2308 HObjectAccess access() { return access_; }
2309
2310 private:
2311 Isolate* isolate() { return lookup_.isolate(); }
2312
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +00002313 bool IsStringLength() {
2314 return map_->instance_type() < FIRST_NONSTRING_TYPE &&
2315 name_->Equals(isolate()->heap()->length_string());
2316 }
2317
2318 bool IsArrayLength() {
2319 return map_->instance_type() == JS_ARRAY_TYPE &&
2320 name_->Equals(isolate()->heap()->length_string());
2321 }
2322
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002323 bool LoadResult(Handle<Map> map);
2324 bool LookupDescriptor();
2325 bool LookupInPrototypes();
2326 bool IsCompatibleForLoad(PropertyAccessInfo* other);
2327
2328 void GeneralizeRepresentation(Representation r) {
2329 access_ = access_.WithRepresentation(
2330 access_.representation().generalize(r));
2331 }
2332
2333 LookupResult lookup_;
2334 Handle<Map> map_;
2335 Handle<String> name_;
2336 Handle<JSObject> holder_;
2337 Handle<JSFunction> accessor_;
2338 Handle<Object> constant_;
2339 HObjectAccess access_;
2340 };
2341
2342 HInstruction* BuildLoadMonomorphic(PropertyAccessInfo* info,
2343 HValue* object,
2344 HInstruction* checked_object,
2345 BailoutId ast_id,
2346 BailoutId return_id,
2347 bool can_inline_accessor = true);
2348
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00002349 void HandlePolymorphicStoreNamedField(BailoutId assignment_id,
danno@chromium.orgfe578672013-06-15 14:38:35 +00002350 HValue* object,
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002351 HValue* value,
danno@chromium.orgfe578672013-06-15 14:38:35 +00002352 SmallMapList* types,
2353 Handle<String> name);
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00002354 bool TryStorePolymorphicAsMonomorphic(BailoutId assignment_id,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002355 HValue* object,
2356 HValue* value,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00002357 SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002358 Handle<String> name);
2359 void HandlePolymorphicCallNamed(Call* expr,
2360 HValue* receiver,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00002361 SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002362 Handle<String> name);
danno@chromium.orgbee51992013-07-10 14:57:15 +00002363 bool TryCallPolymorphicAsMonomorphic(Call* expr,
2364 HValue* receiver,
2365 SmallMapList* types,
2366 Handle<String> name);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002367 void HandleLiteralCompareTypeof(CompareOperation* expr,
jkummerow@chromium.org96a3c512013-07-18 17:02:47 +00002368 Expression* sub_expr,
ager@chromium.org04921a82011-06-27 13:21:41 +00002369 Handle<String> check);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002370 void HandleLiteralCompareNil(CompareOperation* expr,
jkummerow@chromium.org96a3c512013-07-18 17:02:47 +00002371 Expression* sub_expr,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002372 NilValue nil);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002373 HControlInstruction* BuildCompareInstruction(Token::Value op,
2374 HValue* left,
2375 HValue* right,
2376 Handle<Type> left_type,
2377 Handle<Type> right_type,
2378 Handle<Type> combined_type,
2379 int left_position,
2380 int right_position,
2381 BailoutId bailout_id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002382
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002383 HInstruction* BuildStringCharCodeAt(HValue* string,
ulan@chromium.org2e04b582013-02-21 14:06:02 +00002384 HValue* index);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +00002385 HValue* BuildBinaryOperation(BinaryOperation* expr,
2386 HValue* left,
2387 HValue* right);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00002388 HInstruction* BuildIncrement(bool returns_original_input,
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00002389 CountOperation* expr);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002390 HInstruction* BuildLoadKeyedGeneric(HValue* object,
2391 HValue* key);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002392
mstarzinger@chromium.orgc6d9cee2012-07-03 10:03:19 +00002393 HInstruction* TryBuildConsolidatedElementLoad(HValue* object,
2394 HValue* key,
2395 HValue* val,
2396 SmallMapList* maps);
2397
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00002398 LoadKeyedHoleMode BuildKeyedHoleMode(Handle<Map> map);
2399
whesse@chromium.org7b260152011-06-20 15:33:18 +00002400 HInstruction* BuildMonomorphicElementAccess(HValue* object,
2401 HValue* key,
2402 HValue* val,
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00002403 HValue* dependency,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002404 Handle<Map> map,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00002405 bool is_store,
2406 KeyedAccessStoreMode store_mode);
mstarzinger@chromium.orgc6d9cee2012-07-03 10:03:19 +00002407
whesse@chromium.org7b260152011-06-20 15:33:18 +00002408 HValue* HandlePolymorphicElementAccess(HValue* object,
2409 HValue* key,
2410 HValue* val,
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +00002411 SmallMapList* maps,
whesse@chromium.org7b260152011-06-20 15:33:18 +00002412 bool is_store,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00002413 KeyedAccessStoreMode store_mode,
whesse@chromium.org7b260152011-06-20 15:33:18 +00002414 bool* has_side_effects);
2415
2416 HValue* HandleKeyedElementAccess(HValue* obj,
2417 HValue* key,
2418 HValue* val,
2419 Expression* expr,
whesse@chromium.org7b260152011-06-20 15:33:18 +00002420 bool is_store,
2421 bool* has_side_effects);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00002422
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00002423 HInstruction* BuildLoadNamedGeneric(HValue* object,
2424 Handle<String> name,
2425 Property* expr);
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00002426
verwaest@chromium.org003a9252013-08-12 17:15:20 +00002427 HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map);
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00002428
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +00002429 void BuildLoad(Property* property,
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +00002430 BailoutId ast_id);
2431 void PushLoad(Property* property,
2432 HValue* object,
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00002433 HValue* key);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +00002434
dslomov@chromium.org639bac02013-09-09 11:58:54 +00002435 void BuildStoreForEffect(Expression* expression,
2436 Property* prop,
2437 BailoutId ast_id,
2438 BailoutId return_id,
2439 HValue* object,
2440 HValue* key,
2441 HValue* value);
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +00002442
dslomov@chromium.org639bac02013-09-09 11:58:54 +00002443 void BuildStore(Expression* expression,
2444 Property* prop,
2445 BailoutId ast_id,
2446 BailoutId return_id,
2447 bool is_uninitialized = false);
danno@chromium.orgb0deb652013-06-20 16:20:19 +00002448
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002449 HInstruction* BuildStoreNamedField(HValue* object,
2450 Handle<String> name,
2451 HValue* value,
verwaest@chromium.orgb6d052d2012-07-27 08:03:27 +00002452 Handle<Map> map,
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002453 LookupResult* lookup);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002454 HInstruction* BuildStoreNamedGeneric(HValue* object,
2455 Handle<String> name,
2456 HValue* value);
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00002457 HInstruction* BuildStoreNamedMonomorphic(HValue* object,
2458 Handle<String> name,
2459 HValue* value,
2460 Handle<Map> map);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002461 HInstruction* BuildStoreKeyedGeneric(HValue* object,
2462 HValue* key,
2463 HValue* value);
2464
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002465 HValue* BuildContextChainWalk(Variable* var);
2466
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00002467 HInstruction* BuildThisFunction();
2468
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +00002469 HInstruction* BuildFastLiteral(Handle<JSObject> boilerplate_object,
machenbach@chromium.org37be4082013-11-26 13:50:38 +00002470 AllocationSiteUsageContext* site_context);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002471
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002472 void BuildEmitObjectHeader(Handle<JSObject> boilerplate_object,
2473 HInstruction* object);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002474
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002475 void BuildInitElementsInObjectHeader(Handle<JSObject> boilerplate_object,
2476 HInstruction* object,
2477 HInstruction* object_elements);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002478
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00002479 void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object,
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +00002480 HInstruction* object,
machenbach@chromium.orgc86e8c22013-11-27 15:11:04 +00002481 AllocationSiteUsageContext* site_context,
2482 PretenureFlag pretenure_flag);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00002483
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002484 void BuildEmitElements(Handle<JSObject> boilerplate_object,
2485 Handle<FixedArrayBase> elements,
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +00002486 HValue* object_elements,
machenbach@chromium.org37be4082013-11-26 13:50:38 +00002487 AllocationSiteUsageContext* site_context);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00002488
2489 void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements,
2490 ElementsKind kind,
2491 HValue* object_elements);
2492
2493 void BuildEmitFixedArray(Handle<FixedArrayBase> elements,
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00002494 ElementsKind kind,
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +00002495 HValue* object_elements,
machenbach@chromium.org37be4082013-11-26 13:50:38 +00002496 AllocationSiteUsageContext* site_context);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00002497
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002498 void AddCheckPrototypeMaps(Handle<JSObject> holder,
2499 Handle<Map> receiver_map);
2500
yangguo@chromium.org99aa4902012-07-06 16:21:55 +00002501 void AddCheckConstantFunction(Handle<JSObject> holder,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002502 HValue* receiver,
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002503 Handle<Map> receiver_map);
2504
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002505 // The translation state of the currently-being-translated function.
2506 FunctionState* function_state_;
2507
2508 // The base of the function state stack.
2509 FunctionState initial_function_state_;
2510
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002511 // Expression context of the currently visited subexpression. NULL when
2512 // visiting statements.
2513 AstContext* ast_context_;
2514
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002515 // A stack of breakable statements entered.
2516 BreakAndContinueScope* break_scope_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002517
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002518 int inlined_count_;
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00002519 ZoneList<Handle<Object> > globals_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002520
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002521 bool inline_bailout_;
2522
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00002523 HOsrBuilder* osr_;
2524
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002525 friend class FunctionState; // Pushes and pops the state stack.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002526 friend class AstContext; // Pushes and pops the AST context stack.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002527 friend class KeyedLoadFastElementStub;
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00002528 friend class HOsrBuilder;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002529
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002530 DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002531};
2532
2533
mmassi@chromium.org7028c052012-06-13 11:51:58 +00002534Zone* AstContext::zone() const { return owner_->zone(); }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00002535
2536
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00002537class HStatistics V8_FINAL: public Malloced {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002538 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002539 HStatistics()
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002540 : times_(5),
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002541 names_(5),
2542 sizes_(5),
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002543 total_size_(0),
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00002544 source_size_(0) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002545
ulan@chromium.org750145a2013-03-07 15:14:13 +00002546 void Initialize(CompilationInfo* info);
2547 void Print();
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002548 void SaveTiming(const char* name, TimeDelta time, unsigned size);
ulan@chromium.org750145a2013-03-07 15:14:13 +00002549
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002550 void IncrementFullCodeGen(TimeDelta full_code_gen) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002551 full_code_gen_ += full_code_gen;
2552 }
2553
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002554 void IncrementSubtotals(TimeDelta create_graph,
2555 TimeDelta optimize_graph,
2556 TimeDelta generate_code) {
ulan@chromium.org750145a2013-03-07 15:14:13 +00002557 create_graph_ += create_graph;
2558 optimize_graph_ += optimize_graph;
2559 generate_code_ += generate_code;
2560 }
2561
2562 private:
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002563 List<TimeDelta> times_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002564 List<const char*> names_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002565 List<unsigned> sizes_;
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002566 TimeDelta create_graph_;
2567 TimeDelta optimize_graph_;
2568 TimeDelta generate_code_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002569 unsigned total_size_;
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002570 TimeDelta full_code_gen_;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00002571 double source_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002572};
2573
2574
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002575class HPhase : public CompilationPhase {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002576 public:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002577 HPhase(const char* name, HGraph* graph)
2578 : CompilationPhase(name, graph->info()),
2579 graph_(graph) { }
ulan@chromium.org750145a2013-03-07 15:14:13 +00002580 ~HPhase();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002581
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002582 protected:
2583 HGraph* graph() const { return graph_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002584
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002585 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002586 HGraph* graph_;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002587
2588 DISALLOW_COPY_AND_ASSIGN(HPhase);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002589};
2590
2591
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00002592class HTracer V8_FINAL : public Malloced {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002593 public:
ulan@chromium.org750145a2013-03-07 15:14:13 +00002594 explicit HTracer(int isolate_id)
2595 : trace_(&string_allocator_), indent_(0) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00002596 if (FLAG_trace_hydrogen_file == NULL) {
2597 OS::SNPrintF(filename_,
2598 "hydrogen-%d-%d.cfg",
2599 OS::GetCurrentProcessId(),
2600 isolate_id);
2601 } else {
2602 OS::StrNCpy(filename_, FLAG_trace_hydrogen_file, filename_.length());
2603 }
ulan@chromium.org750145a2013-03-07 15:14:13 +00002604 WriteChars(filename_.start(), "", 0, false);
2605 }
2606
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002607 void TraceCompilation(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002608 void TraceHydrogen(const char* name, HGraph* graph);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00002609 void TraceLithium(const char* name, LChunk* chunk);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002610 void TraceLiveRanges(const char* name, LAllocator* allocator);
2611
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002612 private:
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00002613 class Tag V8_FINAL BASE_EMBEDDED {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002614 public:
2615 Tag(HTracer* tracer, const char* name) {
2616 name_ = name;
2617 tracer_ = tracer;
2618 tracer->PrintIndent();
2619 tracer->trace_.Add("begin_%s\n", name);
2620 tracer->indent_++;
2621 }
2622
2623 ~Tag() {
2624 tracer_->indent_--;
2625 tracer_->PrintIndent();
2626 tracer_->trace_.Add("end_%s\n", name_);
2627 ASSERT(tracer_->indent_ >= 0);
2628 tracer_->FlushToFile();
2629 }
2630
2631 private:
2632 HTracer* tracer_;
2633 const char* name_;
2634 };
2635
mmassi@chromium.org7028c052012-06-13 11:51:58 +00002636 void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00002637 void Trace(const char* name, HGraph* graph, LChunk* chunk);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002638 void FlushToFile();
2639
2640 void PrintEmptyProperty(const char* name) {
2641 PrintIndent();
2642 trace_.Add("%s\n", name);
2643 }
2644
2645 void PrintStringProperty(const char* name, const char* value) {
2646 PrintIndent();
2647 trace_.Add("%s \"%s\"\n", name, value);
2648 }
2649
2650 void PrintLongProperty(const char* name, int64_t value) {
2651 PrintIndent();
2652 trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
2653 }
2654
2655 void PrintBlockProperty(const char* name, int block_id) {
2656 PrintIndent();
2657 trace_.Add("%s \"B%d\"\n", name, block_id);
2658 }
2659
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002660 void PrintIntProperty(const char* name, int value) {
2661 PrintIndent();
2662 trace_.Add("%s %d\n", name, value);
2663 }
2664
2665 void PrintIndent() {
2666 for (int i = 0; i < indent_; i++) {
2667 trace_.Add(" ");
2668 }
2669 }
2670
ulan@chromium.org750145a2013-03-07 15:14:13 +00002671 EmbeddedVector<char, 64> filename_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002672 HeapStringAllocator string_allocator_;
2673 StringStream trace_;
2674 int indent_;
2675};
2676
2677
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00002678class NoObservableSideEffectsScope V8_FINAL {
danno@chromium.orgad75d6f2013-08-12 16:57:59 +00002679 public:
2680 explicit NoObservableSideEffectsScope(HGraphBuilder* builder) :
2681 builder_(builder) {
2682 builder_->graph()->IncrementInNoSideEffectsScope();
2683 }
2684 ~NoObservableSideEffectsScope() {
2685 builder_->graph()->DecrementInNoSideEffectsScope();
2686 }
2687
2688 private:
2689 HGraphBuilder* builder_;
2690};
2691
2692
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002693} } // namespace v8::internal
2694
2695#endif // V8_HYDROGEN_H_