blob: 366364f61727631d7cf771293820594b42f21225 [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
119 void SetJoinId(int id);
120
121 void Finish(HControlInstruction* last);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000122 void FinishExit(HControlInstruction* instruction);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000123 void Goto(HBasicBlock* block, bool include_stack_check = false);
124
125 int PredecessorIndexOf(HBasicBlock* predecessor) const;
126 void AddSimulate(int id) { AddInstruction(CreateSimulate(id)); }
127 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
159 HSimulate* CreateSimulate(int 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)
188 : back_edges_(4), loop_header_(loop_header), blocks_(8) {
189 blocks_.Add(loop_header);
190 }
191 virtual ~HLoopInformation() {}
192
193 const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; }
194 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
195 HBasicBlock* loop_header() const { return loop_header_; }
196 HBasicBlock* GetLastBackEdge() const;
197 void RegisterBackEdge(HBasicBlock* block);
198
199 private:
200 void AddBlock(HBasicBlock* block);
201
202 ZoneList<HBasicBlock*> back_edges_;
203 HBasicBlock* loop_header_;
204 ZoneList<HBasicBlock*> blocks_;
205};
206
207
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000208class HGraph: public ZoneObject {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000209 public:
210 explicit HGraph(CompilationInfo* info);
211
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000212 Isolate* isolate() { return isolate_; }
213 Zone* zone() { return isolate_->zone(); }
214
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000215 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
216 const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000217 HBasicBlock* entry_block() const { return entry_block_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000218 HEnvironment* start_environment() const { return start_environment_; }
219
220 void InitializeInferredTypes();
221 void InsertTypeConversions();
222 void InsertRepresentationChanges();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000223 void MarkDeoptimizeOnUndefined();
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000224 void ComputeMinusZeroChecks();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000225 bool ProcessArgumentsObject();
226 void EliminateRedundantPhis();
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000227 void EliminateUnreachablePhis();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000228 void Canonicalize();
229 void OrderBlocks();
230 void AssignDominators();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000231 void ReplaceCheckedValues();
232 void MarkAsDeoptimizingRecursively(HBasicBlock* block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000233
234 // Returns false if there are phi-uses of the arguments-object
235 // which are not supported by the optimizing compiler.
236 bool CollectPhis();
237
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000238 Handle<Code> Compile(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000239
240 void set_undefined_constant(HConstant* constant) {
241 undefined_constant_.set(constant);
242 }
243 HConstant* GetConstantUndefined() const { return undefined_constant_.get(); }
244 HConstant* GetConstant1();
245 HConstant* GetConstantMinus1();
246 HConstant* GetConstantTrue();
247 HConstant* GetConstantFalse();
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000248 HConstant* GetConstantHole();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000249
250 HBasicBlock* CreateBasicBlock();
251 HArgumentsObject* GetArgumentsObject() const {
252 return arguments_object_.get();
253 }
254 bool HasArgumentsObject() const { return arguments_object_.is_set(); }
255
256 void SetArgumentsObject(HArgumentsObject* object) {
257 arguments_object_.set(object);
258 }
259
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000260 int GetMaximumValueID() const { return values_.length(); }
261 int GetNextBlockID() { return next_block_id_++; }
262 int GetNextValueID(HValue* value) {
263 values_.Add(value);
264 return values_.length() - 1;
265 }
266 HValue* LookupValue(int id) const {
267 if (id >= 0 && id < values_.length()) return values_[id];
268 return NULL;
269 }
270
271#ifdef DEBUG
272 void Verify() const;
273#endif
274
275 private:
276 void Postorder(HBasicBlock* block,
277 BitVector* visited,
278 ZoneList<HBasicBlock*>* order,
279 HBasicBlock* loop_header);
280 void PostorderLoopBlocks(HLoopInformation* loop,
281 BitVector* visited,
282 ZoneList<HBasicBlock*>* order,
283 HBasicBlock* loop_header);
284 HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
285 Object* value);
286
287 void InsertTypeConversions(HInstruction* instr);
288 void PropagateMinusZeroChecks(HValue* value, BitVector* visited);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000289 void RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000290 void InsertRepresentationChangeForUse(HValue* value,
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000291 HValue* use_value,
292 int use_index,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000293 Representation to);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000294 void InsertRepresentationChangesForValue(HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000295 void InferTypes(ZoneList<HValue*>* worklist);
296 void InitializeInferredTypes(int from_inclusive, int to_inclusive);
297 void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor);
298
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000299 Isolate* isolate_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000300 int next_block_id_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000301 HBasicBlock* entry_block_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000302 HEnvironment* start_environment_;
303 ZoneList<HBasicBlock*> blocks_;
304 ZoneList<HValue*> values_;
305 ZoneList<HPhi*>* phi_list_;
306 SetOncePointer<HConstant> undefined_constant_;
307 SetOncePointer<HConstant> constant_1_;
308 SetOncePointer<HConstant> constant_minus1_;
309 SetOncePointer<HConstant> constant_true_;
310 SetOncePointer<HConstant> constant_false_;
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000311 SetOncePointer<HConstant> constant_hole_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000312 SetOncePointer<HArgumentsObject> arguments_object_;
313
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000314 DISALLOW_COPY_AND_ASSIGN(HGraph);
315};
316
317
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000318Zone* HBasicBlock::zone() { return graph_->zone(); }
319
320
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000321class HEnvironment: public ZoneObject {
322 public:
lrn@chromium.org1c092762011-05-09 09:42:16 +0000323 enum CompilationPhase { HYDROGEN, LITHIUM };
324
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000325 HEnvironment(HEnvironment* outer,
326 Scope* scope,
327 Handle<JSFunction> closure);
328
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000329 // Simple accessors.
330 Handle<JSFunction> closure() const { return closure_; }
331 const ZoneList<HValue*>* values() const { return &values_; }
332 const ZoneList<int>* assigned_variables() const {
333 return &assigned_variables_;
334 }
335 int parameter_count() const { return parameter_count_; }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000336 int specials_count() const { return specials_count_; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000337 int local_count() const { return local_count_; }
338 HEnvironment* outer() const { return outer_; }
339 int pop_count() const { return pop_count_; }
340 int push_count() const { return push_count_; }
341
342 int ast_id() const { return ast_id_; }
343 void set_ast_id(int id) { ast_id_ = id; }
344
345 int length() const { return values_.length(); }
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000346 bool is_special_index(int i) const {
347 return i >= parameter_count() && i < parameter_count() + specials_count();
348 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000349
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000350 void Bind(Variable* variable, HValue* value) {
351 Bind(IndexFor(variable), value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000352 }
353
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000354 void Bind(int index, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000355
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000356 void BindContext(HValue* value) {
357 Bind(parameter_count(), value);
358 }
359
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000360 HValue* Lookup(Variable* variable) const {
361 return Lookup(IndexFor(variable));
362 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000363
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000364 HValue* Lookup(int index) const {
365 HValue* result = values_[index];
366 ASSERT(result != NULL);
367 return result;
368 }
369
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000370 HValue* LookupContext() const {
371 // Return first special.
372 return Lookup(parameter_count());
373 }
374
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000375 void Push(HValue* value) {
376 ASSERT(value != NULL);
377 ++push_count_;
378 values_.Add(value);
379 }
380
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000381 HValue* Pop() {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000382 ASSERT(!ExpressionStackIsEmpty());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000383 if (push_count_ > 0) {
384 --push_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000385 } else {
386 ++pop_count_;
387 }
388 return values_.RemoveLast();
389 }
390
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000391 void Drop(int count);
392
393 HValue* Top() const { return ExpressionStackAt(0); }
394
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000395 bool ExpressionStackIsEmpty() const;
396
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000397 HValue* ExpressionStackAt(int index_from_top) const {
398 int index = length() - index_from_top - 1;
399 ASSERT(HasExpressionAt(index));
400 return values_[index];
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000401 }
402
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000403 void SetExpressionStackAt(int index_from_top, HValue* value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000404
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000405 HEnvironment* Copy() const;
406 HEnvironment* CopyWithoutHistory() const;
407 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const;
408
409 // Create an "inlined version" of this environment, where the original
410 // environment is the outer environment but the top expression stack
411 // elements are moved to an inner environment as parameters. If
412 // is_speculative, the argument values are expected to be PushArgument
413 // instructions, otherwise they are the actual values.
414 HEnvironment* CopyForInlining(Handle<JSFunction> target,
415 FunctionLiteral* function,
lrn@chromium.org1c092762011-05-09 09:42:16 +0000416 CompilationPhase compilation_phase,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000417 HConstant* undefined,
418 CallKind call_kind) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000419
420 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000421
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000422 void ClearHistory() {
423 pop_count_ = 0;
424 push_count_ = 0;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000425 assigned_variables_.Rewind(0);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000426 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000427
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000428 void SetValueAt(int index, HValue* value) {
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000429 ASSERT(index < length());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000430 values_[index] = value;
431 }
432
433 void PrintTo(StringStream* stream);
434 void PrintToStd();
435
436 private:
437 explicit HEnvironment(const HEnvironment* other);
438
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000439 // True if index is included in the expression stack part of the environment.
440 bool HasExpressionAt(int index) const;
441
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000442 void Initialize(int parameter_count, int local_count, int stack_height);
443 void Initialize(const HEnvironment* other);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000444
445 // Map a variable to an environment index. Parameter indices are shifted
446 // by 1 (receiver is parameter index -1 but environment index 0).
447 // Stack-allocated local indices are shifted by the number of parameters.
448 int IndexFor(Variable* variable) const {
449 Slot* slot = variable->AsSlot();
450 ASSERT(slot != NULL && slot->IsStackAllocated());
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000451 int shift = (slot->type() == Slot::PARAMETER)
452 ? 1
453 : parameter_count_ + specials_count_;
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000454 return slot->index() + shift;
455 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000456
457 Handle<JSFunction> closure_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000458 // Value array [parameters] [specials] [locals] [temporaries].
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000459 ZoneList<HValue*> values_;
460 ZoneList<int> assigned_variables_;
461 int parameter_count_;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000462 int specials_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000463 int local_count_;
464 HEnvironment* outer_;
465 int pop_count_;
466 int push_count_;
467 int ast_id_;
468};
469
470
471class HGraphBuilder;
472
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000473enum ArgumentsAllowedFlag {
474 ARGUMENTS_NOT_ALLOWED,
475 ARGUMENTS_ALLOWED
476};
477
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000478// This class is not BASE_EMBEDDED because our inlining implementation uses
479// new and delete.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000480class AstContext {
481 public:
482 bool IsEffect() const { return kind_ == Expression::kEffect; }
483 bool IsValue() const { return kind_ == Expression::kValue; }
484 bool IsTest() const { return kind_ == Expression::kTest; }
485
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000486 // 'Fill' this context with a hydrogen value. The value is assumed to
487 // have already been inserted in the instruction stream (or not need to
488 // be, e.g., HPhi). Call this function in tail position in the Visit
489 // functions for expressions.
490 virtual void ReturnValue(HValue* value) = 0;
491
492 // Add a hydrogen instruction to the instruction stream (recording an
493 // environment simulation if necessary) and then fill this context with
494 // the instruction as value.
495 virtual void ReturnInstruction(HInstruction* instr, int ast_id) = 0;
496
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000497 void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; }
498 bool is_for_typeof() { return for_typeof_; }
499
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000500 protected:
501 AstContext(HGraphBuilder* owner, Expression::Context kind);
502 virtual ~AstContext();
503
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000504 HGraphBuilder* owner() const { return owner_; }
505
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000506 inline Zone* zone();
507
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000508 // We want to be able to assert, in a context-specific way, that the stack
509 // height makes sense when the context is filled.
510#ifdef DEBUG
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000511 int original_length_;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000512#endif
513
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000514 private:
515 HGraphBuilder* owner_;
516 Expression::Context kind_;
517 AstContext* outer_;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000518 bool for_typeof_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000519};
520
521
522class EffectContext: public AstContext {
523 public:
524 explicit EffectContext(HGraphBuilder* owner)
525 : AstContext(owner, Expression::kEffect) {
526 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000527 virtual ~EffectContext();
528
529 virtual void ReturnValue(HValue* value);
530 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000531};
532
533
534class ValueContext: public AstContext {
535 public:
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000536 explicit ValueContext(HGraphBuilder* owner, ArgumentsAllowedFlag flag)
537 : AstContext(owner, Expression::kValue), flag_(flag) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000538 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000539 virtual ~ValueContext();
540
541 virtual void ReturnValue(HValue* value);
542 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000543
544 bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
545
546 private:
547 ArgumentsAllowedFlag flag_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000548};
549
550
551class TestContext: public AstContext {
552 public:
553 TestContext(HGraphBuilder* owner,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000554 Expression* condition,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000555 HBasicBlock* if_true,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000556 HBasicBlock* if_false)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000557 : AstContext(owner, Expression::kTest),
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000558 condition_(condition),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000559 if_true_(if_true),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000560 if_false_(if_false) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000561 }
562
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000563 virtual void ReturnValue(HValue* value);
564 virtual void ReturnInstruction(HInstruction* instr, int ast_id);
565
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000566 static TestContext* cast(AstContext* context) {
567 ASSERT(context->IsTest());
568 return reinterpret_cast<TestContext*>(context);
569 }
570
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000571 Expression* condition() const { return condition_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000572 HBasicBlock* if_true() const { return if_true_; }
573 HBasicBlock* if_false() const { return if_false_; }
574
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000575 private:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000576 // Build the shared core part of the translation unpacking a value into
577 // control flow.
578 void BuildBranch(HValue* value);
579
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000580 Expression* condition_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000581 HBasicBlock* if_true_;
582 HBasicBlock* if_false_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000583};
584
585
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000586class FunctionState BASE_EMBEDDED {
587 public:
588 FunctionState(HGraphBuilder* owner,
589 CompilationInfo* info,
590 TypeFeedbackOracle* oracle);
591 ~FunctionState();
592
593 CompilationInfo* compilation_info() { return compilation_info_; }
594 TypeFeedbackOracle* oracle() { return oracle_; }
595 AstContext* call_context() { return call_context_; }
596 HBasicBlock* function_return() { return function_return_; }
597 TestContext* test_context() { return test_context_; }
598 void ClearInlinedTestContext() {
599 delete test_context_;
600 test_context_ = NULL;
601 }
602
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000603 FunctionState* outer() { return outer_; }
604
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000605 private:
606 HGraphBuilder* owner_;
607
608 CompilationInfo* compilation_info_;
609 TypeFeedbackOracle* oracle_;
610
611 // During function inlining, expression context of the call being
612 // inlined. NULL when not inlining.
613 AstContext* call_context_;
614
615 // When inlining in an effect of value context, this is the return block.
616 // It is NULL otherwise. When inlining in a test context, there are a
617 // pair of return blocks in the context. When not inlining, there is no
618 // local return point.
619 HBasicBlock* function_return_;
620
621 // When inlining a call in a test context, a context containing a pair of
622 // return blocks. NULL in all other cases.
623 TestContext* test_context_;
624
625 FunctionState* outer_;
626};
627
628
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000629class HGraphBuilder: public AstVisitor {
630 public:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000631 enum BreakType { BREAK, CONTINUE };
632
633 // A class encapsulating (lazily-allocated) break and continue blocks for
634 // a breakable statement. Separated from BreakAndContinueScope so that it
635 // can have a separate lifetime.
636 class BreakAndContinueInfo BASE_EMBEDDED {
637 public:
638 explicit BreakAndContinueInfo(BreakableStatement* target)
639 : target_(target), break_block_(NULL), continue_block_(NULL) {
640 }
641
642 BreakableStatement* target() { return target_; }
643 HBasicBlock* break_block() { return break_block_; }
644 void set_break_block(HBasicBlock* block) { break_block_ = block; }
645 HBasicBlock* continue_block() { return continue_block_; }
646 void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
647
648 private:
649 BreakableStatement* target_;
650 HBasicBlock* break_block_;
651 HBasicBlock* continue_block_;
652 };
653
654 // A helper class to maintain a stack of current BreakAndContinueInfo
655 // structures mirroring BreakableStatement nesting.
656 class BreakAndContinueScope BASE_EMBEDDED {
657 public:
658 BreakAndContinueScope(BreakAndContinueInfo* info, HGraphBuilder* owner)
659 : info_(info), owner_(owner), next_(owner->break_scope()) {
660 owner->set_break_scope(this);
661 }
662
663 ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
664
665 BreakAndContinueInfo* info() { return info_; }
666 HGraphBuilder* owner() { return owner_; }
667 BreakAndContinueScope* next() { return next_; }
668
669 // Search the break stack for a break or continue target.
670 HBasicBlock* Get(BreakableStatement* stmt, BreakType type);
671
672 private:
673 BreakAndContinueInfo* info_;
674 HGraphBuilder* owner_;
675 BreakAndContinueScope* next_;
676 };
677
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000678 HGraphBuilder(CompilationInfo* info, TypeFeedbackOracle* oracle);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000679
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000680 HGraph* CreateGraph();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000681
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000682 // Simple accessors.
683 HGraph* graph() const { return graph_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000684 BreakAndContinueScope* break_scope() const { return break_scope_; }
685 void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000686
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000687 HBasicBlock* current_block() const { return current_block_; }
688 void set_current_block(HBasicBlock* block) { current_block_ = block; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000689 HEnvironment* environment() const {
690 return current_block()->last_environment();
691 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000692
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000693 bool inline_bailout() { return inline_bailout_; }
694
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000695 // Adding instructions.
696 HInstruction* AddInstruction(HInstruction* instr);
697 void AddSimulate(int id);
698
699 // Bailout environment manipulation.
700 void Push(HValue* value) { environment()->Push(value); }
701 HValue* Pop() { return environment()->Pop(); }
702
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000703 void Bailout(const char* reason);
704
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000705 private:
706 // Type of a member function that generates inline code for a native function.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000707 typedef void (HGraphBuilder::*InlineFunctionGenerator)(CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000708
709 // Forward declarations for inner scope classes.
710 class SubgraphScope;
711
712 static const InlineFunctionGenerator kInlineFunctionGenerators[];
713
714 static const int kMaxCallPolymorphism = 4;
715 static const int kMaxLoadPolymorphism = 4;
716 static const int kMaxStorePolymorphism = 4;
717
718 static const int kMaxInlinedNodes = 196;
719 static const int kMaxInlinedSize = 196;
720 static const int kMaxSourceSize = 600;
721
722 // Simple accessors.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000723 FunctionState* function_state() const { return function_state_; }
724 void set_function_state(FunctionState* state) { function_state_ = state; }
725
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000726 AstContext* ast_context() const { return ast_context_; }
727 void set_ast_context(AstContext* context) { ast_context_ = context; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000728
729 // Accessors forwarded to the function state.
730 CompilationInfo* info() const {
731 return function_state()->compilation_info();
732 }
733 TypeFeedbackOracle* oracle() const { return function_state()->oracle(); }
734
735 AstContext* call_context() const {
736 return function_state()->call_context();
737 }
738 HBasicBlock* function_return() const {
739 return function_state()->function_return();
740 }
741 TestContext* inlined_test_context() const {
742 return function_state()->test_context();
743 }
744 void ClearInlinedTestContext() {
745 function_state()->ClearInlinedTestContext();
746 }
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000747 bool function_strict_mode() {
748 return function_state()->compilation_info()->is_strict_mode();
749 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000750
751 // Generators for inline runtime functions.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000752#define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000753 void Generate##Name(CallRuntime* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000754
755 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
756 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
757#undef INLINE_FUNCTION_GENERATOR_DECLARATION
758
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000759 void VisitDelete(UnaryOperation* expr);
760 void VisitVoid(UnaryOperation* expr);
761 void VisitTypeof(UnaryOperation* expr);
762 void VisitAdd(UnaryOperation* expr);
763 void VisitSub(UnaryOperation* expr);
764 void VisitBitNot(UnaryOperation* expr);
765 void VisitNot(UnaryOperation* expr);
766
767 void VisitComma(BinaryOperation* expr);
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000768 void VisitLogicalExpression(BinaryOperation* expr);
769 void VisitArithmeticExpression(BinaryOperation* expr);
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000770
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000771 void PreProcessOsrEntry(IterationStatement* statement);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000772 // True iff. we are compiling for OSR and the statement is the entry.
773 bool HasOsrEntryAt(IterationStatement* statement);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000774
775 HBasicBlock* CreateJoin(HBasicBlock* first,
776 HBasicBlock* second,
777 int join_id);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000778
779 // Create a back edge in the flow graph. body_exit is the predecessor
780 // block and loop_entry is the successor block. loop_successor is the
781 // block where control flow exits the loop normally (e.g., via failure of
782 // the condition) and break_block is the block where control flow breaks
783 // from the loop. All blocks except loop_entry can be NULL. The return
784 // value is the new successor block which is the join of loop_successor
785 // and break_block, or NULL.
786 HBasicBlock* CreateLoop(IterationStatement* statement,
787 HBasicBlock* loop_entry,
788 HBasicBlock* body_exit,
789 HBasicBlock* loop_successor,
790 HBasicBlock* break_block);
791
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000792 HBasicBlock* JoinContinue(IterationStatement* statement,
793 HBasicBlock* exit_block,
794 HBasicBlock* continue_block);
795
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000796 HValue* Top() const { return environment()->Top(); }
797 void Drop(int n) { environment()->Drop(n); }
798 void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
799
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000800 // The value of the arguments object is allowed in some but not most value
801 // contexts. (It's allowed in all effect contexts and disallowed in all
802 // test contexts.)
803 void VisitForValue(Expression* expr,
804 ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000805 void VisitForTypeOf(Expression* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000806 void VisitForEffect(Expression* expr);
807 void VisitForControl(Expression* expr,
808 HBasicBlock* true_block,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000809 HBasicBlock* false_block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000810
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000811 // Visit an argument subexpression and emit a push to the outgoing
812 // arguments.
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000813 void VisitArgument(Expression* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000814 void VisitArgumentList(ZoneList<Expression*>* arguments);
815
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000816 // Visit a list of expressions from left to right, each in a value context.
817 void VisitExpressions(ZoneList<Expression*>* exprs);
818
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000819 void AddPhi(HPhi* phi);
820
821 void PushAndAdd(HInstruction* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000822
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000823 // Remove the arguments from the bailout environment and emit instructions
824 // to push them as outgoing parameters.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000825 template <int V> HInstruction* PreProcessCall(HCall<V>* call);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000826
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000827 void TraceRepresentation(Token::Value op,
828 TypeInfo info,
829 HValue* value,
830 Representation rep);
831 void AssumeRepresentation(HValue* value, Representation rep);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000832 static Representation ToRepresentation(TypeInfo info);
833
834 void SetupScope(Scope* scope);
835 virtual void VisitStatements(ZoneList<Statement*>* statements);
836
837#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
838 AST_NODE_LIST(DECLARE_VISIT)
839#undef DECLARE_VISIT
840
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000841 HBasicBlock* CreateBasicBlock(HEnvironment* env);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000842 HBasicBlock* CreateLoopHeaderBlock();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000843
844 // Helpers for flow graph construction.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000845 enum GlobalPropertyAccess {
846 kUseCell,
847 kUseGeneric
848 };
849 GlobalPropertyAccess LookupGlobalProperty(Variable* var,
850 LookupResult* lookup,
851 bool is_store);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000852
853 bool TryArgumentsAccess(Property* expr);
854 bool TryCallApply(Call* expr);
855 bool TryInline(Call* expr);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000856 bool TryInlineBuiltinFunction(Call* expr,
857 HValue* receiver,
858 Handle<Map> receiver_map,
859 CheckType check_type);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000860
861 // If --trace-inlining, print a line of the inlining trace. Inlining
862 // succeeded if the reason string is NULL and failed if there is a
863 // non-NULL reason string.
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000864 void TraceInline(Handle<JSFunction> target,
865 Handle<JSFunction> caller,
866 const char* failure_reason);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000867
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000868 void HandleGlobalVariableAssignment(Variable* var,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000869 HValue* value,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000870 int position,
871 int ast_id);
872
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000873 void HandlePropertyAssignment(Assignment* expr);
874 void HandleCompoundAssignment(Assignment* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000875 void HandlePolymorphicStoreNamedField(Assignment* expr,
876 HValue* object,
877 HValue* value,
878 ZoneMapList* types,
879 Handle<String> name);
880 void HandlePolymorphicCallNamed(Call* expr,
881 HValue* receiver,
882 ZoneMapList* types,
883 Handle<String> name);
884
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000885 HCompareSymbolEq* BuildSymbolCompare(HValue* left,
886 HValue* right,
887 Token::Value op);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000888 HStringCharCodeAt* BuildStringCharCodeAt(HValue* string,
889 HValue* index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000890 HInstruction* BuildBinaryOperation(BinaryOperation* expr,
891 HValue* left,
892 HValue* right);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000893 HInstruction* BuildIncrement(bool returns_original_input,
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000894 CountOperation* expr);
whesse@chromium.org023421e2010-12-21 12:19:12 +0000895 HLoadNamedField* BuildLoadNamedField(HValue* object,
896 Property* expr,
897 Handle<Map> type,
898 LookupResult* result,
899 bool smi_and_map_check);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000900 HInstruction* BuildLoadNamedGeneric(HValue* object, Property* expr);
901 HInstruction* BuildLoadKeyedFastElement(HValue* object,
902 HValue* key,
903 Property* expr);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000904 HInstruction* BuildLoadKeyedSpecializedArrayElement(HValue* object,
905 HValue* key,
906 Property* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000907 HInstruction* BuildLoadKeyedGeneric(HValue* object,
908 HValue* key);
909
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000910 HInstruction* BuildLoadKeyed(HValue* obj,
911 HValue* key,
912 Property* prop);
913
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000914 HInstruction* BuildLoadNamed(HValue* object,
915 Property* prop,
916 Handle<Map> map,
917 Handle<String> name);
918 HInstruction* BuildStoreNamed(HValue* object,
919 HValue* value,
920 Expression* expr);
921 HInstruction* BuildStoreNamedField(HValue* object,
922 Handle<String> name,
923 HValue* value,
924 Handle<Map> type,
925 LookupResult* lookup,
926 bool smi_and_map_check);
927 HInstruction* BuildStoreNamedGeneric(HValue* object,
928 Handle<String> name,
929 HValue* value);
930 HInstruction* BuildStoreKeyedGeneric(HValue* object,
931 HValue* key,
932 HValue* value);
933
934 HInstruction* BuildStoreKeyedFastElement(HValue* object,
935 HValue* key,
936 HValue* val,
937 Expression* expr);
938
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000939 HInstruction* BuildStoreKeyedSpecializedArrayElement(
940 HValue* object,
941 HValue* key,
942 HValue* val,
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000943 Expression* expr);
944
945 HInstruction* BuildStoreKeyed(HValue* object,
946 HValue* key,
947 HValue* value,
948 Expression* assignment);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000949
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000950 HValue* BuildContextChainWalk(Variable* var);
951
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000952 void AddCheckConstantFunction(Call* expr,
953 HValue* receiver,
954 Handle<Map> receiver_map,
955 bool smi_and_map_check);
956
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000957 Zone* zone() { return zone_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000958
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000959 // The translation state of the currently-being-translated function.
960 FunctionState* function_state_;
961
962 // The base of the function state stack.
963 FunctionState initial_function_state_;
964
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000965 // Expression context of the currently visited subexpression. NULL when
966 // visiting statements.
967 AstContext* ast_context_;
968
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000969 // A stack of breakable statements entered.
970 BreakAndContinueScope* break_scope_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000971
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000972 HGraph* graph_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000973 HBasicBlock* current_block_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000974
975 int inlined_count_;
976
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000977 Zone* zone_;
978
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000979 bool inline_bailout_;
980
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000981 friend class FunctionState; // Pushes and pops the state stack.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000982 friend class AstContext; // Pushes and pops the AST context stack.
983
984 DISALLOW_COPY_AND_ASSIGN(HGraphBuilder);
985};
986
987
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000988Zone* AstContext::zone() { return owner_->zone(); }
989
990
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000991class HValueMap: public ZoneObject {
992 public:
993 HValueMap()
994 : array_size_(0),
995 lists_size_(0),
996 count_(0),
997 present_flags_(0),
998 array_(NULL),
999 lists_(NULL),
1000 free_list_head_(kNil) {
1001 ResizeLists(kInitialSize);
1002 Resize(kInitialSize);
1003 }
1004
1005 void Kill(int flags);
1006
1007 void Add(HValue* value) {
1008 present_flags_ |= value->flags();
1009 Insert(value);
1010 }
1011
1012 HValue* Lookup(HValue* value) const;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001013
1014 HValueMap* Copy(Zone* zone) const {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001015 return new(zone) HValueMap(zone, this);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001016 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001017
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001018 bool IsEmpty() const { return count_ == 0; }
1019
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001020 private:
1021 // A linked list of HValue* values. Stored in arrays.
1022 struct HValueMapListElement {
1023 HValue* value;
1024 int next; // Index in the array of the next list element.
1025 };
1026 static const int kNil = -1; // The end of a linked list
1027
1028 // Must be a power of 2.
1029 static const int kInitialSize = 16;
1030
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001031 HValueMap(Zone* zone, const HValueMap* other);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001032
1033 void Resize(int new_size);
1034 void ResizeLists(int new_size);
1035 void Insert(HValue* value);
1036 uint32_t Bound(uint32_t value) const { return value & (array_size_ - 1); }
1037
1038 int array_size_;
1039 int lists_size_;
1040 int count_; // The number of values stored in the HValueMap.
1041 int present_flags_; // All flags that are in any value in the HValueMap.
1042 HValueMapListElement* array_; // Primary store - contains the first value
1043 // with a given hash. Colliding elements are stored in linked lists.
1044 HValueMapListElement* lists_; // The linked lists containing hash collisions.
1045 int free_list_head_; // Unused elements in lists_ are on the free list.
1046};
1047
1048
1049class HStatistics: public Malloced {
1050 public:
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001051 void Initialize(CompilationInfo* info);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001052 void Print();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001053 void SaveTiming(const char* name, int64_t ticks, unsigned size);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001054 static HStatistics* Instance() {
1055 static SetOncePointer<HStatistics> instance;
1056 if (!instance.is_set()) {
1057 instance.set(new HStatistics());
1058 }
1059 return instance.get();
1060 }
1061
1062 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001063 HStatistics()
1064 : timing_(5),
1065 names_(5),
1066 sizes_(5),
1067 total_(0),
1068 total_size_(0),
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001069 full_code_gen_(0),
1070 source_size_(0) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001071
1072 List<int64_t> timing_;
1073 List<const char*> names_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001074 List<unsigned> sizes_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001075 int64_t total_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001076 unsigned total_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001077 int64_t full_code_gen_;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001078 double source_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001079};
1080
1081
1082class HPhase BASE_EMBEDDED {
1083 public:
1084 static const char* const kFullCodeGen;
1085 static const char* const kTotal;
1086
1087 explicit HPhase(const char* name) { Begin(name, NULL, NULL, NULL); }
1088 HPhase(const char* name, HGraph* graph) {
1089 Begin(name, graph, NULL, NULL);
1090 }
1091 HPhase(const char* name, LChunk* chunk) {
1092 Begin(name, NULL, chunk, NULL);
1093 }
1094 HPhase(const char* name, LAllocator* allocator) {
1095 Begin(name, NULL, NULL, allocator);
1096 }
1097
1098 ~HPhase() {
1099 End();
1100 }
1101
1102 private:
1103 void Begin(const char* name,
1104 HGraph* graph,
1105 LChunk* chunk,
1106 LAllocator* allocator);
1107 void End() const;
1108
1109 int64_t start_;
1110 const char* name_;
1111 HGraph* graph_;
1112 LChunk* chunk_;
1113 LAllocator* allocator_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001114 unsigned start_allocation_size_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001115};
1116
1117
1118class HTracer: public Malloced {
1119 public:
1120 void TraceCompilation(FunctionLiteral* function);
1121 void TraceHydrogen(const char* name, HGraph* graph);
1122 void TraceLithium(const char* name, LChunk* chunk);
1123 void TraceLiveRanges(const char* name, LAllocator* allocator);
1124
1125 static HTracer* Instance() {
1126 static SetOncePointer<HTracer> instance;
1127 if (!instance.is_set()) {
1128 instance.set(new HTracer("hydrogen.cfg"));
1129 }
1130 return instance.get();
1131 }
1132
1133 private:
1134 class Tag BASE_EMBEDDED {
1135 public:
1136 Tag(HTracer* tracer, const char* name) {
1137 name_ = name;
1138 tracer_ = tracer;
1139 tracer->PrintIndent();
1140 tracer->trace_.Add("begin_%s\n", name);
1141 tracer->indent_++;
1142 }
1143
1144 ~Tag() {
1145 tracer_->indent_--;
1146 tracer_->PrintIndent();
1147 tracer_->trace_.Add("end_%s\n", name_);
1148 ASSERT(tracer_->indent_ >= 0);
1149 tracer_->FlushToFile();
1150 }
1151
1152 private:
1153 HTracer* tracer_;
1154 const char* name_;
1155 };
1156
1157 explicit HTracer(const char* filename)
1158 : filename_(filename), trace_(&string_allocator_), indent_(0) {
1159 WriteChars(filename, "", 0, false);
1160 }
1161
1162 void TraceLiveRange(LiveRange* range, const char* type);
1163 void Trace(const char* name, HGraph* graph, LChunk* chunk);
1164 void FlushToFile();
1165
1166 void PrintEmptyProperty(const char* name) {
1167 PrintIndent();
1168 trace_.Add("%s\n", name);
1169 }
1170
1171 void PrintStringProperty(const char* name, const char* value) {
1172 PrintIndent();
1173 trace_.Add("%s \"%s\"\n", name, value);
1174 }
1175
1176 void PrintLongProperty(const char* name, int64_t value) {
1177 PrintIndent();
1178 trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
1179 }
1180
1181 void PrintBlockProperty(const char* name, int block_id) {
1182 PrintIndent();
1183 trace_.Add("%s \"B%d\"\n", name, block_id);
1184 }
1185
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001186 void PrintIntProperty(const char* name, int value) {
1187 PrintIndent();
1188 trace_.Add("%s %d\n", name, value);
1189 }
1190
1191 void PrintIndent() {
1192 for (int i = 0; i < indent_; i++) {
1193 trace_.Add(" ");
1194 }
1195 }
1196
1197 const char* filename_;
1198 HeapStringAllocator string_allocator_;
1199 StringStream trace_;
1200 int indent_;
1201};
1202
1203
1204} } // namespace v8::internal
1205
1206#endif // V8_HYDROGEN_H_