blob: 0ea3b4ea961e9bfb6f8118e0f85a78b97643916f [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
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000998class HGraphBuilder {
999 public:
1000 explicit HGraphBuilder(CompilationInfo* info)
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001001 : info_(info),
1002 graph_(NULL),
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001003 current_block_(NULL),
1004 position_(RelocInfo::kNoPosition) {}
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001005 virtual ~HGraphBuilder() {}
1006
1007 HBasicBlock* current_block() const { return current_block_; }
1008 void set_current_block(HBasicBlock* block) { current_block_ = block; }
1009 HEnvironment* environment() const {
1010 return current_block()->last_environment();
1011 }
1012 Zone* zone() const { return info_->zone(); }
ulan@chromium.org750145a2013-03-07 15:14:13 +00001013 HGraph* graph() const { return graph_; }
1014 Isolate* isolate() const { return graph_->isolate(); }
danno@chromium.org41728482013-06-12 22:31:22 +00001015 CompilationInfo* top_info() { return info_; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001016
1017 HGraph* CreateGraph();
1018
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001019 // Bailout environment manipulation.
1020 void Push(HValue* value) { environment()->Push(value); }
1021 HValue* Pop() { return environment()->Pop(); }
1022
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001023 virtual HValue* context() = 0;
1024
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001025 // Adding instructions.
1026 HInstruction* AddInstruction(HInstruction* instr);
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001027 void FinishCurrentBlock(HControlInstruction* last);
1028 void FinishExitCurrentBlock(HControlInstruction* instruction);
1029
1030 void Goto(HBasicBlock* from,
1031 HBasicBlock* target,
1032 FunctionState* state = NULL,
1033 bool add_simulate = true) {
1034 from->Goto(target, position_, state, add_simulate);
1035 }
1036 void Goto(HBasicBlock* target,
1037 FunctionState* state = NULL,
1038 bool add_simulate = true) {
1039 Goto(current_block(), target, state, add_simulate);
1040 }
1041 void GotoNoSimulate(HBasicBlock* from, HBasicBlock* target) {
1042 Goto(from, target, NULL, false);
1043 }
1044 void GotoNoSimulate(HBasicBlock* target) {
1045 Goto(target, NULL, false);
1046 }
1047 void AddLeaveInlined(HBasicBlock* block,
1048 HValue* return_value,
1049 FunctionState* state) {
1050 block->AddLeaveInlined(return_value, state, position_);
1051 }
1052 void AddLeaveInlined(HValue* return_value, FunctionState* state) {
1053 return AddLeaveInlined(current_block(), return_value, state);
1054 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001055
1056 template<class I>
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001057 HInstruction* NewUncasted() { return I::New(zone(), context()); }
1058
1059 template<class I>
1060 I* New() { return I::cast(NewUncasted<I>()); }
1061
1062 template<class I>
1063 HInstruction* AddUncasted() { return AddInstruction(NewUncasted<I>());}
1064
1065 template<class I>
1066 I* Add() { return I::cast(AddUncasted<I>());}
1067
1068 template<class I, class P1>
1069 HInstruction* NewUncasted(P1 p1) {
1070 return I::New(zone(), context(), p1);
1071 }
1072
1073 template<class I, class P1>
1074 I* New(P1 p1) { return I::cast(NewUncasted<I>(p1)); }
1075
1076 template<class I, class P1>
1077 HInstruction* AddUncasted(P1 p1) {
1078 HInstruction* result = AddInstruction(NewUncasted<I>(p1));
1079 // Specializations must have their parameters properly casted
1080 // to avoid landing here.
1081 ASSERT(!result->IsReturn() && !result->IsSimulate() &&
1082 !result->IsDeoptimize());
1083 return result;
1084 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001085
1086 template<class I, class P1>
1087 I* Add(P1 p1) {
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001088 return I::cast(AddUncasted<I>(p1));
1089 }
1090
1091 template<class I, class P1, class P2>
1092 HInstruction* NewUncasted(P1 p1, P2 p2) {
1093 return I::New(zone(), context(), p1, p2);
1094 }
1095
1096 template<class I, class P1, class P2>
1097 I* New(P1 p1, P2 p2) {
1098 return I::cast(NewUncasted<I>(p1, p2));
1099 }
1100
1101 template<class I, class P1, class P2>
1102 HInstruction* AddUncasted(P1 p1, P2 p2) {
1103 HInstruction* result = AddInstruction(NewUncasted<I>(p1, p2));
1104 // Specializations must have their parameters properly casted
1105 // to avoid landing here.
1106 ASSERT(!result->IsSimulate());
1107 return result;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001108 }
1109
1110 template<class I, class P1, class P2>
1111 I* Add(P1 p1, P2 p2) {
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001112 return I::cast(AddUncasted<I>(p1, p2));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001113 }
1114
1115 template<class I, class P1, class P2, class P3>
1116 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3) {
1117 return I::New(zone(), context(), p1, p2, p3);
1118 }
1119
1120 template<class I, class P1, class P2, class P3>
1121 I* New(P1 p1, P2 p2, P3 p3) {
1122 return I::cast(NewUncasted<I>(p1, p2, p3));
1123 }
1124
1125 template<class I, class P1, class P2, class P3>
1126 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3) {
1127 return AddInstruction(NewUncasted<I>(p1, p2, p3));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001128 }
1129
1130 template<class I, class P1, class P2, class P3>
1131 I* Add(P1 p1, P2 p2, P3 p3) {
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001132 return I::cast(AddUncasted<I>(p1, p2, p3));
1133 }
1134
1135 template<class I, class P1, class P2, class P3, class P4>
1136 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
1137 return I::New(zone(), context(), p1, p2, p3, p4);
1138 }
1139
1140 template<class I, class P1, class P2, class P3, class P4>
1141 I* New(P1 p1, P2 p2, P3 p3, P4 p4) {
1142 return I::cast(NewUncasted<I>(p1, p2, p3, p4));
1143 }
1144
1145 template<class I, class P1, class P2, class P3, class P4>
1146 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
1147 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001148 }
1149
1150 template<class I, class P1, class P2, class P3, class P4>
1151 I* Add(P1 p1, P2 p2, P3 p3, P4 p4) {
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001152 return I::cast(AddUncasted<I>(p1, p2, p3, p4));
1153 }
1154
1155 template<class I, class P1, class P2, class P3, class P4, class P5>
1156 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1157 return I::New(zone(), context(), p1, p2, p3, p4, p5);
1158 }
1159
1160 template<class I, class P1, class P2, class P3, class P4, class P5>
1161 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1162 return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5));
1163 }
1164
1165 template<class I, class P1, class P2, class P3, class P4, class P5>
1166 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1167 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001168 }
1169
1170 template<class I, class P1, class P2, class P3, class P4, class P5>
1171 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001172 return I::cast(AddUncasted<I>(p1, p2, p3, p4, p5));
1173 }
1174
1175 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1176 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1177 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6);
1178 }
1179
1180 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1181 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1182 return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5, p6));
1183 }
1184
1185 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1186 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1187 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001188 }
1189
1190 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1191 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001192 return I::cast(AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6)));
1193 }
1194
1195 template<class I, class P1, class P2, class P3, class P4,
1196 class P5, class P6, class P7>
1197 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1198 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7);
1199 }
1200
1201 template<class I, class P1, class P2, class P3, class P4,
1202 class P5, class P6, class P7>
1203 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1204 return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7));
1205 }
1206
1207 template<class I, class P1, class P2, class P3,
1208 class P4, class P5, class P6, class P7>
1209 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1210 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001211 }
1212
1213 template<class I, class P1, class P2, class P3,
1214 class P4, class P5, class P6, class P7>
1215 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001216 return I::cast(AddInstruction(NewUncasted<I>(p1, p2, p3, p4,
1217 p5, p6, p7)));
1218 }
1219
1220 template<class I, class P1, class P2, class P3, class P4,
1221 class P5, class P6, class P7, class P8>
1222 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
1223 P5 p5, P6 p6, P7 p7, P8 p8) {
1224 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8);
1225 }
1226
1227 template<class I, class P1, class P2, class P3, class P4,
1228 class P5, class P6, class P7, class P8>
1229 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
1230 return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8));
1231 }
1232
1233 template<class I, class P1, class P2, class P3, class P4,
1234 class P5, class P6, class P7, class P8>
1235 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
1236 P5 p5, P6 p6, P7 p7, P8 p8) {
1237 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001238 }
1239
1240 template<class I, class P1, class P2, class P3, class P4,
1241 class P5, class P6, class P7, class P8>
1242 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001243 return I::cast(
1244 AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8)));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001245 }
1246
danno@chromium.orgad75d6f2013-08-12 16:57:59 +00001247 void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001248
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001249 int position() const { return position_; }
1250
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001251 protected:
1252 virtual bool BuildGraph() = 0;
1253
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001254 HBasicBlock* CreateBasicBlock(HEnvironment* env);
1255 HBasicBlock* CreateLoopHeaderBlock();
1256
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001257 HValue* BuildCheckHeapObject(HValue* object);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001258 HValue* BuildCheckMap(HValue* obj, Handle<Map> map);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001259 HValue* BuildWrapReceiver(HValue* object, HValue* function);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001260
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001261 // Building common constructs
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001262 HValue* BuildCheckForCapacityGrow(HValue* object,
1263 HValue* elements,
1264 ElementsKind kind,
1265 HValue* length,
1266 HValue* key,
1267 bool is_js_array);
1268
1269 HValue* BuildCopyElementsOnWrite(HValue* object,
1270 HValue* elements,
1271 ElementsKind kind,
1272 HValue* length);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001273
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00001274 void BuildTransitionElementsKind(HValue* object,
1275 HValue* map,
1276 ElementsKind from_kind,
1277 ElementsKind to_kind,
1278 bool is_jsarray);
1279
bmeurer@chromium.orge7a07452013-10-21 13:27:29 +00001280 HValue* BuildNumberToString(HValue* object, Handle<Type> type);
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +00001281
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001282 HValue* BuildUncheckedDictionaryElementLoad(HValue* receiver,
1283 HValue* key);
1284
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00001285 // Computes the size for a sequential string of the given length and encoding.
1286 HValue* BuildSeqStringSizeFor(HValue* length,
1287 String::Encoding encoding);
1288 // Copies characters from one sequential string to another.
1289 void BuildCopySeqStringChars(HValue* src,
1290 HValue* src_offset,
1291 String::Encoding src_encoding,
1292 HValue* dst,
1293 HValue* dst_offset,
1294 String::Encoding dst_encoding,
1295 HValue* length);
1296 // Both operands are non-empty strings.
1297 HValue* BuildUncheckedStringAdd(HValue* left,
1298 HValue* right,
1299 PretenureFlag pretenure_flag);
1300 // Both operands are strings.
1301 HValue* BuildStringAdd(HValue* left,
1302 HValue* right,
1303 PretenureFlag pretenure_flag);
1304
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001305 HInstruction* BuildUncheckedMonomorphicElementAccess(
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001306 HValue* checked_object,
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001307 HValue* key,
1308 HValue* val,
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001309 bool is_js_array,
1310 ElementsKind elements_kind,
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00001311 bool is_store,
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001312 LoadKeyedHoleMode load_mode,
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001313 KeyedAccessStoreMode store_mode);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001314
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +00001315 HInstruction* AddElementAccess(
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00001316 HValue* elements,
1317 HValue* checked_key,
1318 HValue* val,
1319 HValue* dependency,
1320 ElementsKind elements_kind,
1321 bool is_store,
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +00001322 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE);
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00001323
verwaest@chromium.orgec6855e2013-08-22 12:26:58 +00001324 HLoadNamedField* BuildLoadNamedField(HValue* object, HObjectAccess access);
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +00001325 HInstruction* AddLoadNamedField(HValue* object, HObjectAccess access);
verwaest@chromium.orgec6855e2013-08-22 12:26:58 +00001326 HInstruction* BuildLoadStringLength(HValue* object, HValue* checked_value);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00001327 HStoreNamedField* AddStoreMapConstant(HValue* object, Handle<Map> map);
1328 HStoreNamedField* AddStoreMapConstantNoWriteBarrier(HValue* object,
1329 Handle<Map> map) {
1330 HStoreNamedField* store_map = AddStoreMapConstant(object, map);
1331 store_map->SkipWriteBarrier();
1332 return store_map;
1333 }
verwaest@chromium.orgec6855e2013-08-22 12:26:58 +00001334 HLoadNamedField* AddLoadElements(HValue* object);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001335
1336 bool MatchRotateRight(HValue* left,
1337 HValue* right,
1338 HValue** operand,
1339 HValue** shift_amount);
1340
1341 HInstruction* BuildBinaryOperation(Token::Value op,
1342 HValue* left,
1343 HValue* right,
1344 Handle<Type> left_type,
1345 Handle<Type> right_type,
1346 Handle<Type> result_type,
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001347 Maybe<int> fixed_right_arg,
1348 bool binop_stub = false);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001349
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00001350 HLoadNamedField* AddLoadFixedArrayLength(HValue *object);
1351
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001352 HValue* AddLoadJSBuiltin(Builtins::JavaScript builtin);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001353
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001354 HValue* EnforceNumberType(HValue* number, Handle<Type> expected);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001355 HValue* TruncateToNumber(HValue* value, Handle<Type>* expected);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001356
danno@chromium.org59400602013-08-13 17:09:37 +00001357 void FinishExitWithHardDeoptimization(const char* reason,
1358 HBasicBlock* continuation);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001359
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001360 void AddIncrementCounter(StatsCounter* counter);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001361
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001362 class IfBuilder V8_FINAL {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001363 public:
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001364 explicit IfBuilder(HGraphBuilder* builder);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001365 IfBuilder(HGraphBuilder* builder,
1366 HIfContinuation* continuation);
1367
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001368 ~IfBuilder() {
1369 if (!finished_) End();
1370 }
1371
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001372 template<class Condition>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001373 Condition* If(HValue *p) {
1374 Condition* compare = builder()->New<Condition>(p);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001375 AddCompare(compare);
1376 return compare;
1377 }
1378
1379 template<class Condition, class P2>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001380 Condition* If(HValue* p1, P2 p2) {
1381 Condition* compare = builder()->New<Condition>(p1, p2);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001382 AddCompare(compare);
1383 return compare;
1384 }
1385
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001386 template<class Condition, class P2, class P3>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001387 Condition* If(HValue* p1, P2 p2, P3 p3) {
1388 Condition* compare = builder()->New<Condition>(p1, p2, p3);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001389 AddCompare(compare);
1390 return compare;
1391 }
1392
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001393 template<class Condition>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001394 Condition* IfNot(HValue* p) {
1395 Condition* compare = If<Condition>(p);
1396 compare->Not();
1397 return compare;
1398 }
1399
1400 template<class Condition, class P2>
1401 Condition* IfNot(HValue* p1, P2 p2) {
1402 Condition* compare = If<Condition>(p1, p2);
1403 compare->Not();
1404 return compare;
1405 }
1406
1407 template<class Condition, class P2, class P3>
1408 Condition* IfNot(HValue* p1, P2 p2, P3 p3) {
1409 Condition* compare = If<Condition>(p1, p2, p3);
1410 compare->Not();
1411 return compare;
1412 }
1413
1414 template<class Condition>
1415 Condition* OrIf(HValue *p) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001416 Or();
1417 return If<Condition>(p);
1418 }
1419
1420 template<class Condition, class P2>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001421 Condition* OrIf(HValue* p1, P2 p2) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001422 Or();
1423 return If<Condition>(p1, p2);
1424 }
1425
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001426 template<class Condition, class P2, class P3>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001427 Condition* OrIf(HValue* p1, P2 p2, P3 p3) {
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001428 Or();
1429 return If<Condition>(p1, p2, p3);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001430 }
1431
1432 template<class Condition>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001433 Condition* AndIf(HValue *p) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001434 And();
1435 return If<Condition>(p);
1436 }
1437
1438 template<class Condition, class P2>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001439 Condition* AndIf(HValue* p1, P2 p2) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001440 And();
1441 return If<Condition>(p1, p2);
1442 }
1443
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001444 template<class Condition, class P2, class P3>
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001445 Condition* AndIf(HValue* p1, P2 p2, P3 p3) {
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001446 And();
1447 return If<Condition>(p1, p2, p3);
1448 }
1449
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001450 void Or();
1451 void And();
1452
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001453 // Captures the current state of this IfBuilder in the specified
1454 // continuation and ends this IfBuilder.
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001455 void CaptureContinuation(HIfContinuation* continuation);
1456
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001457 // Joins the specified continuation from this IfBuilder and ends this
1458 // IfBuilder. This appends a Goto instruction from the true branch of
1459 // this IfBuilder to the true branch of the continuation unless the
1460 // true branch of this IfBuilder is already finished. And vice versa
1461 // for the false branch.
1462 //
1463 // The basic idea is as follows: You have several nested IfBuilder's
1464 // that you want to join based on two possible outcomes (i.e. success
1465 // and failure, or whatever). You can do this easily using this method
1466 // now, for example:
1467 //
1468 // HIfContinuation cont(graph()->CreateBasicBlock(),
1469 // graph()->CreateBasicBlock());
1470 // ...
1471 // IfBuilder if_whatever(this);
1472 // if_whatever.If<Condition>(arg);
1473 // if_whatever.Then();
1474 // ...
1475 // if_whatever.Else();
1476 // ...
1477 // if_whatever.JoinContinuation(&cont);
1478 // ...
1479 // IfBuilder if_something(this);
1480 // if_something.If<Condition>(arg1, arg2);
1481 // if_something.Then();
1482 // ...
1483 // if_something.Else();
1484 // ...
1485 // if_something.JoinContinuation(&cont);
1486 // ...
1487 // IfBuilder if_finally(this, &cont);
1488 // if_finally.Then();
1489 // // continues after then code of if_whatever or if_something.
1490 // ...
1491 // if_finally.Else();
1492 // // continues after else code of if_whatever or if_something.
1493 // ...
1494 // if_finally.End();
1495 void JoinContinuation(HIfContinuation* continuation);
1496
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001497 void Then();
1498 void Else();
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001499 void End();
1500
danno@chromium.org59400602013-08-13 17:09:37 +00001501 void Deopt(const char* reason);
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001502 void ThenDeopt(const char* reason) {
1503 Then();
1504 Deopt(reason);
1505 }
danno@chromium.org59400602013-08-13 17:09:37 +00001506 void ElseDeopt(const char* reason) {
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00001507 Else();
danno@chromium.org59400602013-08-13 17:09:37 +00001508 Deopt(reason);
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00001509 }
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001510
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001511 void Return(HValue* value);
1512
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001513 private:
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001514 HControlInstruction* AddCompare(HControlInstruction* compare);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001515
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001516 HGraphBuilder* builder() const { return builder_; }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001517
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001518 void AddMergeAtJoinBlock(bool deopt);
1519
1520 void Finish();
1521 void Finish(HBasicBlock** then_continuation,
1522 HBasicBlock** else_continuation);
1523
1524 class MergeAtJoinBlock : public ZoneObject {
1525 public:
1526 MergeAtJoinBlock(HBasicBlock* block,
1527 bool deopt,
1528 MergeAtJoinBlock* next)
1529 : block_(block),
1530 deopt_(deopt),
1531 next_(next) {}
1532 HBasicBlock* block_;
1533 bool deopt_;
1534 MergeAtJoinBlock* next_;
1535 };
1536
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001537 HGraphBuilder* builder_;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001538 bool finished_ : 1;
1539 bool did_then_ : 1;
1540 bool did_else_ : 1;
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001541 bool did_else_if_ : 1;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001542 bool did_and_ : 1;
1543 bool did_or_ : 1;
1544 bool captured_ : 1;
1545 bool needs_compare_ : 1;
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001546 bool pending_merge_block_ : 1;
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001547 HBasicBlock* first_true_block_;
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001548 HBasicBlock* first_false_block_;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001549 HBasicBlock* split_edge_merge_block_;
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001550 MergeAtJoinBlock* merge_at_join_blocks_;
1551 int normal_merge_at_join_block_count_;
1552 int deopt_merge_at_join_block_count_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001553 };
1554
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001555 class LoopBuilder V8_FINAL {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001556 public:
1557 enum Direction {
1558 kPreIncrement,
1559 kPostIncrement,
1560 kPreDecrement,
1561 kPostDecrement
1562 };
1563
1564 LoopBuilder(HGraphBuilder* builder,
1565 HValue* context,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001566 Direction direction);
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001567 LoopBuilder(HGraphBuilder* builder,
1568 HValue* context,
1569 Direction direction,
1570 HValue* increment_amount);
1571
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001572 ~LoopBuilder() {
1573 ASSERT(finished_);
1574 }
1575
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001576 HValue* BeginBody(
1577 HValue* initial,
1578 HValue* terminating,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00001579 Token::Value token);
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001580
1581 void Break();
1582
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001583 void EndBody();
1584
1585 private:
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001586 Zone* zone() { return builder_->zone(); }
1587
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001588 HGraphBuilder* builder_;
1589 HValue* context_;
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001590 HValue* increment_amount_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001591 HInstruction* increment_;
1592 HPhi* phi_;
1593 HBasicBlock* header_block_;
1594 HBasicBlock* body_block_;
1595 HBasicBlock* exit_block_;
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001596 HBasicBlock* exit_trampoline_block_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001597 Direction direction_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001598 bool finished_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001599 };
1600
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001601 HValue* BuildNewElementsCapacity(HValue* old_capacity);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001602
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001603 void BuildNewSpaceArrayCheck(HValue* length,
1604 ElementsKind kind);
1605
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001606 class JSArrayBuilder V8_FINAL {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001607 public:
1608 JSArrayBuilder(HGraphBuilder* builder,
1609 ElementsKind kind,
1610 HValue* allocation_site_payload,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001611 HValue* constructor_function,
1612 AllocationSiteOverrideMode override_mode);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001613
1614 JSArrayBuilder(HGraphBuilder* builder,
1615 ElementsKind kind,
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001616 HValue* constructor_function = NULL);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001617
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +00001618 enum FillMode {
1619 DONT_FILL_WITH_HOLE,
1620 FILL_WITH_HOLE
1621 };
1622
1623 ElementsKind kind() { return kind_; }
1624
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001625 HValue* AllocateEmptyArray();
1626 HValue* AllocateArray(HValue* capacity, HValue* length_field,
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +00001627 FillMode fill_mode = FILL_WITH_HOLE);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001628 HValue* GetElementsLocation() { return elements_location_; }
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001629 HValue* EmitMapCode();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001630
1631 private:
1632 Zone* zone() const { return builder_->zone(); }
1633 int elements_size() const {
1634 return IsFastDoubleElementsKind(kind_) ? kDoubleSize : kPointerSize;
1635 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001636 HGraphBuilder* builder() { return builder_; }
1637 HGraph* graph() { return builder_->graph(); }
1638 int initial_capacity() {
1639 STATIC_ASSERT(JSArray::kPreallocatedArrayElements > 0);
1640 return JSArray::kPreallocatedArrayElements;
1641 }
1642
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001643 HValue* EmitInternalMapCode();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001644 HValue* EstablishEmptyArrayAllocationSize();
1645 HValue* EstablishAllocationSize(HValue* length_node);
1646 HValue* AllocateArray(HValue* size_in_bytes, HValue* capacity,
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +00001647 HValue* length_field,
1648 FillMode fill_mode = FILL_WITH_HOLE);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001649
1650 HGraphBuilder* builder_;
1651 ElementsKind kind_;
1652 AllocationSiteMode mode_;
1653 HValue* allocation_site_payload_;
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001654 HValue* constructor_function_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001655 HInnerAllocatedObject* elements_location_;
1656 };
1657
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +00001658 HValue* BuildAllocateArrayFromLength(JSArrayBuilder* array_builder,
1659 HValue* length_argument);
1660
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001661 HValue* BuildAllocateElements(ElementsKind kind,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001662 HValue* capacity);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001663
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001664 void BuildInitializeElementsHeader(HValue* elements,
1665 ElementsKind kind,
1666 HValue* capacity);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001667
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001668 HValue* BuildAllocateElementsAndInitializeElementsHeader(ElementsKind kind,
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001669 HValue* capacity);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001670
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001671 // array must have been allocated with enough room for
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00001672 // 1) the JSArray, 2) a AllocationMemento if mode requires it,
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001673 // 3) a FixedArray or FixedDoubleArray.
1674 // A pointer to the Fixed(Double)Array is returned.
1675 HInnerAllocatedObject* BuildJSArrayHeader(HValue* array,
1676 HValue* array_map,
1677 AllocationSiteMode mode,
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001678 ElementsKind elements_kind,
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001679 HValue* allocation_site_payload,
1680 HValue* length_field);
1681
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001682 HValue* BuildGrowElementsCapacity(HValue* object,
1683 HValue* elements,
1684 ElementsKind kind,
danno@chromium.orgbee51992013-07-10 14:57:15 +00001685 ElementsKind new_kind,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001686 HValue* length,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001687 HValue* new_capacity);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001688
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001689 void BuildFillElementsWithHole(HValue* elements,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001690 ElementsKind elements_kind,
1691 HValue* from,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001692 HValue* to);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001693
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001694 void BuildCopyElements(HValue* from_elements,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001695 ElementsKind from_elements_kind,
1696 HValue* to_elements,
1697 ElementsKind to_elements_kind,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001698 HValue* length,
danno@chromium.org2d18b362013-03-22 17:19:26 +00001699 HValue* capacity);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001700
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001701 HValue* BuildCloneShallowArray(HValue* boilerplate,
danno@chromium.orgbee51992013-07-10 14:57:15 +00001702 HValue* allocation_site,
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001703 AllocationSiteMode mode,
1704 ElementsKind kind,
1705 int length);
1706
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001707 HValue* BuildElementIndexHash(HValue* index);
1708
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001709 void BuildCompareNil(
1710 HValue* value,
danno@chromium.org41728482013-06-12 22:31:22 +00001711 Handle<Type> type,
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001712 HIfContinuation* continuation);
1713
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00001714 HValue* BuildCreateAllocationMemento(HValue* previous_object,
1715 int previous_object_size,
1716 HValue* payload);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001717
verwaest@chromium.orgec6855e2013-08-22 12:26:58 +00001718 HInstruction* BuildConstantMapCheck(Handle<JSObject> constant,
1719 CompilationInfo* info);
1720 HInstruction* BuildCheckPrototypeMaps(Handle<JSObject> prototype,
1721 Handle<JSObject> holder);
danno@chromium.org59400602013-08-13 17:09:37 +00001722
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001723 HInstruction* BuildGetNativeContext();
1724 HInstruction* BuildGetArrayFunction();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001725
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001726 protected:
1727 void SetSourcePosition(int position) {
1728 ASSERT(position != RelocInfo::kNoPosition);
1729 position_ = position;
1730 }
1731
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001732 private:
1733 HGraphBuilder();
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001734
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001735 HValue* BuildUncheckedDictionaryElementLoadHelper(
1736 HValue* elements,
1737 HValue* key,
1738 HValue* hash,
1739 HValue* mask,
1740 int current_probe);
1741
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001742 void PadEnvironmentForContinuation(HBasicBlock* from,
1743 HBasicBlock* continuation);
1744
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001745 CompilationInfo* info_;
1746 HGraph* graph_;
1747 HBasicBlock* current_block_;
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001748 int position_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001749};
1750
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001751
1752template<>
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001753inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>(
danno@chromium.org59400602013-08-13 17:09:37 +00001754 const char* reason, Deoptimizer::BailoutType type) {
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001755 if (type == Deoptimizer::SOFT) {
1756 isolate()->counters()->soft_deopts_requested()->Increment();
1757 if (FLAG_always_opt) return NULL;
1758 }
1759 if (current_block()->IsDeoptimizing()) return NULL;
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001760 HBasicBlock* after_deopt_block = CreateBasicBlock(
1761 current_block()->last_environment());
1762 HDeoptimize* instr = New<HDeoptimize>(reason, type, after_deopt_block);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001763 if (type == Deoptimizer::SOFT) {
1764 isolate()->counters()->soft_deopts_inserted()->Increment();
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001765 }
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001766 FinishCurrentBlock(instr);
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001767 set_current_block(after_deopt_block);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001768 return instr;
1769}
1770
1771
1772template<>
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001773inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>(
danno@chromium.org59400602013-08-13 17:09:37 +00001774 const char* reason, Deoptimizer::BailoutType type) {
1775 return static_cast<HDeoptimize*>(AddUncasted<HDeoptimize>(reason, type));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001776}
1777
1778
1779template<>
1780inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(
1781 BailoutId id,
1782 RemovableSimulate removable) {
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001783 HSimulate* instr = current_block()->CreateSimulate(id, removable);
1784 AddInstruction(instr);
1785 return instr;
1786}
1787
1788
1789template<>
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001790inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(BailoutId id) {
1791 return AddUncasted<HSimulate>(id, FIXED_SIMULATE);
1792}
1793
1794
1795template<>
1796inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HValue* value) {
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001797 int num_parameters = graph()->info()->num_parameters();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001798 HValue* params = AddUncasted<HConstant>(num_parameters);
1799 HReturn* return_instruction = New<HReturn>(value, params);
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001800 FinishExitCurrentBlock(return_instruction);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001801 return return_instruction;
1802}
1803
1804
1805template<>
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001806inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HConstant* value) {
1807 return AddUncasted<HReturn>(static_cast<HValue*>(value));
1808}
1809
1810
1811template<>
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +00001812inline HInstruction* HGraphBuilder::AddUncasted<HCallRuntime>(
1813 Handle<String> name,
1814 const Runtime::Function* c_function,
1815 int argument_count) {
1816 HCallRuntime* instr = New<HCallRuntime>(name, c_function, argument_count);
1817 if (graph()->info()->IsStub()) {
1818 // When compiling code stubs, we don't want to save all double registers
1819 // upon entry to the stub, but instead have the call runtime instruction
1820 // save the double registers only on-demand (in the fallback case).
1821 instr->set_save_doubles(kSaveFPRegs);
1822 }
1823 AddInstruction(instr);
1824 return instr;
1825}
1826
1827
1828template<>
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001829inline HInstruction* HGraphBuilder::NewUncasted<HContext>() {
1830 return HContext::New(zone());
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001831}
1832
1833
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001834class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001835 public:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001836 // A class encapsulating (lazily-allocated) break and continue blocks for
1837 // a breakable statement. Separated from BreakAndContinueScope so that it
1838 // can have a separate lifetime.
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001839 class BreakAndContinueInfo V8_FINAL BASE_EMBEDDED {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001840 public:
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001841 explicit BreakAndContinueInfo(BreakableStatement* target,
1842 int drop_extra = 0)
1843 : target_(target),
1844 break_block_(NULL),
1845 continue_block_(NULL),
1846 drop_extra_(drop_extra) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001847 }
1848
1849 BreakableStatement* target() { return target_; }
1850 HBasicBlock* break_block() { return break_block_; }
1851 void set_break_block(HBasicBlock* block) { break_block_ = block; }
1852 HBasicBlock* continue_block() { return continue_block_; }
1853 void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001854 int drop_extra() { return drop_extra_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001855
1856 private:
1857 BreakableStatement* target_;
1858 HBasicBlock* break_block_;
1859 HBasicBlock* continue_block_;
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001860 int drop_extra_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001861 };
1862
1863 // A helper class to maintain a stack of current BreakAndContinueInfo
1864 // structures mirroring BreakableStatement nesting.
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001865 class BreakAndContinueScope V8_FINAL BASE_EMBEDDED {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001866 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001867 BreakAndContinueScope(BreakAndContinueInfo* info,
1868 HOptimizedGraphBuilder* owner)
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001869 : info_(info), owner_(owner), next_(owner->break_scope()) {
1870 owner->set_break_scope(this);
1871 }
1872
1873 ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
1874
1875 BreakAndContinueInfo* info() { return info_; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001876 HOptimizedGraphBuilder* owner() { return owner_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001877 BreakAndContinueScope* next() { return next_; }
1878
1879 // Search the break stack for a break or continue target.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001880 enum BreakType { BREAK, CONTINUE };
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001881 HBasicBlock* Get(BreakableStatement* stmt, BreakType type, int* drop_extra);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001882
1883 private:
1884 BreakAndContinueInfo* info_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001885 HOptimizedGraphBuilder* owner_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001886 BreakAndContinueScope* next_;
1887 };
1888
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001889 explicit HOptimizedGraphBuilder(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001890
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001891 virtual bool BuildGraph() V8_OVERRIDE;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001892
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001893 // Simple accessors.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001894 BreakAndContinueScope* break_scope() const { return break_scope_; }
1895 void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001896
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001897 bool inline_bailout() { return inline_bailout_; }
1898
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001899 HValue* context() { return environment()->context(); }
1900
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00001901 HOsrBuilder* osr() const { return osr_; }
1902
danno@chromium.org59400602013-08-13 17:09:37 +00001903 void Bailout(BailoutReason reason);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001904
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001905 HBasicBlock* CreateJoin(HBasicBlock* first,
1906 HBasicBlock* second,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001907 BailoutId join_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001908
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001909 FunctionState* function_state() const { return function_state_; }
1910
yangguo@chromium.org56454712012-02-16 15:33:53 +00001911 void VisitDeclarations(ZoneList<Declaration*>* declarations);
1912
verwaest@chromium.org178fb152012-07-18 11:21:48 +00001913 void* operator new(size_t size, Zone* zone) {
1914 return zone->New(static_cast<int>(size));
1915 }
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001916 void operator delete(void* pointer, Zone* zone) { }
1917 void operator delete(void* pointer) { }
verwaest@chromium.org178fb152012-07-18 11:21:48 +00001918
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001919 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
1920
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00001921 protected:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001922 // Type of a member function that generates inline code for a native function.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001923 typedef void (HOptimizedGraphBuilder::*InlineFunctionGenerator)
1924 (CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001925
1926 // Forward declarations for inner scope classes.
1927 class SubgraphScope;
1928
1929 static const InlineFunctionGenerator kInlineFunctionGenerators[];
1930
1931 static const int kMaxCallPolymorphism = 4;
1932 static const int kMaxLoadPolymorphism = 4;
1933 static const int kMaxStorePolymorphism = 4;
1934
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001935 // Even in the 'unlimited' case we have to have some limit in order not to
1936 // overflow the stack.
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +00001937 static const int kUnlimitedMaxInlinedSourceSize = 100000;
1938 static const int kUnlimitedMaxInlinedNodes = 10000;
1939 static const int kUnlimitedMaxInlinedNodesCumulative = 10000;
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001940
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001941 // Maximum depth and total number of elements and properties for literal
1942 // graphs to be considered for fast deep-copying.
1943 static const int kMaxFastLiteralDepth = 3;
1944 static const int kMaxFastLiteralProperties = 8;
1945
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001946 // Simple accessors.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001947 void set_function_state(FunctionState* state) { function_state_ = state; }
1948
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001949 AstContext* ast_context() const { return ast_context_; }
1950 void set_ast_context(AstContext* context) { ast_context_ = context; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001951
1952 // Accessors forwarded to the function state.
danno@chromium.org41728482013-06-12 22:31:22 +00001953 CompilationInfo* current_info() const {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001954 return function_state()->compilation_info();
1955 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001956 AstContext* call_context() const {
1957 return function_state()->call_context();
1958 }
1959 HBasicBlock* function_return() const {
1960 return function_state()->function_return();
1961 }
1962 TestContext* inlined_test_context() const {
1963 return function_state()->test_context();
1964 }
1965 void ClearInlinedTestContext() {
1966 function_state()->ClearInlinedTestContext();
1967 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001968 StrictModeFlag function_strict_mode_flag() {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001969 return function_state()->compilation_info()->is_classic_mode()
1970 ? kNonStrictMode : kStrictMode;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001971 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001972
1973 // Generators for inline runtime functions.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001974#define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001975 void Generate##Name(CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001976
1977 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
1978 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
1979#undef INLINE_FUNCTION_GENERATOR_DECLARATION
1980
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001981 void VisitDelete(UnaryOperation* expr);
1982 void VisitVoid(UnaryOperation* expr);
1983 void VisitTypeof(UnaryOperation* expr);
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001984 void VisitNot(UnaryOperation* expr);
1985
1986 void VisitComma(BinaryOperation* expr);
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +00001987 void VisitLogicalExpression(BinaryOperation* expr);
1988 void VisitArithmeticExpression(BinaryOperation* expr);
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001989
rossberg@chromium.org2c067b12012-03-19 11:01:52 +00001990 bool PreProcessOsrEntry(IterationStatement* statement);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001991 void VisitLoopBody(IterationStatement* stmt,
ager@chromium.org04921a82011-06-27 13:21:41 +00001992 HBasicBlock* loop_entry,
1993 BreakAndContinueInfo* break_info);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +00001994
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001995 // Create a back edge in the flow graph. body_exit is the predecessor
1996 // block and loop_entry is the successor block. loop_successor is the
1997 // block where control flow exits the loop normally (e.g., via failure of
1998 // the condition) and break_block is the block where control flow breaks
1999 // from the loop. All blocks except loop_entry can be NULL. The return
2000 // value is the new successor block which is the join of loop_successor
2001 // and break_block, or NULL.
2002 HBasicBlock* CreateLoop(IterationStatement* statement,
2003 HBasicBlock* loop_entry,
2004 HBasicBlock* body_exit,
2005 HBasicBlock* loop_successor,
2006 HBasicBlock* break_block);
2007
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00002008 // Build a loop entry
2009 HBasicBlock* BuildLoopEntry();
2010
2011 // Builds a loop entry respectful of OSR requirements
2012 HBasicBlock* BuildLoopEntry(IterationStatement* statement);
2013
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +00002014 HBasicBlock* JoinContinue(IterationStatement* statement,
2015 HBasicBlock* exit_block,
2016 HBasicBlock* continue_block);
2017
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002018 HValue* Top() const { return environment()->Top(); }
2019 void Drop(int n) { environment()->Drop(n); }
2020 void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002021 bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var,
2022 int index,
2023 HValue* value,
2024 HEnvironment* env) {
2025 if (!FLAG_analyze_environment_liveness) return false;
2026 // |this| and |arguments| are always live; zapping parameters isn't
2027 // safe because function.arguments can inspect them at any time.
2028 return !var->is_this() &&
2029 !var->is_arguments() &&
2030 !value->IsArgumentsObject() &&
2031 env->is_local_index(index);
2032 }
2033 void BindIfLive(Variable* var, HValue* value) {
2034 HEnvironment* env = environment();
2035 int index = env->IndexFor(var);
2036 env->Bind(index, value);
2037 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
2038 HEnvironmentMarker* bind =
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +00002039 Add<HEnvironmentMarker>(HEnvironmentMarker::BIND, index);
2040 USE(bind);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002041#ifdef DEBUG
2042 bind->set_closure(env->closure());
2043#endif
2044 }
2045 }
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +00002046
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002047 HValue* LookupAndMakeLive(Variable* var) {
2048 HEnvironment* env = environment();
2049 int index = env->IndexFor(var);
2050 HValue* value = env->Lookup(index);
2051 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
2052 HEnvironmentMarker* lookup =
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +00002053 Add<HEnvironmentMarker>(HEnvironmentMarker::LOOKUP, index);
2054 USE(lookup);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002055#ifdef DEBUG
2056 lookup->set_closure(env->closure());
2057#endif
2058 }
2059 return value;
2060 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002061
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00002062 // The value of the arguments object is allowed in some but not most value
2063 // contexts. (It's allowed in all effect contexts and disallowed in all
2064 // test contexts.)
2065 void VisitForValue(Expression* expr,
2066 ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002067 void VisitForTypeOf(Expression* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002068 void VisitForEffect(Expression* expr);
2069 void VisitForControl(Expression* expr,
2070 HBasicBlock* true_block,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002071 HBasicBlock* false_block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002072
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002073 // Visit an argument subexpression and emit a push to the outgoing arguments.
2074 void VisitArgument(Expression* expr);
vegorov@chromium.org3cf47312011-06-29 13:20:01 +00002075
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002076 void VisitArgumentList(ZoneList<Expression*>* arguments);
2077
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002078 // Visit a list of expressions from left to right, each in a value context.
2079 void VisitExpressions(ZoneList<Expression*>* exprs);
2080
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002081 // Remove the arguments from the bailout environment and emit instructions
2082 // to push them as outgoing parameters.
ulan@chromium.org967e2702012-02-28 09:49:15 +00002083 template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002084
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00002085 void SetUpScope(Scope* scope);
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00002086 virtual void VisitStatements(ZoneList<Statement*>* statements) V8_OVERRIDE;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002087
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00002088#define DECLARE_VISIT(type) virtual void Visit##type(type* node) V8_OVERRIDE;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002089 AST_NODE_LIST(DECLARE_VISIT)
2090#undef DECLARE_VISIT
2091
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00002092 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002093 // Helpers for flow graph construction.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002094 enum GlobalPropertyAccess {
2095 kUseCell,
2096 kUseGeneric
2097 };
2098 GlobalPropertyAccess LookupGlobalProperty(Variable* var,
2099 LookupResult* lookup,
2100 bool is_store);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002101
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002102 void EnsureArgumentsArePushedForAccess();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002103 bool TryArgumentsAccess(Property* expr);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00002104
2105 // Try to optimize fun.apply(receiver, arguments) pattern.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002106 bool TryCallApply(Call* expr);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00002107
jkummerow@chromium.org212d9642012-05-11 15:02:09 +00002108 int InliningAstSize(Handle<JSFunction> target);
ulan@chromium.org967e2702012-02-28 09:49:15 +00002109 bool TryInline(CallKind call_kind,
2110 Handle<JSFunction> target,
yangguo@chromium.org304cc332012-07-24 07:59:48 +00002111 int arguments_count,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002112 HValue* implicit_return_value,
2113 BailoutId ast_id,
2114 BailoutId return_id,
2115 InliningKind inlining_kind);
ulan@chromium.org967e2702012-02-28 09:49:15 +00002116
2117 bool TryInlineCall(Call* expr, bool drop_extra = false);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002118 bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +00002119 bool TryInlineGetter(Handle<JSFunction> getter,
2120 BailoutId ast_id,
2121 BailoutId return_id);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002122 bool TryInlineSetter(Handle<JSFunction> setter,
danno@chromium.orgb0deb652013-06-20 16:20:19 +00002123 BailoutId id,
2124 BailoutId assignment_id,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002125 HValue* implicit_return_value);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +00002126 bool TryInlineApply(Handle<JSFunction> function,
2127 Call* expr,
2128 int arguments_count);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00002129 bool TryInlineBuiltinMethodCall(Call* expr,
ulan@chromium.org967e2702012-02-28 09:49:15 +00002130 HValue* receiver,
2131 Handle<Map> receiver_map,
2132 CheckType check_type);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00002133 bool TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002134
2135 // If --trace-inlining, print a line of the inlining trace. Inlining
2136 // succeeded if the reason string is NULL and failed if there is a
2137 // non-NULL reason string.
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002138 void TraceInline(Handle<JSFunction> target,
2139 Handle<JSFunction> caller,
2140 const char* failure_reason);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002141
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002142 void HandleGlobalVariableAssignment(Variable* var,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002143 HValue* value,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002144 BailoutId ast_id);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002145
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002146 void HandlePropertyAssignment(Assignment* expr);
2147 void HandleCompoundAssignment(Assignment* expr);
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00002148 void HandlePolymorphicLoadNamedField(BailoutId ast_id,
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +00002149 BailoutId return_id,
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002150 HValue* object,
2151 SmallMapList* types,
2152 Handle<String> name);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002153
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +00002154 bool IsCallNewArrayInlineable(CallNew* expr);
2155 void BuildInlinedCallNewArray(CallNew* expr);
2156
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002157 class PropertyAccessInfo {
2158 public:
2159 PropertyAccessInfo(Isolate* isolate, Handle<Map> map, Handle<String> name)
2160 : lookup_(isolate),
2161 map_(map),
2162 name_(name),
2163 access_(HObjectAccess::ForMap()) { }
2164
2165 // Checkes whether this PropertyAccessInfo can be handled as a monomorphic
2166 // load named. It additionally fills in the fields necessary to generate the
2167 // lookup code.
2168 bool CanLoadMonomorphic();
2169
2170 // Checks whether all types behave uniform when loading name. If all maps
2171 // behave the same, a single monomorphic load instruction can be emitted,
2172 // guarded by a single map-checks instruction that whether the receiver is
2173 // an instance of any of the types.
2174 // This method skips the first type in types, assuming that this
2175 // PropertyAccessInfo is built for types->first().
2176 bool CanLoadAsMonomorphic(SmallMapList* types);
2177
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +00002178 bool IsJSObjectFieldAccessor() {
2179 int offset; // unused
2180 return Accessors::IsJSObjectFieldAccessor(map_, name_, &offset);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002181 }
2182
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +00002183 bool GetJSObjectFieldAccess(HObjectAccess* access) {
2184 if (IsStringLength()) {
2185 *access = HObjectAccess::ForStringLength();
2186 return true;
2187 } else if (IsArrayLength()) {
2188 *access = HObjectAccess::ForArrayLength(map_->elements_kind());
2189 return true;
2190 } else {
2191 int offset;
2192 if (Accessors::IsJSObjectFieldAccessor(map_, name_, &offset)) {
2193 *access = HObjectAccess::ForJSObjectOffset(offset);
2194 return true;
2195 }
2196 return false;
2197 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002198 }
2199
2200 bool has_holder() { return !holder_.is_null(); }
2201
2202 LookupResult* lookup() { return &lookup_; }
2203 Handle<Map> map() { return map_; }
2204 Handle<JSObject> holder() { return holder_; }
2205 Handle<JSFunction> accessor() { return accessor_; }
2206 Handle<Object> constant() { return constant_; }
2207 HObjectAccess access() { return access_; }
2208
2209 private:
2210 Isolate* isolate() { return lookup_.isolate(); }
2211
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +00002212 bool IsStringLength() {
2213 return map_->instance_type() < FIRST_NONSTRING_TYPE &&
2214 name_->Equals(isolate()->heap()->length_string());
2215 }
2216
2217 bool IsArrayLength() {
2218 return map_->instance_type() == JS_ARRAY_TYPE &&
2219 name_->Equals(isolate()->heap()->length_string());
2220 }
2221
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002222 bool LoadResult(Handle<Map> map);
2223 bool LookupDescriptor();
2224 bool LookupInPrototypes();
2225 bool IsCompatibleForLoad(PropertyAccessInfo* other);
2226
2227 void GeneralizeRepresentation(Representation r) {
2228 access_ = access_.WithRepresentation(
2229 access_.representation().generalize(r));
2230 }
2231
2232 LookupResult lookup_;
2233 Handle<Map> map_;
2234 Handle<String> name_;
2235 Handle<JSObject> holder_;
2236 Handle<JSFunction> accessor_;
2237 Handle<Object> constant_;
2238 HObjectAccess access_;
2239 };
2240
2241 HInstruction* BuildLoadMonomorphic(PropertyAccessInfo* info,
2242 HValue* object,
2243 HInstruction* checked_object,
2244 BailoutId ast_id,
2245 BailoutId return_id,
2246 bool can_inline_accessor = true);
2247
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00002248 void HandlePolymorphicStoreNamedField(BailoutId assignment_id,
danno@chromium.orgfe578672013-06-15 14:38:35 +00002249 HValue* object,
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002250 HValue* value,
danno@chromium.orgfe578672013-06-15 14:38:35 +00002251 SmallMapList* types,
2252 Handle<String> name);
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00002253 bool TryStorePolymorphicAsMonomorphic(BailoutId assignment_id,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002254 HValue* object,
2255 HValue* value,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00002256 SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002257 Handle<String> name);
2258 void HandlePolymorphicCallNamed(Call* expr,
2259 HValue* receiver,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00002260 SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002261 Handle<String> name);
danno@chromium.orgbee51992013-07-10 14:57:15 +00002262 bool TryCallPolymorphicAsMonomorphic(Call* expr,
2263 HValue* receiver,
2264 SmallMapList* types,
2265 Handle<String> name);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002266 void HandleLiteralCompareTypeof(CompareOperation* expr,
jkummerow@chromium.org96a3c512013-07-18 17:02:47 +00002267 Expression* sub_expr,
ager@chromium.org04921a82011-06-27 13:21:41 +00002268 Handle<String> check);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002269 void HandleLiteralCompareNil(CompareOperation* expr,
jkummerow@chromium.org96a3c512013-07-18 17:02:47 +00002270 Expression* sub_expr,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002271 NilValue nil);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002272
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002273 HInstruction* BuildStringCharCodeAt(HValue* string,
ulan@chromium.org2e04b582013-02-21 14:06:02 +00002274 HValue* index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002275 HInstruction* BuildBinaryOperation(BinaryOperation* expr,
2276 HValue* left,
2277 HValue* right);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00002278 HInstruction* BuildIncrement(bool returns_original_input,
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00002279 CountOperation* expr);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002280 HInstruction* BuildLoadKeyedGeneric(HValue* object,
2281 HValue* key);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002282
mstarzinger@chromium.orgc6d9cee2012-07-03 10:03:19 +00002283 HInstruction* TryBuildConsolidatedElementLoad(HValue* object,
2284 HValue* key,
2285 HValue* val,
2286 SmallMapList* maps);
2287
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00002288 LoadKeyedHoleMode BuildKeyedHoleMode(Handle<Map> map);
2289
whesse@chromium.org7b260152011-06-20 15:33:18 +00002290 HInstruction* BuildMonomorphicElementAccess(HValue* object,
2291 HValue* key,
2292 HValue* val,
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00002293 HValue* dependency,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002294 Handle<Map> map,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00002295 bool is_store,
2296 KeyedAccessStoreMode store_mode);
mstarzinger@chromium.orgc6d9cee2012-07-03 10:03:19 +00002297
whesse@chromium.org7b260152011-06-20 15:33:18 +00002298 HValue* HandlePolymorphicElementAccess(HValue* object,
2299 HValue* key,
2300 HValue* val,
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +00002301 SmallMapList* maps,
whesse@chromium.org7b260152011-06-20 15:33:18 +00002302 bool is_store,
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00002303 KeyedAccessStoreMode store_mode,
whesse@chromium.org7b260152011-06-20 15:33:18 +00002304 bool* has_side_effects);
2305
2306 HValue* HandleKeyedElementAccess(HValue* obj,
2307 HValue* key,
2308 HValue* val,
2309 Expression* expr,
whesse@chromium.org7b260152011-06-20 15:33:18 +00002310 bool is_store,
2311 bool* has_side_effects);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00002312
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00002313 HInstruction* BuildLoadNamedGeneric(HValue* object,
2314 Handle<String> name,
2315 Property* expr);
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00002316
verwaest@chromium.org003a9252013-08-12 17:15:20 +00002317 HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map);
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00002318
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +00002319 void BuildLoad(Property* property,
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +00002320 BailoutId ast_id);
2321 void PushLoad(Property* property,
2322 HValue* object,
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +00002323 HValue* key);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +00002324
dslomov@chromium.org639bac02013-09-09 11:58:54 +00002325 void BuildStoreForEffect(Expression* expression,
2326 Property* prop,
2327 BailoutId ast_id,
2328 BailoutId return_id,
2329 HValue* object,
2330 HValue* key,
2331 HValue* value);
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +00002332
dslomov@chromium.org639bac02013-09-09 11:58:54 +00002333 void BuildStore(Expression* expression,
2334 Property* prop,
2335 BailoutId ast_id,
2336 BailoutId return_id,
2337 bool is_uninitialized = false);
danno@chromium.orgb0deb652013-06-20 16:20:19 +00002338
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002339 HInstruction* BuildStoreNamedField(HValue* object,
2340 Handle<String> name,
2341 HValue* value,
verwaest@chromium.orgb6d052d2012-07-27 08:03:27 +00002342 Handle<Map> map,
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002343 LookupResult* lookup);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002344 HInstruction* BuildStoreNamedGeneric(HValue* object,
2345 Handle<String> name,
2346 HValue* value);
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00002347 HInstruction* BuildStoreNamedMonomorphic(HValue* object,
2348 Handle<String> name,
2349 HValue* value,
2350 Handle<Map> map);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002351 HInstruction* BuildStoreKeyedGeneric(HValue* object,
2352 HValue* key,
2353 HValue* value);
2354
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002355 HValue* BuildContextChainWalk(Variable* var);
2356
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00002357 HInstruction* BuildThisFunction();
2358
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +00002359 HInstruction* BuildFastLiteral(Handle<JSObject> boilerplate_object,
2360 AllocationSiteContext* site_context);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002361
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002362 void BuildEmitObjectHeader(Handle<JSObject> boilerplate_object,
2363 HInstruction* object);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002364
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002365 void BuildInitElementsInObjectHeader(Handle<JSObject> boilerplate_object,
2366 HInstruction* object,
2367 HInstruction* object_elements);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002368
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00002369 void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object,
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +00002370 HInstruction* object,
2371 AllocationSiteContext* site_context);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00002372
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002373 void BuildEmitElements(Handle<JSObject> boilerplate_object,
2374 Handle<FixedArrayBase> elements,
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +00002375 HValue* object_elements,
2376 AllocationSiteContext* site_context);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00002377
2378 void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements,
2379 ElementsKind kind,
2380 HValue* object_elements);
2381
2382 void BuildEmitFixedArray(Handle<FixedArrayBase> elements,
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00002383 ElementsKind kind,
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +00002384 HValue* object_elements,
2385 AllocationSiteContext* site_context);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00002386
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002387 void AddCheckPrototypeMaps(Handle<JSObject> holder,
2388 Handle<Map> receiver_map);
2389
yangguo@chromium.org99aa4902012-07-06 16:21:55 +00002390 void AddCheckConstantFunction(Handle<JSObject> holder,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002391 HValue* receiver,
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002392 Handle<Map> receiver_map);
2393
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002394 // The translation state of the currently-being-translated function.
2395 FunctionState* function_state_;
2396
2397 // The base of the function state stack.
2398 FunctionState initial_function_state_;
2399
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002400 // Expression context of the currently visited subexpression. NULL when
2401 // visiting statements.
2402 AstContext* ast_context_;
2403
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002404 // A stack of breakable statements entered.
2405 BreakAndContinueScope* break_scope_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002406
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002407 int inlined_count_;
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00002408 ZoneList<Handle<Object> > globals_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002409
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002410 bool inline_bailout_;
2411
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00002412 HOsrBuilder* osr_;
2413
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002414 friend class FunctionState; // Pushes and pops the state stack.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002415 friend class AstContext; // Pushes and pops the AST context stack.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002416 friend class KeyedLoadFastElementStub;
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00002417 friend class HOsrBuilder;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002418
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002419 DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002420};
2421
2422
mmassi@chromium.org7028c052012-06-13 11:51:58 +00002423Zone* AstContext::zone() const { return owner_->zone(); }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00002424
2425
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00002426class HStatistics V8_FINAL: public Malloced {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002427 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002428 HStatistics()
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002429 : times_(5),
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002430 names_(5),
2431 sizes_(5),
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002432 total_size_(0),
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00002433 source_size_(0) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002434
ulan@chromium.org750145a2013-03-07 15:14:13 +00002435 void Initialize(CompilationInfo* info);
2436 void Print();
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002437 void SaveTiming(const char* name, TimeDelta time, unsigned size);
ulan@chromium.org750145a2013-03-07 15:14:13 +00002438
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002439 void IncrementFullCodeGen(TimeDelta full_code_gen) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002440 full_code_gen_ += full_code_gen;
2441 }
2442
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002443 void IncrementSubtotals(TimeDelta create_graph,
2444 TimeDelta optimize_graph,
2445 TimeDelta generate_code) {
ulan@chromium.org750145a2013-03-07 15:14:13 +00002446 create_graph_ += create_graph;
2447 optimize_graph_ += optimize_graph;
2448 generate_code_ += generate_code;
2449 }
2450
2451 private:
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002452 List<TimeDelta> times_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002453 List<const char*> names_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002454 List<unsigned> sizes_;
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002455 TimeDelta create_graph_;
2456 TimeDelta optimize_graph_;
2457 TimeDelta generate_code_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002458 unsigned total_size_;
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00002459 TimeDelta full_code_gen_;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00002460 double source_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002461};
2462
2463
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002464class HPhase : public CompilationPhase {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002465 public:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002466 HPhase(const char* name, HGraph* graph)
2467 : CompilationPhase(name, graph->info()),
2468 graph_(graph) { }
ulan@chromium.org750145a2013-03-07 15:14:13 +00002469 ~HPhase();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002470
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002471 protected:
2472 HGraph* graph() const { return graph_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002473
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002474 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002475 HGraph* graph_;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002476
2477 DISALLOW_COPY_AND_ASSIGN(HPhase);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002478};
2479
2480
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00002481class HTracer V8_FINAL : public Malloced {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002482 public:
ulan@chromium.org750145a2013-03-07 15:14:13 +00002483 explicit HTracer(int isolate_id)
2484 : trace_(&string_allocator_), indent_(0) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00002485 if (FLAG_trace_hydrogen_file == NULL) {
2486 OS::SNPrintF(filename_,
2487 "hydrogen-%d-%d.cfg",
2488 OS::GetCurrentProcessId(),
2489 isolate_id);
2490 } else {
2491 OS::StrNCpy(filename_, FLAG_trace_hydrogen_file, filename_.length());
2492 }
ulan@chromium.org750145a2013-03-07 15:14:13 +00002493 WriteChars(filename_.start(), "", 0, false);
2494 }
2495
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002496 void TraceCompilation(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002497 void TraceHydrogen(const char* name, HGraph* graph);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00002498 void TraceLithium(const char* name, LChunk* chunk);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002499 void TraceLiveRanges(const char* name, LAllocator* allocator);
2500
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002501 private:
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00002502 class Tag V8_FINAL BASE_EMBEDDED {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002503 public:
2504 Tag(HTracer* tracer, const char* name) {
2505 name_ = name;
2506 tracer_ = tracer;
2507 tracer->PrintIndent();
2508 tracer->trace_.Add("begin_%s\n", name);
2509 tracer->indent_++;
2510 }
2511
2512 ~Tag() {
2513 tracer_->indent_--;
2514 tracer_->PrintIndent();
2515 tracer_->trace_.Add("end_%s\n", name_);
2516 ASSERT(tracer_->indent_ >= 0);
2517 tracer_->FlushToFile();
2518 }
2519
2520 private:
2521 HTracer* tracer_;
2522 const char* name_;
2523 };
2524
mmassi@chromium.org7028c052012-06-13 11:51:58 +00002525 void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00002526 void Trace(const char* name, HGraph* graph, LChunk* chunk);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002527 void FlushToFile();
2528
2529 void PrintEmptyProperty(const char* name) {
2530 PrintIndent();
2531 trace_.Add("%s\n", name);
2532 }
2533
2534 void PrintStringProperty(const char* name, const char* value) {
2535 PrintIndent();
2536 trace_.Add("%s \"%s\"\n", name, value);
2537 }
2538
2539 void PrintLongProperty(const char* name, int64_t value) {
2540 PrintIndent();
2541 trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
2542 }
2543
2544 void PrintBlockProperty(const char* name, int block_id) {
2545 PrintIndent();
2546 trace_.Add("%s \"B%d\"\n", name, block_id);
2547 }
2548
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002549 void PrintIntProperty(const char* name, int value) {
2550 PrintIndent();
2551 trace_.Add("%s %d\n", name, value);
2552 }
2553
2554 void PrintIndent() {
2555 for (int i = 0; i < indent_; i++) {
2556 trace_.Add(" ");
2557 }
2558 }
2559
ulan@chromium.org750145a2013-03-07 15:14:13 +00002560 EmbeddedVector<char, 64> filename_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002561 HeapStringAllocator string_allocator_;
2562 StringStream trace_;
2563 int indent_;
2564};
2565
2566
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00002567class NoObservableSideEffectsScope V8_FINAL {
danno@chromium.orgad75d6f2013-08-12 16:57:59 +00002568 public:
2569 explicit NoObservableSideEffectsScope(HGraphBuilder* builder) :
2570 builder_(builder) {
2571 builder_->graph()->IncrementInNoSideEffectsScope();
2572 }
2573 ~NoObservableSideEffectsScope() {
2574 builder_->graph()->DecrementInNoSideEffectsScope();
2575 }
2576
2577 private:
2578 HGraphBuilder* builder_;
2579};
2580
2581
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002582} } // namespace v8::internal
2583
2584#endif // V8_HYDROGEN_H_