blob: 05c42dd7f0e2ac24343c9dc98efd51bac9d070f5 [file] [log] [blame]
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001// Copyright 2011 the V8 project authors. All rights reserved.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_HYDROGEN_H_
29#define V8_HYDROGEN_H_
30
31#include "v8.h"
32
lrn@chromium.org1c092762011-05-09 09:42:16 +000033#include "allocation.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000034#include "ast.h"
35#include "compiler.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000036#include "hydrogen-instructions.h"
vegorov@chromium.org7304bca2011-05-16 12:14:13 +000037#include "type-info.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000038#include "zone.h"
39
40namespace v8 {
41namespace internal {
42
43// Forward declarations.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000044class BitVector;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000045class HEnvironment;
46class HGraph;
47class HLoopInformation;
48class HTracer;
49class LAllocator;
50class LChunk;
51class LiveRange;
52
53
54class HBasicBlock: public ZoneObject {
55 public:
56 explicit HBasicBlock(HGraph* graph);
57 virtual ~HBasicBlock() { }
58
59 // Simple accessors.
60 int block_id() const { return block_id_; }
61 void set_block_id(int id) { block_id_ = id; }
62 HGraph* graph() const { return graph_; }
63 const ZoneList<HPhi*>* phis() const { return &phis_; }
64 HInstruction* first() const { return first_; }
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +000065 HInstruction* last() const { return last_; }
66 void set_last(HInstruction* instr) { last_ = instr; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +000067 HInstruction* GetLastInstruction();
68 HControlInstruction* end() const { return end_; }
69 HLoopInformation* loop_information() const { return loop_information_; }
70 const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; }
71 bool HasPredecessor() const { return predecessors_.length() > 0; }
72 const ZoneList<HBasicBlock*>* dominated_blocks() const {
73 return &dominated_blocks_;
74 }
75 const ZoneList<int>* deleted_phis() const {
76 return &deleted_phis_;
77 }
78 void RecordDeletedPhi(int merge_index) {
79 deleted_phis_.Add(merge_index);
80 }
81 HBasicBlock* dominator() const { return dominator_; }
82 HEnvironment* last_environment() const { return last_environment_; }
83 int argument_count() const { return argument_count_; }
84 void set_argument_count(int count) { argument_count_ = count; }
85 int first_instruction_index() const { return first_instruction_index_; }
86 void set_first_instruction_index(int index) {
87 first_instruction_index_ = index;
88 }
89 int last_instruction_index() const { return last_instruction_index_; }
90 void set_last_instruction_index(int index) {
91 last_instruction_index_ = index;
92 }
93
94 void AttachLoopInformation();
95 void DetachLoopInformation();
96 bool IsLoopHeader() const { return loop_information() != NULL; }
97 bool IsStartBlock() const { return block_id() == 0; }
98 void PostProcessLoopHeader(IterationStatement* stmt);
99
100 bool IsFinished() const { return end_ != NULL; }
101 void AddPhi(HPhi* phi);
102 void RemovePhi(HPhi* phi);
103 void AddInstruction(HInstruction* instr);
104 bool Dominates(HBasicBlock* other) const;
105
106 void SetInitialEnvironment(HEnvironment* env);
107 void ClearEnvironment() { last_environment_ = NULL; }
108 bool HasEnvironment() const { return last_environment_ != NULL; }
109 void UpdateEnvironment(HEnvironment* env) { last_environment_ = env; }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000110 HBasicBlock* parent_loop_header() const { return parent_loop_header_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000111
112 void set_parent_loop_header(HBasicBlock* block) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000113 ASSERT(parent_loop_header_ == NULL);
114 parent_loop_header_ = block;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000115 }
116
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000117 bool HasParentLoopHeader() const { return parent_loop_header_ != NULL; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000118
ager@chromium.org04921a82011-06-27 13:21:41 +0000119 void SetJoinId(int ast_id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000120
121 void Finish(HControlInstruction* last);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000122 void FinishExit(HControlInstruction* instruction);
ager@chromium.org04921a82011-06-27 13:21:41 +0000123 void Goto(HBasicBlock* block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000124
125 int PredecessorIndexOf(HBasicBlock* predecessor) const;
ager@chromium.org04921a82011-06-27 13:21:41 +0000126 void AddSimulate(int ast_id) { AddInstruction(CreateSimulate(ast_id)); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000127 void AssignCommonDominator(HBasicBlock* other);
128
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000129 void FinishExitWithDeoptimization(HDeoptimize::UseEnvironment has_uses) {
130 FinishExit(CreateDeoptimize(has_uses));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000131 }
132
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000133 // Add the inlined function exit sequence, adding an HLeaveInlined
134 // instruction and updating the bailout environment.
135 void AddLeaveInlined(HValue* return_value, HBasicBlock* target);
136
137 // If a target block is tagged as an inline function return, all
138 // predecessors should contain the inlined exit sequence:
139 //
140 // LeaveInlined
141 // Simulate (caller's environment)
142 // Goto (target block)
143 bool IsInlineReturnTarget() const { return is_inline_return_target_; }
144 void MarkAsInlineReturnTarget() { is_inline_return_target_ = true; }
145
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000146 bool IsDeoptimizing() const { return is_deoptimizing_; }
147 void MarkAsDeoptimizing() { is_deoptimizing_ = true; }
148
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000149 inline Zone* zone();
150
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000151#ifdef DEBUG
152 void Verify();
153#endif
154
155 private:
156 void RegisterPredecessor(HBasicBlock* pred);
157 void AddDominatedBlock(HBasicBlock* block);
158
ager@chromium.org04921a82011-06-27 13:21:41 +0000159 HSimulate* CreateSimulate(int ast_id);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000160 HDeoptimize* CreateDeoptimize(HDeoptimize::UseEnvironment has_uses);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000161
162 int block_id_;
163 HGraph* graph_;
164 ZoneList<HPhi*> phis_;
165 HInstruction* first_;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000166 HInstruction* last_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000167 HControlInstruction* end_;
168 HLoopInformation* loop_information_;
169 ZoneList<HBasicBlock*> predecessors_;
170 HBasicBlock* dominator_;
171 ZoneList<HBasicBlock*> dominated_blocks_;
172 HEnvironment* last_environment_;
173 // Outgoing parameter count at block exit, set during lithium translation.
174 int argument_count_;
175 // Instruction indices into the lithium code stream.
176 int first_instruction_index_;
177 int last_instruction_index_;
178 ZoneList<int> deleted_phis_;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000179 HBasicBlock* parent_loop_header_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000180 bool is_inline_return_target_;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000181 bool is_deoptimizing_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000182};
183
184
185class HLoopInformation: public ZoneObject {
186 public:
187 explicit HLoopInformation(HBasicBlock* loop_header)
ager@chromium.org04921a82011-06-27 13:21:41 +0000188 : back_edges_(4),
189 loop_header_(loop_header),
190 blocks_(8),
191 stack_check_(NULL) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000192 blocks_.Add(loop_header);
193 }
194 virtual ~HLoopInformation() {}
195
196 const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; }
197 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
198 HBasicBlock* loop_header() const { return loop_header_; }
199 HBasicBlock* GetLastBackEdge() const;
200 void RegisterBackEdge(HBasicBlock* block);
201
ager@chromium.org04921a82011-06-27 13:21:41 +0000202 HStackCheck* stack_check() const { return stack_check_; }
203 void set_stack_check(HStackCheck* stack_check) {
204 stack_check_ = stack_check;
205 }
206
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000207 private:
208 void AddBlock(HBasicBlock* block);
209
210 ZoneList<HBasicBlock*> back_edges_;
211 HBasicBlock* loop_header_;
212 ZoneList<HBasicBlock*> blocks_;
ager@chromium.org04921a82011-06-27 13:21:41 +0000213 HStackCheck* stack_check_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000214};
215
216
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000217class HGraph: public ZoneObject {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000218 public:
219 explicit HGraph(CompilationInfo* info);
220
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000221 Isolate* isolate() { return isolate_; }
222 Zone* zone() { return isolate_->zone(); }
223
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000224 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
225 const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000226 HBasicBlock* entry_block() const { return entry_block_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000227 HEnvironment* start_environment() const { return start_environment_; }
228
229 void InitializeInferredTypes();
230 void InsertTypeConversions();
231 void InsertRepresentationChanges();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000232 void MarkDeoptimizeOnUndefined();
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000233 void ComputeMinusZeroChecks();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000234 bool ProcessArgumentsObject();
235 void EliminateRedundantPhis();
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000236 void EliminateUnreachablePhis();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000237 void Canonicalize();
238 void OrderBlocks();
239 void AssignDominators();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000240 void ReplaceCheckedValues();
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000241 void PropagateDeoptimizingMark();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000242
243 // Returns false if there are phi-uses of the arguments-object
244 // which are not supported by the optimizing compiler.
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +0000245 bool CheckPhis();
246
247 // Returns false if there are phi-uses of hole values comming
248 // from uninitialized consts.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000249 bool CollectPhis();
250
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000251 Handle<Code> Compile(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000252
253 void set_undefined_constant(HConstant* constant) {
254 undefined_constant_.set(constant);
255 }
256 HConstant* GetConstantUndefined() const { return undefined_constant_.get(); }
257 HConstant* GetConstant1();
258 HConstant* GetConstantMinus1();
259 HConstant* GetConstantTrue();
260 HConstant* GetConstantFalse();
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000261 HConstant* GetConstantHole();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000262
263 HBasicBlock* CreateBasicBlock();
264 HArgumentsObject* GetArgumentsObject() const {
265 return arguments_object_.get();
266 }
267 bool HasArgumentsObject() const { return arguments_object_.is_set(); }
268
269 void SetArgumentsObject(HArgumentsObject* object) {
270 arguments_object_.set(object);
271 }
272
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000273 int GetMaximumValueID() const { return values_.length(); }
274 int GetNextBlockID() { return next_block_id_++; }
275 int GetNextValueID(HValue* value) {
276 values_.Add(value);
277 return values_.length() - 1;
278 }
279 HValue* LookupValue(int id) const {
280 if (id >= 0 && id < values_.length()) return values_[id];
281 return NULL;
282 }
283
284#ifdef DEBUG
285 void Verify() const;
286#endif
287
288 private:
289 void Postorder(HBasicBlock* block,
290 BitVector* visited,
291 ZoneList<HBasicBlock*>* order,
292 HBasicBlock* loop_header);
293 void PostorderLoopBlocks(HLoopInformation* loop,
294 BitVector* visited,
295 ZoneList<HBasicBlock*>* order,
296 HBasicBlock* loop_header);
297 HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
298 Object* value);
299
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000300 void MarkAsDeoptimizingRecursively(HBasicBlock* block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000301 void InsertTypeConversions(HInstruction* instr);
302 void PropagateMinusZeroChecks(HValue* value, BitVector* visited);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000303 void RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000304 void InsertRepresentationChangeForUse(HValue* value,
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000305 HValue* use_value,
306 int use_index,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000307 Representation to);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000308 void InsertRepresentationChangesForValue(HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000309 void InferTypes(ZoneList<HValue*>* worklist);
310 void InitializeInferredTypes(int from_inclusive, int to_inclusive);
311 void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor);
312
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000313 Isolate* isolate_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000314 int next_block_id_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000315 HBasicBlock* entry_block_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000316 HEnvironment* start_environment_;
317 ZoneList<HBasicBlock*> blocks_;
318 ZoneList<HValue*> values_;
319 ZoneList<HPhi*>* phi_list_;
320 SetOncePointer<HConstant> undefined_constant_;
321 SetOncePointer<HConstant> constant_1_;
322 SetOncePointer<HConstant> constant_minus1_;
323 SetOncePointer<HConstant> constant_true_;
324 SetOncePointer<HConstant> constant_false_;
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000325 SetOncePointer<HConstant> constant_hole_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000326 SetOncePointer<HArgumentsObject> arguments_object_;
327
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000328 DISALLOW_COPY_AND_ASSIGN(HGraph);
329};
330
331
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000332Zone* HBasicBlock::zone() { return graph_->zone(); }
333
334
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000335class HEnvironment: public ZoneObject {
336 public:
337 HEnvironment(HEnvironment* outer,
338 Scope* scope,
339 Handle<JSFunction> closure);
340
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000341 // Simple accessors.
342 Handle<JSFunction> closure() const { return closure_; }
343 const ZoneList<HValue*>* values() const { return &values_; }
344 const ZoneList<int>* assigned_variables() const {
345 return &assigned_variables_;
346 }
347 int parameter_count() const { return parameter_count_; }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000348 int specials_count() const { return specials_count_; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000349 int local_count() const { return local_count_; }
350 HEnvironment* outer() const { return outer_; }
351 int pop_count() const { return pop_count_; }
352 int push_count() const { return push_count_; }
353
354 int ast_id() const { return ast_id_; }
355 void set_ast_id(int id) { ast_id_ = id; }
356
357 int length() const { return values_.length(); }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000358 bool is_special_index(int i) const {
359 return i >= parameter_count() && i < parameter_count() + specials_count();
360 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000361
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000362 void Bind(Variable* variable, HValue* value) {
363 Bind(IndexFor(variable), value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000364 }
365
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000366 void Bind(int index, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000367
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000368 void BindContext(HValue* value) {
369 Bind(parameter_count(), value);
370 }
371
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000372 HValue* Lookup(Variable* variable) const {
373 return Lookup(IndexFor(variable));
374 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000375
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000376 HValue* Lookup(int index) const {
377 HValue* result = values_[index];
378 ASSERT(result != NULL);
379 return result;
380 }
381
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000382 HValue* LookupContext() const {
383 // Return first special.
384 return Lookup(parameter_count());
385 }
386
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000387 void Push(HValue* value) {
388 ASSERT(value != NULL);
389 ++push_count_;
390 values_.Add(value);
391 }
392
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000393 HValue* Pop() {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000394 ASSERT(!ExpressionStackIsEmpty());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000395 if (push_count_ > 0) {
396 --push_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000397 } else {
398 ++pop_count_;
399 }
400 return values_.RemoveLast();
401 }
402
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000403 void Drop(int count);
404
405 HValue* Top() const { return ExpressionStackAt(0); }
406
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000407 bool ExpressionStackIsEmpty() const;
408
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000409 HValue* ExpressionStackAt(int index_from_top) const {
410 int index = length() - index_from_top - 1;
411 ASSERT(HasExpressionAt(index));
412 return values_[index];
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000413 }
414
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000415 void SetExpressionStackAt(int index_from_top, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000416
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000417 HEnvironment* Copy() const;
418 HEnvironment* CopyWithoutHistory() const;
419 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const;
420
421 // Create an "inlined version" of this environment, where the original
422 // environment is the outer environment but the top expression stack
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000423 // elements are moved to an inner environment as parameters.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000424 HEnvironment* CopyForInlining(Handle<JSFunction> target,
425 FunctionLiteral* function,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000426 HConstant* undefined,
427 CallKind call_kind) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000428
429 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000430
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000431 void ClearHistory() {
432 pop_count_ = 0;
433 push_count_ = 0;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000434 assigned_variables_.Rewind(0);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000435 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000436
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000437 void SetValueAt(int index, HValue* value) {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000438 ASSERT(index < length());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000439 values_[index] = value;
440 }
441
442 void PrintTo(StringStream* stream);
443 void PrintToStd();
444
445 private:
446 explicit HEnvironment(const HEnvironment* other);
447
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000448 // True if index is included in the expression stack part of the environment.
449 bool HasExpressionAt(int index) const;
450
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000451 void Initialize(int parameter_count, int local_count, int stack_height);
452 void Initialize(const HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000453
454 // Map a variable to an environment index. Parameter indices are shifted
455 // by 1 (receiver is parameter index -1 but environment index 0).
456 // Stack-allocated local indices are shifted by the number of parameters.
457 int IndexFor(Variable* variable) const {
458 Slot* slot = variable->AsSlot();
459 ASSERT(slot != NULL && slot->IsStackAllocated());
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000460 int shift = (slot->type() == Slot::PARAMETER)
461 ? 1
462 : parameter_count_ + specials_count_;
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000463 return slot->index() + shift;
464 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000465
466 Handle<JSFunction> closure_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000467 // Value array [parameters] [specials] [locals] [temporaries].
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000468 ZoneList<HValue*> values_;
469 ZoneList<int> assigned_variables_;
470 int parameter_count_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000471 int specials_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000472 int local_count_;
473 HEnvironment* outer_;
474 int pop_count_;
475 int push_count_;
476 int ast_id_;
477};
478
479
480class HGraphBuilder;
481
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000482enum ArgumentsAllowedFlag {
483 ARGUMENTS_NOT_ALLOWED,
484 ARGUMENTS_ALLOWED
485};
486
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000487// This class is not BASE_EMBEDDED because our inlining implementation uses
488// new and delete.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000489class AstContext {
490 public:
491 bool IsEffect() const { return kind_ == Expression::kEffect; }
492 bool IsValue() const { return kind_ == Expression::kValue; }
493 bool IsTest() const { return kind_ == Expression::kTest; }
494
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000495 // 'Fill' this context with a hydrogen value. The value is assumed to
496 // have already been inserted in the instruction stream (or not need to
497 // be, e.g., HPhi). Call this function in tail position in the Visit
498 // functions for expressions.
499 virtual void ReturnValue(HValue* value) = 0;
500
501 // Add a hydrogen instruction to the instruction stream (recording an
502 // environment simulation if necessary) and then fill this context with
503 // the instruction as value.
504 virtual void ReturnInstruction(HInstruction* instr, int ast_id) = 0;
505
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000506 // Finishes the current basic block and materialize a boolean for
507 // value context, nothing for effect, generate a branch for test context.
508 // Call this function in tail position in the Visit functions for
509 // expressions.
510 virtual void ReturnControl(HControlInstruction* instr, int ast_id) = 0;
511
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000512 void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; }
513 bool is_for_typeof() { return for_typeof_; }
514
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000515 protected:
516 AstContext(HGraphBuilder* owner, Expression::Context kind);
517 virtual ~AstContext();
518
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000519 HGraphBuilder* owner() const { return owner_; }
520
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000521 inline Zone* zone();
522
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000523 // We want to be able to assert, in a context-specific way, that the stack
524 // height makes sense when the context is filled.
525#ifdef DEBUG
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000526 int original_length_;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000527#endif
528
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000529 private:
530 HGraphBuilder* owner_;
531 Expression::Context kind_;
532 AstContext* outer_;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000533 bool for_typeof_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000534};
535
536
537class EffectContext: public AstContext {
538 public:
539 explicit EffectContext(HGraphBuilder* owner)
540 : AstContext(owner, Expression::kEffect) {
541 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000542 virtual ~EffectContext();
543
544 virtual void ReturnValue(HValue* value);
545 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000546 virtual void ReturnControl(HControlInstruction* instr, int ast_id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000547};
548
549
550class ValueContext: public AstContext {
551 public:
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000552 explicit ValueContext(HGraphBuilder* owner, ArgumentsAllowedFlag flag)
553 : AstContext(owner, Expression::kValue), flag_(flag) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000554 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000555 virtual ~ValueContext();
556
557 virtual void ReturnValue(HValue* value);
558 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000559 virtual void ReturnControl(HControlInstruction* instr, int ast_id);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000560
561 bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
562
563 private:
564 ArgumentsAllowedFlag flag_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000565};
566
567
568class TestContext: public AstContext {
569 public:
570 TestContext(HGraphBuilder* owner,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000571 Expression* condition,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000572 HBasicBlock* if_true,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000573 HBasicBlock* if_false)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000574 : AstContext(owner, Expression::kTest),
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000575 condition_(condition),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000576 if_true_(if_true),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000577 if_false_(if_false) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000578 }
579
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000580 virtual void ReturnValue(HValue* value);
581 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000582 virtual void ReturnControl(HControlInstruction* instr, int ast_id);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000583
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000584 static TestContext* cast(AstContext* context) {
585 ASSERT(context->IsTest());
586 return reinterpret_cast<TestContext*>(context);
587 }
588
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000589 Expression* condition() const { return condition_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000590 HBasicBlock* if_true() const { return if_true_; }
591 HBasicBlock* if_false() const { return if_false_; }
592
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000593 private:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000594 // Build the shared core part of the translation unpacking a value into
595 // control flow.
596 void BuildBranch(HValue* value);
597
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000598 Expression* condition_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000599 HBasicBlock* if_true_;
600 HBasicBlock* if_false_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000601};
602
603
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000604class FunctionState BASE_EMBEDDED {
605 public:
606 FunctionState(HGraphBuilder* owner,
607 CompilationInfo* info,
608 TypeFeedbackOracle* oracle);
609 ~FunctionState();
610
611 CompilationInfo* compilation_info() { return compilation_info_; }
612 TypeFeedbackOracle* oracle() { return oracle_; }
613 AstContext* call_context() { return call_context_; }
614 HBasicBlock* function_return() { return function_return_; }
615 TestContext* test_context() { return test_context_; }
616 void ClearInlinedTestContext() {
617 delete test_context_;
618 test_context_ = NULL;
619 }
620
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000621 FunctionState* outer() { return outer_; }
622
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000623 private:
624 HGraphBuilder* owner_;
625
626 CompilationInfo* compilation_info_;
627 TypeFeedbackOracle* oracle_;
628
629 // During function inlining, expression context of the call being
630 // inlined. NULL when not inlining.
631 AstContext* call_context_;
632
633 // When inlining in an effect of value context, this is the return block.
634 // It is NULL otherwise. When inlining in a test context, there are a
635 // pair of return blocks in the context. When not inlining, there is no
636 // local return point.
637 HBasicBlock* function_return_;
638
639 // When inlining a call in a test context, a context containing a pair of
640 // return blocks. NULL in all other cases.
641 TestContext* test_context_;
642
643 FunctionState* outer_;
644};
645
646
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000647class HGraphBuilder: public AstVisitor {
648 public:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000649 enum BreakType { BREAK, CONTINUE };
650
651 // A class encapsulating (lazily-allocated) break and continue blocks for
652 // a breakable statement. Separated from BreakAndContinueScope so that it
653 // can have a separate lifetime.
654 class BreakAndContinueInfo BASE_EMBEDDED {
655 public:
656 explicit BreakAndContinueInfo(BreakableStatement* target)
657 : target_(target), break_block_(NULL), continue_block_(NULL) {
658 }
659
660 BreakableStatement* target() { return target_; }
661 HBasicBlock* break_block() { return break_block_; }
662 void set_break_block(HBasicBlock* block) { break_block_ = block; }
663 HBasicBlock* continue_block() { return continue_block_; }
664 void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
665
666 private:
667 BreakableStatement* target_;
668 HBasicBlock* break_block_;
669 HBasicBlock* continue_block_;
670 };
671
672 // A helper class to maintain a stack of current BreakAndContinueInfo
673 // structures mirroring BreakableStatement nesting.
674 class BreakAndContinueScope BASE_EMBEDDED {
675 public:
676 BreakAndContinueScope(BreakAndContinueInfo* info, HGraphBuilder* owner)
677 : info_(info), owner_(owner), next_(owner->break_scope()) {
678 owner->set_break_scope(this);
679 }
680
681 ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
682
683 BreakAndContinueInfo* info() { return info_; }
684 HGraphBuilder* owner() { return owner_; }
685 BreakAndContinueScope* next() { return next_; }
686
687 // Search the break stack for a break or continue target.
688 HBasicBlock* Get(BreakableStatement* stmt, BreakType type);
689
690 private:
691 BreakAndContinueInfo* info_;
692 HGraphBuilder* owner_;
693 BreakAndContinueScope* next_;
694 };
695
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000696 HGraphBuilder(CompilationInfo* info, TypeFeedbackOracle* oracle);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000697
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000698 HGraph* CreateGraph();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000699
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000700 // Simple accessors.
701 HGraph* graph() const { return graph_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000702 BreakAndContinueScope* break_scope() const { return break_scope_; }
703 void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000704
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000705 HBasicBlock* current_block() const { return current_block_; }
706 void set_current_block(HBasicBlock* block) { current_block_ = block; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000707 HEnvironment* environment() const {
708 return current_block()->last_environment();
709 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000710
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000711 bool inline_bailout() { return inline_bailout_; }
712
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000713 // Adding instructions.
714 HInstruction* AddInstruction(HInstruction* instr);
ager@chromium.org04921a82011-06-27 13:21:41 +0000715 void AddSimulate(int ast_id);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000716
717 // Bailout environment manipulation.
718 void Push(HValue* value) { environment()->Push(value); }
719 HValue* Pop() { return environment()->Pop(); }
720
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000721 void Bailout(const char* reason);
722
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000723 HBasicBlock* CreateJoin(HBasicBlock* first,
724 HBasicBlock* second,
725 int join_id);
726
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000727 TypeFeedbackOracle* oracle() const { return function_state()->oracle(); }
728
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000729 private:
730 // Type of a member function that generates inline code for a native function.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000731 typedef void (HGraphBuilder::*InlineFunctionGenerator)(CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000732
733 // Forward declarations for inner scope classes.
734 class SubgraphScope;
735
736 static const InlineFunctionGenerator kInlineFunctionGenerators[];
737
738 static const int kMaxCallPolymorphism = 4;
739 static const int kMaxLoadPolymorphism = 4;
740 static const int kMaxStorePolymorphism = 4;
741
742 static const int kMaxInlinedNodes = 196;
743 static const int kMaxInlinedSize = 196;
744 static const int kMaxSourceSize = 600;
745
746 // Simple accessors.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000747 FunctionState* function_state() const { return function_state_; }
748 void set_function_state(FunctionState* state) { function_state_ = state; }
749
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000750 AstContext* ast_context() const { return ast_context_; }
751 void set_ast_context(AstContext* context) { ast_context_ = context; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000752
753 // Accessors forwarded to the function state.
754 CompilationInfo* info() const {
755 return function_state()->compilation_info();
756 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000757
758 AstContext* call_context() const {
759 return function_state()->call_context();
760 }
761 HBasicBlock* function_return() const {
762 return function_state()->function_return();
763 }
764 TestContext* inlined_test_context() const {
765 return function_state()->test_context();
766 }
767 void ClearInlinedTestContext() {
768 function_state()->ClearInlinedTestContext();
769 }
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000770 bool function_strict_mode() {
771 return function_state()->compilation_info()->is_strict_mode();
772 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000773
774 // Generators for inline runtime functions.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000775#define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000776 void Generate##Name(CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000777
778 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
779 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
780#undef INLINE_FUNCTION_GENERATOR_DECLARATION
781
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000782 void VisitDelete(UnaryOperation* expr);
783 void VisitVoid(UnaryOperation* expr);
784 void VisitTypeof(UnaryOperation* expr);
785 void VisitAdd(UnaryOperation* expr);
786 void VisitSub(UnaryOperation* expr);
787 void VisitBitNot(UnaryOperation* expr);
788 void VisitNot(UnaryOperation* expr);
789
790 void VisitComma(BinaryOperation* expr);
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000791 void VisitLogicalExpression(BinaryOperation* expr);
792 void VisitArithmeticExpression(BinaryOperation* expr);
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000793
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000794 void PreProcessOsrEntry(IterationStatement* statement);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000795 // True iff. we are compiling for OSR and the statement is the entry.
796 bool HasOsrEntryAt(IterationStatement* statement);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000797 void VisitLoopBody(IterationStatement* stmt,
ager@chromium.org04921a82011-06-27 13:21:41 +0000798 HBasicBlock* loop_entry,
799 BreakAndContinueInfo* break_info);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000800
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000801 // Create a back edge in the flow graph. body_exit is the predecessor
802 // block and loop_entry is the successor block. loop_successor is the
803 // block where control flow exits the loop normally (e.g., via failure of
804 // the condition) and break_block is the block where control flow breaks
805 // from the loop. All blocks except loop_entry can be NULL. The return
806 // value is the new successor block which is the join of loop_successor
807 // and break_block, or NULL.
808 HBasicBlock* CreateLoop(IterationStatement* statement,
809 HBasicBlock* loop_entry,
810 HBasicBlock* body_exit,
811 HBasicBlock* loop_successor,
812 HBasicBlock* break_block);
813
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000814 HBasicBlock* JoinContinue(IterationStatement* statement,
815 HBasicBlock* exit_block,
816 HBasicBlock* continue_block);
817
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000818 HValue* Top() const { return environment()->Top(); }
819 void Drop(int n) { environment()->Drop(n); }
820 void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
821
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000822 // The value of the arguments object is allowed in some but not most value
823 // contexts. (It's allowed in all effect contexts and disallowed in all
824 // test contexts.)
825 void VisitForValue(Expression* expr,
826 ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000827 void VisitForTypeOf(Expression* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000828 void VisitForEffect(Expression* expr);
829 void VisitForControl(Expression* expr,
830 HBasicBlock* true_block,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000831 HBasicBlock* false_block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000832
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000833 // Visit an argument subexpression and emit a push to the outgoing
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000834 // arguments. Returns the hydrogen value that was pushed.
835 HValue* VisitArgument(Expression* expr);
836
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000837 void VisitArgumentList(ZoneList<Expression*>* arguments);
838
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000839 // Visit a list of expressions from left to right, each in a value context.
840 void VisitExpressions(ZoneList<Expression*>* exprs);
841
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000842 void AddPhi(HPhi* phi);
843
844 void PushAndAdd(HInstruction* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000845
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000846 // Remove the arguments from the bailout environment and emit instructions
847 // to push them as outgoing parameters.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000848 template <int V> HInstruction* PreProcessCall(HCall<V>* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000849
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000850 void TraceRepresentation(Token::Value op,
851 TypeInfo info,
852 HValue* value,
853 Representation rep);
854 void AssumeRepresentation(HValue* value, Representation rep);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000855 static Representation ToRepresentation(TypeInfo info);
856
857 void SetupScope(Scope* scope);
858 virtual void VisitStatements(ZoneList<Statement*>* statements);
859
860#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
861 AST_NODE_LIST(DECLARE_VISIT)
862#undef DECLARE_VISIT
863
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000864 HBasicBlock* CreateBasicBlock(HEnvironment* env);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000865 HBasicBlock* CreateLoopHeaderBlock();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000866
867 // Helpers for flow graph construction.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000868 enum GlobalPropertyAccess {
869 kUseCell,
870 kUseGeneric
871 };
872 GlobalPropertyAccess LookupGlobalProperty(Variable* var,
873 LookupResult* lookup,
874 bool is_store);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000875
876 bool TryArgumentsAccess(Property* expr);
877 bool TryCallApply(Call* expr);
878 bool TryInline(Call* expr);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000879 bool TryInlineBuiltinFunction(Call* expr,
880 HValue* receiver,
881 Handle<Map> receiver_map,
882 CheckType check_type);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000883
884 // If --trace-inlining, print a line of the inlining trace. Inlining
885 // succeeded if the reason string is NULL and failed if there is a
886 // non-NULL reason string.
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000887 void TraceInline(Handle<JSFunction> target,
888 Handle<JSFunction> caller,
889 const char* failure_reason);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000890
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000891 void HandleGlobalVariableAssignment(Variable* var,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000892 HValue* value,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000893 int position,
894 int ast_id);
895
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000896 void HandlePropertyAssignment(Assignment* expr);
897 void HandleCompoundAssignment(Assignment* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000898 void HandlePolymorphicStoreNamedField(Assignment* expr,
899 HValue* object,
900 HValue* value,
901 ZoneMapList* types,
902 Handle<String> name);
903 void HandlePolymorphicCallNamed(Call* expr,
904 HValue* receiver,
905 ZoneMapList* types,
906 Handle<String> name);
ager@chromium.org04921a82011-06-27 13:21:41 +0000907 void HandleLiteralCompareTypeof(CompareOperation* compare_expr,
908 Expression* expr,
909 Handle<String> check);
910 void HandleLiteralCompareUndefined(CompareOperation* compare_expr,
911 Expression* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000912
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000913 HStringCharCodeAt* BuildStringCharCodeAt(HValue* context,
914 HValue* string,
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000915 HValue* index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000916 HInstruction* BuildBinaryOperation(BinaryOperation* expr,
917 HValue* left,
918 HValue* right);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000919 HInstruction* BuildIncrement(bool returns_original_input,
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000920 CountOperation* expr);
whesse@chromium.org023421e2010-12-21 12:19:12 +0000921 HLoadNamedField* BuildLoadNamedField(HValue* object,
922 Property* expr,
923 Handle<Map> type,
924 LookupResult* result,
925 bool smi_and_map_check);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000926 HInstruction* BuildLoadNamedGeneric(HValue* object, Property* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000927 HInstruction* BuildLoadKeyedGeneric(HValue* object,
928 HValue* key);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000929 HInstruction* BuildExternalArrayElementAccess(
930 HValue* external_elements,
931 HValue* checked_key,
932 HValue* val,
933 JSObject::ElementsKind elements_kind,
934 bool is_store);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000935
whesse@chromium.org7b260152011-06-20 15:33:18 +0000936 HInstruction* BuildMonomorphicElementAccess(HValue* object,
937 HValue* key,
938 HValue* val,
939 Expression* expr,
940 bool is_store);
941 HValue* HandlePolymorphicElementAccess(HValue* object,
942 HValue* key,
943 HValue* val,
944 Expression* prop,
945 int ast_id,
946 int position,
947 bool is_store,
948 bool* has_side_effects);
949
950 HValue* HandleKeyedElementAccess(HValue* obj,
951 HValue* key,
952 HValue* val,
953 Expression* expr,
954 int ast_id,
955 int position,
956 bool is_store,
957 bool* has_side_effects);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000958
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000959 HInstruction* BuildLoadNamed(HValue* object,
960 Property* prop,
961 Handle<Map> map,
962 Handle<String> name);
963 HInstruction* BuildStoreNamed(HValue* object,
964 HValue* value,
965 Expression* expr);
966 HInstruction* BuildStoreNamedField(HValue* object,
967 Handle<String> name,
968 HValue* value,
969 Handle<Map> type,
970 LookupResult* lookup,
971 bool smi_and_map_check);
972 HInstruction* BuildStoreNamedGeneric(HValue* object,
973 Handle<String> name,
974 HValue* value);
975 HInstruction* BuildStoreKeyedGeneric(HValue* object,
976 HValue* key,
977 HValue* value);
978
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000979 HValue* BuildContextChainWalk(Variable* var);
980
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000981 void AddCheckConstantFunction(Call* expr,
982 HValue* receiver,
983 Handle<Map> receiver_map,
984 bool smi_and_map_check);
985
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000986 Zone* zone() { return zone_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000987
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000988 // The translation state of the currently-being-translated function.
989 FunctionState* function_state_;
990
991 // The base of the function state stack.
992 FunctionState initial_function_state_;
993
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000994 // Expression context of the currently visited subexpression. NULL when
995 // visiting statements.
996 AstContext* ast_context_;
997
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000998 // A stack of breakable statements entered.
999 BreakAndContinueScope* break_scope_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001000
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001001 HGraph* graph_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001002 HBasicBlock* current_block_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001003
1004 int inlined_count_;
1005
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001006 Zone* zone_;
1007
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001008 bool inline_bailout_;
1009
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001010 friend class FunctionState; // Pushes and pops the state stack.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001011 friend class AstContext; // Pushes and pops the AST context stack.
1012
1013 DISALLOW_COPY_AND_ASSIGN(HGraphBuilder);
1014};
1015
1016
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001017Zone* AstContext::zone() { return owner_->zone(); }
1018
1019
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001020class HValueMap: public ZoneObject {
1021 public:
1022 HValueMap()
1023 : array_size_(0),
1024 lists_size_(0),
1025 count_(0),
1026 present_flags_(0),
1027 array_(NULL),
1028 lists_(NULL),
1029 free_list_head_(kNil) {
1030 ResizeLists(kInitialSize);
1031 Resize(kInitialSize);
1032 }
1033
1034 void Kill(int flags);
1035
1036 void Add(HValue* value) {
1037 present_flags_ |= value->flags();
1038 Insert(value);
1039 }
1040
1041 HValue* Lookup(HValue* value) const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001042
1043 HValueMap* Copy(Zone* zone) const {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001044 return new(zone) HValueMap(zone, this);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001045 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001046
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001047 bool IsEmpty() const { return count_ == 0; }
1048
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001049 private:
1050 // A linked list of HValue* values. Stored in arrays.
1051 struct HValueMapListElement {
1052 HValue* value;
1053 int next; // Index in the array of the next list element.
1054 };
1055 static const int kNil = -1; // The end of a linked list
1056
1057 // Must be a power of 2.
1058 static const int kInitialSize = 16;
1059
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001060 HValueMap(Zone* zone, const HValueMap* other);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001061
1062 void Resize(int new_size);
1063 void ResizeLists(int new_size);
1064 void Insert(HValue* value);
1065 uint32_t Bound(uint32_t value) const { return value & (array_size_ - 1); }
1066
1067 int array_size_;
1068 int lists_size_;
1069 int count_; // The number of values stored in the HValueMap.
1070 int present_flags_; // All flags that are in any value in the HValueMap.
1071 HValueMapListElement* array_; // Primary store - contains the first value
1072 // with a given hash. Colliding elements are stored in linked lists.
1073 HValueMapListElement* lists_; // The linked lists containing hash collisions.
1074 int free_list_head_; // Unused elements in lists_ are on the free list.
1075};
1076
1077
1078class HStatistics: public Malloced {
1079 public:
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001080 void Initialize(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001081 void Print();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001082 void SaveTiming(const char* name, int64_t ticks, unsigned size);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001083 static HStatistics* Instance() {
1084 static SetOncePointer<HStatistics> instance;
1085 if (!instance.is_set()) {
1086 instance.set(new HStatistics());
1087 }
1088 return instance.get();
1089 }
1090
1091 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001092 HStatistics()
1093 : timing_(5),
1094 names_(5),
1095 sizes_(5),
1096 total_(0),
1097 total_size_(0),
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001098 full_code_gen_(0),
1099 source_size_(0) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001100
1101 List<int64_t> timing_;
1102 List<const char*> names_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001103 List<unsigned> sizes_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001104 int64_t total_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001105 unsigned total_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001106 int64_t full_code_gen_;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001107 double source_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001108};
1109
1110
1111class HPhase BASE_EMBEDDED {
1112 public:
1113 static const char* const kFullCodeGen;
1114 static const char* const kTotal;
1115
1116 explicit HPhase(const char* name) { Begin(name, NULL, NULL, NULL); }
1117 HPhase(const char* name, HGraph* graph) {
1118 Begin(name, graph, NULL, NULL);
1119 }
1120 HPhase(const char* name, LChunk* chunk) {
1121 Begin(name, NULL, chunk, NULL);
1122 }
1123 HPhase(const char* name, LAllocator* allocator) {
1124 Begin(name, NULL, NULL, allocator);
1125 }
1126
1127 ~HPhase() {
1128 End();
1129 }
1130
1131 private:
1132 void Begin(const char* name,
1133 HGraph* graph,
1134 LChunk* chunk,
1135 LAllocator* allocator);
1136 void End() const;
1137
1138 int64_t start_;
1139 const char* name_;
1140 HGraph* graph_;
1141 LChunk* chunk_;
1142 LAllocator* allocator_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001143 unsigned start_allocation_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001144};
1145
1146
1147class HTracer: public Malloced {
1148 public:
1149 void TraceCompilation(FunctionLiteral* function);
1150 void TraceHydrogen(const char* name, HGraph* graph);
1151 void TraceLithium(const char* name, LChunk* chunk);
1152 void TraceLiveRanges(const char* name, LAllocator* allocator);
1153
1154 static HTracer* Instance() {
1155 static SetOncePointer<HTracer> instance;
1156 if (!instance.is_set()) {
1157 instance.set(new HTracer("hydrogen.cfg"));
1158 }
1159 return instance.get();
1160 }
1161
1162 private:
1163 class Tag BASE_EMBEDDED {
1164 public:
1165 Tag(HTracer* tracer, const char* name) {
1166 name_ = name;
1167 tracer_ = tracer;
1168 tracer->PrintIndent();
1169 tracer->trace_.Add("begin_%s\n", name);
1170 tracer->indent_++;
1171 }
1172
1173 ~Tag() {
1174 tracer_->indent_--;
1175 tracer_->PrintIndent();
1176 tracer_->trace_.Add("end_%s\n", name_);
1177 ASSERT(tracer_->indent_ >= 0);
1178 tracer_->FlushToFile();
1179 }
1180
1181 private:
1182 HTracer* tracer_;
1183 const char* name_;
1184 };
1185
1186 explicit HTracer(const char* filename)
1187 : filename_(filename), trace_(&string_allocator_), indent_(0) {
1188 WriteChars(filename, "", 0, false);
1189 }
1190
1191 void TraceLiveRange(LiveRange* range, const char* type);
1192 void Trace(const char* name, HGraph* graph, LChunk* chunk);
1193 void FlushToFile();
1194
1195 void PrintEmptyProperty(const char* name) {
1196 PrintIndent();
1197 trace_.Add("%s\n", name);
1198 }
1199
1200 void PrintStringProperty(const char* name, const char* value) {
1201 PrintIndent();
1202 trace_.Add("%s \"%s\"\n", name, value);
1203 }
1204
1205 void PrintLongProperty(const char* name, int64_t value) {
1206 PrintIndent();
1207 trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
1208 }
1209
1210 void PrintBlockProperty(const char* name, int block_id) {
1211 PrintIndent();
1212 trace_.Add("%s \"B%d\"\n", name, block_id);
1213 }
1214
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001215 void PrintIntProperty(const char* name, int value) {
1216 PrintIndent();
1217 trace_.Add("%s %d\n", name, value);
1218 }
1219
1220 void PrintIndent() {
1221 for (int i = 0; i < indent_; i++) {
1222 trace_.Add(" ");
1223 }
1224 }
1225
1226 const char* filename_;
1227 HeapStringAllocator string_allocator_;
1228 StringStream trace_;
1229 int indent_;
1230};
1231
1232
1233} } // namespace v8::internal
1234
1235#endif // V8_HYDROGEN_H_