1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // 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
33 #include "accessors.h"
34 #include "allocation.h"
35 #include "ast.h"
36 #include "compiler.h"
37 #include "hydrogen-instructions.h"
38 #include "zone.h"
39 #include "scopes.h"
40
41 namespace v8 {
42 namespace internal {
43
44 // Forward declarations.
45 class BitVector;
46 class FunctionState;
47 class HEnvironment;
48 class HGraph;
49 class HLoopInformation;
50 class HOsrBuilder;
51 class HTracer;
52 class LAllocator;
53 class LChunk;
54 class LiveRange;
55
56
57 class HBasicBlock V8_FINAL : public ZoneObject {
58 public:
59 explicit HBasicBlock(HGraph* graph);
~HBasicBlock()60 ~HBasicBlock() { }
61
62 // Simple accessors.
block_id()63 int block_id() const { return block_id_; }
set_block_id(int id)64 void set_block_id(int id) { block_id_ = id; }
graph()65 HGraph* graph() const { return graph_; }
66 Isolate* isolate() const;
phis()67 const ZoneList<HPhi*>* phis() const { return &phis_; }
first()68 HInstruction* first() const { return first_; }
last()69 HInstruction* last() const { return last_; }
set_last(HInstruction * instr)70 void set_last(HInstruction* instr) { last_ = instr; }
end()71 HControlInstruction* end() const { return end_; }
loop_information()72 HLoopInformation* loop_information() const { return loop_information_; }
current_loop()73 HLoopInformation* current_loop() const {
74 return IsLoopHeader() ? loop_information()
75 : (parent_loop_header() != NULL
76 ? parent_loop_header()->loop_information() : NULL);
77 }
predecessors()78 const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; }
HasPredecessor()79 bool HasPredecessor() const { return predecessors_.length() > 0; }
dominated_blocks()80 const ZoneList<HBasicBlock*>* dominated_blocks() const {
81 return &dominated_blocks_;
82 }
deleted_phis()83 const ZoneList<int>* deleted_phis() const {
84 return &deleted_phis_;
85 }
RecordDeletedPhi(int merge_index)86 void RecordDeletedPhi(int merge_index) {
87 deleted_phis_.Add(merge_index, zone());
88 }
dominator()89 HBasicBlock* dominator() const { return dominator_; }
last_environment()90 HEnvironment* last_environment() const { return last_environment_; }
argument_count()91 int argument_count() const { return argument_count_; }
set_argument_count(int count)92 void set_argument_count(int count) { argument_count_ = count; }
first_instruction_index()93 int first_instruction_index() const { return first_instruction_index_; }
set_first_instruction_index(int index)94 void set_first_instruction_index(int index) {
95 first_instruction_index_ = index;
96 }
last_instruction_index()97 int last_instruction_index() const { return last_instruction_index_; }
set_last_instruction_index(int index)98 void set_last_instruction_index(int index) {
99 last_instruction_index_ = index;
100 }
is_osr_entry()101 bool is_osr_entry() { return is_osr_entry_; }
set_osr_entry()102 void set_osr_entry() { is_osr_entry_ = true; }
103
104 void AttachLoopInformation();
105 void DetachLoopInformation();
IsLoopHeader()106 bool IsLoopHeader() const { return loop_information() != NULL; }
IsStartBlock()107 bool IsStartBlock() const { return block_id() == 0; }
108 void PostProcessLoopHeader(IterationStatement* stmt);
109
IsFinished()110 bool IsFinished() const { return end_ != NULL; }
111 void AddPhi(HPhi* phi);
112 void RemovePhi(HPhi* phi);
113 void AddInstruction(HInstruction* instr, int position);
114 bool Dominates(HBasicBlock* other) const;
115 int LoopNestingDepth() const;
116
117 void SetInitialEnvironment(HEnvironment* env);
ClearEnvironment()118 void ClearEnvironment() {
119 ASSERT(IsFinished());
120 ASSERT(end()->SuccessorCount() == 0);
121 last_environment_ = NULL;
122 }
HasEnvironment()123 bool HasEnvironment() const { return last_environment_ != NULL; }
124 void UpdateEnvironment(HEnvironment* env);
parent_loop_header()125 HBasicBlock* parent_loop_header() const { return parent_loop_header_; }
126
set_parent_loop_header(HBasicBlock * block)127 void set_parent_loop_header(HBasicBlock* block) {
128 ASSERT(parent_loop_header_ == NULL);
129 parent_loop_header_ = block;
130 }
131
HasParentLoopHeader()132 bool HasParentLoopHeader() const { return parent_loop_header_ != NULL; }
133
134 void SetJoinId(BailoutId ast_id);
135
136 int PredecessorIndexOf(HBasicBlock* predecessor) const;
137 HPhi* AddNewPhi(int merged_index);
138 HSimulate* AddNewSimulate(BailoutId ast_id,
139 int position,
140 RemovableSimulate removable = FIXED_SIMULATE) {
141 HSimulate* instr = CreateSimulate(ast_id, removable);
142 AddInstruction(instr, position);
143 return instr;
144 }
145 void AssignCommonDominator(HBasicBlock* other);
146 void AssignLoopSuccessorDominators();
147
148 // If a target block is tagged as an inline function return, all
149 // predecessors should contain the inlined exit sequence:
150 //
151 // LeaveInlined
152 // Simulate (caller's environment)
153 // Goto (target block)
IsInlineReturnTarget()154 bool IsInlineReturnTarget() const { return is_inline_return_target_; }
MarkAsInlineReturnTarget(HBasicBlock * inlined_entry_block)155 void MarkAsInlineReturnTarget(HBasicBlock* inlined_entry_block) {
156 is_inline_return_target_ = true;
157 inlined_entry_block_ = inlined_entry_block;
158 }
inlined_entry_block()159 HBasicBlock* inlined_entry_block() { return inlined_entry_block_; }
160
IsDeoptimizing()161 bool IsDeoptimizing() const {
162 return end() != NULL && end()->IsDeoptimize();
163 }
164
165 void MarkUnreachable();
IsUnreachable()166 bool IsUnreachable() const { return !is_reachable_; }
IsReachable()167 bool IsReachable() const { return is_reachable_; }
168
IsLoopSuccessorDominator()169 bool IsLoopSuccessorDominator() const {
170 return dominates_loop_successors_;
171 }
MarkAsLoopSuccessorDominator()172 void MarkAsLoopSuccessorDominator() {
173 dominates_loop_successors_ = true;
174 }
175
176 inline Zone* zone() const;
177
178 #ifdef DEBUG
179 void Verify();
180 #endif
181
182 protected:
183 friend class HGraphBuilder;
184
185 HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable);
186 void Finish(HControlInstruction* last, int position);
187 void FinishExit(HControlInstruction* instruction, int position);
188 void Goto(HBasicBlock* block,
189 int position,
190 FunctionState* state = NULL,
191 bool add_simulate = true);
GotoNoSimulate(HBasicBlock * block,int position)192 void GotoNoSimulate(HBasicBlock* block, int position) {
193 Goto(block, position, NULL, false);
194 }
195
196 // Add the inlined function exit sequence, adding an HLeaveInlined
197 // instruction and updating the bailout environment.
198 void AddLeaveInlined(HValue* return_value,
199 FunctionState* state,
200 int position);
201
202 private:
203 void RegisterPredecessor(HBasicBlock* pred);
204 void AddDominatedBlock(HBasicBlock* block);
205
206 int block_id_;
207 HGraph* graph_;
208 ZoneList<HPhi*> phis_;
209 HInstruction* first_;
210 HInstruction* last_;
211 HControlInstruction* end_;
212 HLoopInformation* loop_information_;
213 ZoneList<HBasicBlock*> predecessors_;
214 HBasicBlock* dominator_;
215 ZoneList<HBasicBlock*> dominated_blocks_;
216 HEnvironment* last_environment_;
217 // Outgoing parameter count at block exit, set during lithium translation.
218 int argument_count_;
219 // Instruction indices into the lithium code stream.
220 int first_instruction_index_;
221 int last_instruction_index_;
222 ZoneList<int> deleted_phis_;
223 HBasicBlock* parent_loop_header_;
224 // For blocks marked as inline return target: the block with HEnterInlined.
225 HBasicBlock* inlined_entry_block_;
226 bool is_inline_return_target_ : 1;
227 bool is_reachable_ : 1;
228 bool dominates_loop_successors_ : 1;
229 bool is_osr_entry_ : 1;
230 };
231
232
233 class HPredecessorIterator V8_FINAL BASE_EMBEDDED {
234 public:
HPredecessorIterator(HBasicBlock * block)235 explicit HPredecessorIterator(HBasicBlock* block)
236 : predecessor_list_(block->predecessors()), current_(0) { }
237
Done()238 bool Done() { return current_ >= predecessor_list_->length(); }
Current()239 HBasicBlock* Current() { return predecessor_list_->at(current_); }
Advance()240 void Advance() { current_++; }
241
242 private:
243 const ZoneList<HBasicBlock*>* predecessor_list_;
244 int current_;
245 };
246
247
248 class HInstructionIterator V8_FINAL BASE_EMBEDDED {
249 public:
HInstructionIterator(HBasicBlock * block)250 explicit HInstructionIterator(HBasicBlock* block)
251 : instr_(block->first()) {
252 next_ = Done() ? NULL : instr_->next();
253 }
254
Done()255 inline bool Done() const { return instr_ == NULL; }
Current()256 inline HInstruction* Current() { return instr_; }
Advance()257 inline void Advance() {
258 instr_ = next_;
259 next_ = Done() ? NULL : instr_->next();
260 }
261
262 private:
263 HInstruction* instr_;
264 HInstruction* next_;
265 };
266
267
268 class HLoopInformation V8_FINAL : public ZoneObject {
269 public:
HLoopInformation(HBasicBlock * loop_header,Zone * zone)270 HLoopInformation(HBasicBlock* loop_header, Zone* zone)
271 : back_edges_(4, zone),
272 loop_header_(loop_header),
273 blocks_(8, zone),
274 stack_check_(NULL) {
275 blocks_.Add(loop_header, zone);
276 }
~HLoopInformation()277 ~HLoopInformation() {}
278
back_edges()279 const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; }
blocks()280 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
loop_header()281 HBasicBlock* loop_header() const { return loop_header_; }
282 HBasicBlock* GetLastBackEdge() const;
283 void RegisterBackEdge(HBasicBlock* block);
284
stack_check()285 HStackCheck* stack_check() const { return stack_check_; }
set_stack_check(HStackCheck * stack_check)286 void set_stack_check(HStackCheck* stack_check) {
287 stack_check_ = stack_check;
288 }
289
IsNestedInThisLoop(HLoopInformation * other)290 bool IsNestedInThisLoop(HLoopInformation* other) {
291 while (other != NULL) {
292 if (other == this) {
293 return true;
294 }
295 other = other->parent_loop();
296 }
297 return false;
298 }
parent_loop()299 HLoopInformation* parent_loop() {
300 HBasicBlock* parent_header = loop_header()->parent_loop_header();
301 return parent_header != NULL ? parent_header->loop_information() : NULL;
302 }
303
304 private:
305 void AddBlock(HBasicBlock* block);
306
307 ZoneList<HBasicBlock*> back_edges_;
308 HBasicBlock* loop_header_;
309 ZoneList<HBasicBlock*> blocks_;
310 HStackCheck* stack_check_;
311 };
312
313
314 class BoundsCheckTable;
315 class InductionVariableBlocksTable;
316 class HGraph V8_FINAL : public ZoneObject {
317 public:
318 explicit HGraph(CompilationInfo* info);
319
isolate()320 Isolate* isolate() const { return isolate_; }
zone()321 Zone* zone() const { return zone_; }
info()322 CompilationInfo* info() const { return info_; }
323
blocks()324 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
phi_list()325 const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
entry_block()326 HBasicBlock* entry_block() const { return entry_block_; }
start_environment()327 HEnvironment* start_environment() const { return start_environment_; }
328
329 void FinalizeUniqueness();
330 bool ProcessArgumentsObject();
331 void OrderBlocks();
332 void AssignDominators();
333 void RestoreActualValues();
334
335 // Returns false if there are phi-uses of the arguments-object
336 // which are not supported by the optimizing compiler.
337 bool CheckArgumentsPhiUses();
338
339 // Returns false if there are phi-uses of an uninitialized const
340 // which are not supported by the optimizing compiler.
341 bool CheckConstPhiUses();
342
343 void CollectPhis();
344
345 HConstant* GetConstantUndefined();
346 HConstant* GetConstant0();
347 HConstant* GetConstant1();
348 HConstant* GetConstantMinus1();
349 HConstant* GetConstantTrue();
350 HConstant* GetConstantFalse();
351 HConstant* GetConstantHole();
352 HConstant* GetConstantNull();
353 HConstant* GetInvalidContext();
354
355 bool IsConstantUndefined(HConstant* constant);
356 bool IsConstant0(HConstant* constant);
357 bool IsConstant1(HConstant* constant);
358 bool IsConstantMinus1(HConstant* constant);
359 bool IsConstantTrue(HConstant* constant);
360 bool IsConstantFalse(HConstant* constant);
361 bool IsConstantHole(HConstant* constant);
362 bool IsConstantNull(HConstant* constant);
363 bool IsStandardConstant(HConstant* constant);
364
365 HBasicBlock* CreateBasicBlock();
GetArgumentsObject()366 HArgumentsObject* GetArgumentsObject() const {
367 return arguments_object_.get();
368 }
369
SetArgumentsObject(HArgumentsObject * object)370 void SetArgumentsObject(HArgumentsObject* object) {
371 arguments_object_.set(object);
372 }
373
GetMaximumValueID()374 int GetMaximumValueID() const { return values_.length(); }
GetNextBlockID()375 int GetNextBlockID() { return next_block_id_++; }
GetNextValueID(HValue * value)376 int GetNextValueID(HValue* value) {
377 ASSERT(!disallow_adding_new_values_);
378 values_.Add(value, zone());
379 return values_.length() - 1;
380 }
LookupValue(int id)381 HValue* LookupValue(int id) const {
382 if (id >= 0 && id < values_.length()) return values_[id];
383 return NULL;
384 }
DisallowAddingNewValues()385 void DisallowAddingNewValues() {
386 disallow_adding_new_values_ = true;
387 }
388
389 bool Optimize(BailoutReason* bailout_reason);
390
391 #ifdef DEBUG
392 void Verify(bool do_full_verify) const;
393 #endif
394
has_osr()395 bool has_osr() {
396 return osr_ != NULL;
397 }
398
set_osr(HOsrBuilder * osr)399 void set_osr(HOsrBuilder* osr) {
400 osr_ = osr;
401 }
402
osr()403 HOsrBuilder* osr() {
404 return osr_;
405 }
406
update_type_change_checksum(int delta)407 int update_type_change_checksum(int delta) {
408 type_change_checksum_ += delta;
409 return type_change_checksum_;
410 }
411
update_maximum_environment_size(int environment_size)412 void update_maximum_environment_size(int environment_size) {
413 if (environment_size > maximum_environment_size_) {
414 maximum_environment_size_ = environment_size;
415 }
416 }
maximum_environment_size()417 int maximum_environment_size() { return maximum_environment_size_; }
418
use_optimistic_licm()419 bool use_optimistic_licm() {
420 return use_optimistic_licm_;
421 }
422
set_use_optimistic_licm(bool value)423 void set_use_optimistic_licm(bool value) {
424 use_optimistic_licm_ = value;
425 }
426
MarkRecursive()427 void MarkRecursive() {
428 is_recursive_ = true;
429 }
430
is_recursive()431 bool is_recursive() const {
432 return is_recursive_;
433 }
434
MarkDependsOnEmptyArrayProtoElements()435 void MarkDependsOnEmptyArrayProtoElements() {
436 // Add map dependency if not already added.
437 if (depends_on_empty_array_proto_elements_) return;
438 isolate()->initial_object_prototype()->map()->AddDependentCompilationInfo(
439 DependentCode::kElementsCantBeAddedGroup, info());
440 isolate()->initial_array_prototype()->map()->AddDependentCompilationInfo(
441 DependentCode::kElementsCantBeAddedGroup, info());
442 depends_on_empty_array_proto_elements_ = true;
443 }
444
depends_on_empty_array_proto_elements()445 bool depends_on_empty_array_proto_elements() {
446 return depends_on_empty_array_proto_elements_;
447 }
448
has_uint32_instructions()449 bool has_uint32_instructions() {
450 ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
451 return uint32_instructions_ != NULL;
452 }
453
uint32_instructions()454 ZoneList<HInstruction*>* uint32_instructions() {
455 ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
456 return uint32_instructions_;
457 }
458
RecordUint32Instruction(HInstruction * instr)459 void RecordUint32Instruction(HInstruction* instr) {
460 ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
461 if (uint32_instructions_ == NULL) {
462 uint32_instructions_ = new(zone()) ZoneList<HInstruction*>(4, zone());
463 }
464 uint32_instructions_->Add(instr, zone());
465 }
466
IncrementInNoSideEffectsScope()467 void IncrementInNoSideEffectsScope() { no_side_effects_scope_count_++; }
DecrementInNoSideEffectsScope()468 void DecrementInNoSideEffectsScope() { no_side_effects_scope_count_--; }
IsInsideNoSideEffectsScope()469 bool IsInsideNoSideEffectsScope() { return no_side_effects_scope_count_ > 0; }
470
471 private:
472 HConstant* ReinsertConstantIfNecessary(HConstant* constant);
473 HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
474 int32_t integer_value);
475
476 template<class Phase>
Run()477 void Run() {
478 Phase phase(this);
479 phase.Run();
480 }
481
482 void EliminateRedundantBoundsChecksUsingInductionVariables();
483
484 Isolate* isolate_;
485 int next_block_id_;
486 HBasicBlock* entry_block_;
487 HEnvironment* start_environment_;
488 ZoneList<HBasicBlock*> blocks_;
489 ZoneList<HValue*> values_;
490 ZoneList<HPhi*>* phi_list_;
491 ZoneList<HInstruction*>* uint32_instructions_;
492 SetOncePointer<HConstant> constant_undefined_;
493 SetOncePointer<HConstant> constant_0_;
494 SetOncePointer<HConstant> constant_1_;
495 SetOncePointer<HConstant> constant_minus1_;
496 SetOncePointer<HConstant> constant_true_;
497 SetOncePointer<HConstant> constant_false_;
498 SetOncePointer<HConstant> constant_the_hole_;
499 SetOncePointer<HConstant> constant_null_;
500 SetOncePointer<HConstant> constant_invalid_context_;
501 SetOncePointer<HArgumentsObject> arguments_object_;
502
503 HOsrBuilder* osr_;
504
505 CompilationInfo* info_;
506 Zone* zone_;
507
508 bool is_recursive_;
509 bool use_optimistic_licm_;
510 bool depends_on_empty_array_proto_elements_;
511 int type_change_checksum_;
512 int maximum_environment_size_;
513 int no_side_effects_scope_count_;
514 bool disallow_adding_new_values_;
515
516 DISALLOW_COPY_AND_ASSIGN(HGraph);
517 };
518
519
zone()520 Zone* HBasicBlock::zone() const { return graph_->zone(); }
521
522
523 // Type of stack frame an environment might refer to.
524 enum FrameType {
525 JS_FUNCTION,
526 JS_CONSTRUCT,
527 JS_GETTER,
528 JS_SETTER,
529 ARGUMENTS_ADAPTOR,
530 STUB
531 };
532
533
534 class HEnvironment V8_FINAL : public ZoneObject {
535 public:
536 HEnvironment(HEnvironment* outer,
537 Scope* scope,
538 Handle<JSFunction> closure,
539 Zone* zone);
540
541 HEnvironment(Zone* zone, int parameter_count);
542
arguments_environment()543 HEnvironment* arguments_environment() {
544 return outer()->frame_type() == ARGUMENTS_ADAPTOR ? outer() : this;
545 }
546
547 // Simple accessors.
closure()548 Handle<JSFunction> closure() const { return closure_; }
values()549 const ZoneList<HValue*>* values() const { return &values_; }
assigned_variables()550 const GrowableBitVector* assigned_variables() const {
551 return &assigned_variables_;
552 }
frame_type()553 FrameType frame_type() const { return frame_type_; }
parameter_count()554 int parameter_count() const { return parameter_count_; }
specials_count()555 int specials_count() const { return specials_count_; }
local_count()556 int local_count() const { return local_count_; }
outer()557 HEnvironment* outer() const { return outer_; }
pop_count()558 int pop_count() const { return pop_count_; }
push_count()559 int push_count() const { return push_count_; }
560
ast_id()561 BailoutId ast_id() const { return ast_id_; }
set_ast_id(BailoutId id)562 void set_ast_id(BailoutId id) { ast_id_ = id; }
563
entry()564 HEnterInlined* entry() const { return entry_; }
set_entry(HEnterInlined * entry)565 void set_entry(HEnterInlined* entry) { entry_ = entry; }
566
length()567 int length() const { return values_.length(); }
568
first_expression_index()569 int first_expression_index() const {
570 return parameter_count() + specials_count() + local_count();
571 }
572
first_local_index()573 int first_local_index() const {
574 return parameter_count() + specials_count();
575 }
576
Bind(Variable * variable,HValue * value)577 void Bind(Variable* variable, HValue* value) {
578 Bind(IndexFor(variable), value);
579 }
580
581 void Bind(int index, HValue* value);
582
BindContext(HValue * value)583 void BindContext(HValue* value) {
584 Bind(parameter_count(), value);
585 }
586
Lookup(Variable * variable)587 HValue* Lookup(Variable* variable) const {
588 return Lookup(IndexFor(variable));
589 }
590
Lookup(int index)591 HValue* Lookup(int index) const {
592 HValue* result = values_[index];
593 ASSERT(result != NULL);
594 return result;
595 }
596
context()597 HValue* context() const {
598 // Return first special.
599 return Lookup(parameter_count());
600 }
601
Push(HValue * value)602 void Push(HValue* value) {
603 ASSERT(value != NULL);
604 ++push_count_;
605 values_.Add(value, zone());
606 }
607
Pop()608 HValue* Pop() {
609 ASSERT(!ExpressionStackIsEmpty());
610 if (push_count_ > 0) {
611 --push_count_;
612 } else {
613 ++pop_count_;
614 }
615 return values_.RemoveLast();
616 }
617
618 void Drop(int count);
619
Top()620 HValue* Top() const { return ExpressionStackAt(0); }
621
622 bool ExpressionStackIsEmpty() const;
623
ExpressionStackAt(int index_from_top)624 HValue* ExpressionStackAt(int index_from_top) const {
625 int index = length() - index_from_top - 1;
626 ASSERT(HasExpressionAt(index));
627 return values_[index];
628 }
629
630 void SetExpressionStackAt(int index_from_top, HValue* value);
631
632 HEnvironment* Copy() const;
633 HEnvironment* CopyWithoutHistory() const;
634 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const;
635
636 // Create an "inlined version" of this environment, where the original
637 // environment is the outer environment but the top expression stack
638 // elements are moved to an inner environment as parameters.
639 HEnvironment* CopyForInlining(Handle<JSFunction> target,
640 int arguments,
641 FunctionLiteral* function,
642 HConstant* undefined,
643 InliningKind inlining_kind,
644 bool undefined_receiver) const;
645
UseUndefinedReceiver(Handle<JSFunction> closure,FunctionLiteral * function,CallKind call_kind,InliningKind inlining_kind)646 static bool UseUndefinedReceiver(Handle<JSFunction> closure,
647 FunctionLiteral* function,
648 CallKind call_kind,
649 InliningKind inlining_kind) {
650 return (closure->shared()->native() || !function->is_classic_mode()) &&
651 call_kind == CALL_AS_FUNCTION && inlining_kind != CONSTRUCT_CALL_RETURN;
652 }
653
DiscardInlined(bool drop_extra)654 HEnvironment* DiscardInlined(bool drop_extra) {
655 HEnvironment* outer = outer_;
656 while (outer->frame_type() != JS_FUNCTION) outer = outer->outer_;
657 if (drop_extra) outer->Drop(1);
658 return outer;
659 }
660
661 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
662
ClearHistory()663 void ClearHistory() {
664 pop_count_ = 0;
665 push_count_ = 0;
666 assigned_variables_.Clear();
667 }
668
SetValueAt(int index,HValue * value)669 void SetValueAt(int index, HValue* value) {
670 ASSERT(index < length());
671 values_[index] = value;
672 }
673
674 // Map a variable to an environment index. Parameter indices are shifted
675 // by 1 (receiver is parameter index -1 but environment index 0).
676 // Stack-allocated local indices are shifted by the number of parameters.
IndexFor(Variable * variable)677 int IndexFor(Variable* variable) const {
678 ASSERT(variable->IsStackAllocated());
679 int shift = variable->IsParameter()
680 ? 1
681 : parameter_count_ + specials_count_;
682 return variable->index() + shift;
683 }
684
is_local_index(int i)685 bool is_local_index(int i) const {
686 return i >= first_local_index() && i < first_expression_index();
687 }
688
is_parameter_index(int i)689 bool is_parameter_index(int i) const {
690 return i >= 0 && i < parameter_count();
691 }
692
is_special_index(int i)693 bool is_special_index(int i) const {
694 return i >= parameter_count() && i < parameter_count() + specials_count();
695 }
696
697 void PrintTo(StringStream* stream);
698 void PrintToStd();
699
zone()700 Zone* zone() const { return zone_; }
701
702 private:
703 HEnvironment(const HEnvironment* other, Zone* zone);
704
705 HEnvironment(HEnvironment* outer,
706 Handle<JSFunction> closure,
707 FrameType frame_type,
708 int arguments,
709 Zone* zone);
710
711 // Create an artificial stub environment (e.g. for argument adaptor or
712 // constructor stub).
713 HEnvironment* CreateStubEnvironment(HEnvironment* outer,
714 Handle<JSFunction> target,
715 FrameType frame_type,
716 int arguments) const;
717
718 // True if index is included in the expression stack part of the environment.
719 bool HasExpressionAt(int index) const;
720
721 void Initialize(int parameter_count, int local_count, int stack_height);
722 void Initialize(const HEnvironment* other);
723
724 Handle<JSFunction> closure_;
725 // Value array [parameters] [specials] [locals] [temporaries].
726 ZoneList<HValue*> values_;
727 GrowableBitVector assigned_variables_;
728 FrameType frame_type_;
729 int parameter_count_;
730 int specials_count_;
731 int local_count_;
732 HEnvironment* outer_;
733 HEnterInlined* entry_;
734 int pop_count_;
735 int push_count_;
736 BailoutId ast_id_;
737 Zone* zone_;
738 };
739
740
741 class HOptimizedGraphBuilder;
742
743 enum ArgumentsAllowedFlag {
744 ARGUMENTS_NOT_ALLOWED,
745 ARGUMENTS_ALLOWED
746 };
747
748
749 class HIfContinuation;
750
751 // This class is not BASE_EMBEDDED because our inlining implementation uses
752 // new and delete.
753 class AstContext {
754 public:
IsEffect()755 bool IsEffect() const { return kind_ == Expression::kEffect; }
IsValue()756 bool IsValue() const { return kind_ == Expression::kValue; }
IsTest()757 bool IsTest() const { return kind_ == Expression::kTest; }
758
759 // 'Fill' this context with a hydrogen value. The value is assumed to
760 // have already been inserted in the instruction stream (or not need to
761 // be, e.g., HPhi). Call this function in tail position in the Visit
762 // functions for expressions.
763 virtual void ReturnValue(HValue* value) = 0;
764
765 // Add a hydrogen instruction to the instruction stream (recording an
766 // environment simulation if necessary) and then fill this context with
767 // the instruction as value.
768 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id) = 0;
769
770 // Finishes the current basic block and materialize a boolean for
771 // value context, nothing for effect, generate a branch for test context.
772 // Call this function in tail position in the Visit functions for
773 // expressions.
774 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id) = 0;
775
776 // Finishes the current basic block and materialize a boolean for
777 // value context, nothing for effect, generate a branch for test context.
778 // Call this function in tail position in the Visit functions for
779 // expressions that use an IfBuilder.
780 virtual void ReturnContinuation(HIfContinuation* continuation,
781 BailoutId ast_id) = 0;
782
set_for_typeof(bool for_typeof)783 void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; }
is_for_typeof()784 bool is_for_typeof() { return for_typeof_; }
785
786 protected:
787 AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind);
788 virtual ~AstContext();
789
owner()790 HOptimizedGraphBuilder* owner() const { return owner_; }
791
792 inline Zone* zone() const;
793
794 // We want to be able to assert, in a context-specific way, that the stack
795 // height makes sense when the context is filled.
796 #ifdef DEBUG
797 int original_length_;
798 #endif
799
800 private:
801 HOptimizedGraphBuilder* owner_;
802 Expression::Context kind_;
803 AstContext* outer_;
804 bool for_typeof_;
805 };
806
807
808 class EffectContext V8_FINAL : public AstContext {
809 public:
EffectContext(HOptimizedGraphBuilder * owner)810 explicit EffectContext(HOptimizedGraphBuilder* owner)
811 : AstContext(owner, Expression::kEffect) {
812 }
813 virtual ~EffectContext();
814
815 virtual void ReturnValue(HValue* value) V8_OVERRIDE;
816 virtual void ReturnInstruction(HInstruction* instr,
817 BailoutId ast_id) V8_OVERRIDE;
818 virtual void ReturnControl(HControlInstruction* instr,
819 BailoutId ast_id) V8_OVERRIDE;
820 virtual void ReturnContinuation(HIfContinuation* continuation,
821 BailoutId ast_id) V8_OVERRIDE;
822 };
823
824
825 class ValueContext V8_FINAL : public AstContext {
826 public:
ValueContext(HOptimizedGraphBuilder * owner,ArgumentsAllowedFlag flag)827 ValueContext(HOptimizedGraphBuilder* owner, ArgumentsAllowedFlag flag)
828 : AstContext(owner, Expression::kValue), flag_(flag) {
829 }
830 virtual ~ValueContext();
831
832 virtual void ReturnValue(HValue* value) V8_OVERRIDE;
833 virtual void ReturnInstruction(HInstruction* instr,
834 BailoutId ast_id) V8_OVERRIDE;
835 virtual void ReturnControl(HControlInstruction* instr,
836 BailoutId ast_id) V8_OVERRIDE;
837 virtual void ReturnContinuation(HIfContinuation* continuation,
838 BailoutId ast_id) V8_OVERRIDE;
839
arguments_allowed()840 bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
841
842 private:
843 ArgumentsAllowedFlag flag_;
844 };
845
846
847 class TestContext V8_FINAL : public AstContext {
848 public:
TestContext(HOptimizedGraphBuilder * owner,Expression * condition,HBasicBlock * if_true,HBasicBlock * if_false)849 TestContext(HOptimizedGraphBuilder* owner,
850 Expression* condition,
851 HBasicBlock* if_true,
852 HBasicBlock* if_false)
853 : AstContext(owner, Expression::kTest),
854 condition_(condition),
855 if_true_(if_true),
856 if_false_(if_false) {
857 }
858
859 virtual void ReturnValue(HValue* value) V8_OVERRIDE;
860 virtual void ReturnInstruction(HInstruction* instr,
861 BailoutId ast_id) V8_OVERRIDE;
862 virtual void ReturnControl(HControlInstruction* instr,
863 BailoutId ast_id) V8_OVERRIDE;
864 virtual void ReturnContinuation(HIfContinuation* continuation,
865 BailoutId ast_id) V8_OVERRIDE;
866
cast(AstContext * context)867 static TestContext* cast(AstContext* context) {
868 ASSERT(context->IsTest());
869 return reinterpret_cast<TestContext*>(context);
870 }
871
condition()872 Expression* condition() const { return condition_; }
if_true()873 HBasicBlock* if_true() const { return if_true_; }
if_false()874 HBasicBlock* if_false() const { return if_false_; }
875
876 private:
877 // Build the shared core part of the translation unpacking a value into
878 // control flow.
879 void BuildBranch(HValue* value);
880
881 Expression* condition_;
882 HBasicBlock* if_true_;
883 HBasicBlock* if_false_;
884 };
885
886
887 class FunctionState V8_FINAL {
888 public:
889 FunctionState(HOptimizedGraphBuilder* owner,
890 CompilationInfo* info,
891 InliningKind inlining_kind);
892 ~FunctionState();
893
compilation_info()894 CompilationInfo* compilation_info() { return compilation_info_; }
call_context()895 AstContext* call_context() { return call_context_; }
inlining_kind()896 InliningKind inlining_kind() const { return inlining_kind_; }
function_return()897 HBasicBlock* function_return() { return function_return_; }
test_context()898 TestContext* test_context() { return test_context_; }
ClearInlinedTestContext()899 void ClearInlinedTestContext() {
900 delete test_context_;
901 test_context_ = NULL;
902 }
903
outer()904 FunctionState* outer() { return outer_; }
905
entry()906 HEnterInlined* entry() { return entry_; }
set_entry(HEnterInlined * entry)907 void set_entry(HEnterInlined* entry) { entry_ = entry; }
908
arguments_object()909 HArgumentsObject* arguments_object() { return arguments_object_; }
set_arguments_object(HArgumentsObject * arguments_object)910 void set_arguments_object(HArgumentsObject* arguments_object) {
911 arguments_object_ = arguments_object;
912 }
913
arguments_elements()914 HArgumentsElements* arguments_elements() { return arguments_elements_; }
set_arguments_elements(HArgumentsElements * arguments_elements)915 void set_arguments_elements(HArgumentsElements* arguments_elements) {
916 arguments_elements_ = arguments_elements;
917 }
918
arguments_pushed()919 bool arguments_pushed() { return arguments_elements() != NULL; }
920
921 private:
922 HOptimizedGraphBuilder* owner_;
923
924 CompilationInfo* compilation_info_;
925
926 // During function inlining, expression context of the call being
927 // inlined. NULL when not inlining.
928 AstContext* call_context_;
929
930 // The kind of call which is currently being inlined.
931 InliningKind inlining_kind_;
932
933 // When inlining in an effect or value context, this is the return block.
934 // It is NULL otherwise. When inlining in a test context, there are a
935 // pair of return blocks in the context. When not inlining, there is no
936 // local return point.
937 HBasicBlock* function_return_;
938
939 // When inlining a call in a test context, a context containing a pair of
940 // return blocks. NULL in all other cases.
941 TestContext* test_context_;
942
943 // When inlining HEnterInlined instruction corresponding to the function
944 // entry.
945 HEnterInlined* entry_;
946
947 HArgumentsObject* arguments_object_;
948 HArgumentsElements* arguments_elements_;
949
950 FunctionState* outer_;
951 };
952
953
954 class HIfContinuation V8_FINAL {
955 public:
HIfContinuation()956 HIfContinuation()
957 : continuation_captured_(false),
958 true_branch_(NULL),
959 false_branch_(NULL) {}
HIfContinuation(HBasicBlock * true_branch,HBasicBlock * false_branch)960 HIfContinuation(HBasicBlock* true_branch,
961 HBasicBlock* false_branch)
962 : continuation_captured_(true), true_branch_(true_branch),
963 false_branch_(false_branch) {}
~HIfContinuation()964 ~HIfContinuation() { ASSERT(!continuation_captured_); }
965
Capture(HBasicBlock * true_branch,HBasicBlock * false_branch)966 void Capture(HBasicBlock* true_branch,
967 HBasicBlock* false_branch) {
968 ASSERT(!continuation_captured_);
969 true_branch_ = true_branch;
970 false_branch_ = false_branch;
971 continuation_captured_ = true;
972 }
973
Continue(HBasicBlock ** true_branch,HBasicBlock ** false_branch)974 void Continue(HBasicBlock** true_branch,
975 HBasicBlock** false_branch) {
976 ASSERT(continuation_captured_);
977 *true_branch = true_branch_;
978 *false_branch = false_branch_;
979 continuation_captured_ = false;
980 }
981
IsTrueReachable()982 bool IsTrueReachable() { return true_branch_ != NULL; }
IsFalseReachable()983 bool IsFalseReachable() { return false_branch_ != NULL; }
TrueAndFalseReachable()984 bool TrueAndFalseReachable() {
985 return IsTrueReachable() || IsFalseReachable();
986 }
987
true_branch()988 HBasicBlock* true_branch() const { return true_branch_; }
false_branch()989 HBasicBlock* false_branch() const { return false_branch_; }
990
991 private:
992 bool continuation_captured_;
993 HBasicBlock* true_branch_;
994 HBasicBlock* false_branch_;
995 };
996
997
998 class HGraphBuilder {
999 public:
HGraphBuilder(CompilationInfo * info)1000 explicit HGraphBuilder(CompilationInfo* info)
1001 : info_(info),
1002 graph_(NULL),
1003 current_block_(NULL),
1004 position_(RelocInfo::kNoPosition) {}
~HGraphBuilder()1005 virtual ~HGraphBuilder() {}
1006
current_block()1007 HBasicBlock* current_block() const { return current_block_; }
set_current_block(HBasicBlock * block)1008 void set_current_block(HBasicBlock* block) { current_block_ = block; }
environment()1009 HEnvironment* environment() const {
1010 return current_block()->last_environment();
1011 }
zone()1012 Zone* zone() const { return info_->zone(); }
graph()1013 HGraph* graph() const { return graph_; }
isolate()1014 Isolate* isolate() const { return graph_->isolate(); }
top_info()1015 CompilationInfo* top_info() { return info_; }
1016
1017 HGraph* CreateGraph();
1018
1019 // Bailout environment manipulation.
Push(HValue * value)1020 void Push(HValue* value) { environment()->Push(value); }
Pop()1021 HValue* Pop() { return environment()->Pop(); }
1022
1023 virtual HValue* context() = 0;
1024
1025 // Adding instructions.
1026 HInstruction* AddInstruction(HInstruction* instr);
1027 void FinishCurrentBlock(HControlInstruction* last);
1028 void FinishExitCurrentBlock(HControlInstruction* instruction);
1029
1030 void Goto(HBasicBlock* from,
1031 HBasicBlock* target,
1032 FunctionState* state = NULL,
1033 bool add_simulate = true) {
1034 from->Goto(target, position_, state, add_simulate);
1035 }
1036 void Goto(HBasicBlock* target,
1037 FunctionState* state = NULL,
1038 bool add_simulate = true) {
1039 Goto(current_block(), target, state, add_simulate);
1040 }
GotoNoSimulate(HBasicBlock * from,HBasicBlock * target)1041 void GotoNoSimulate(HBasicBlock* from, HBasicBlock* target) {
1042 Goto(from, target, NULL, false);
1043 }
GotoNoSimulate(HBasicBlock * target)1044 void GotoNoSimulate(HBasicBlock* target) {
1045 Goto(target, NULL, false);
1046 }
AddLeaveInlined(HBasicBlock * block,HValue * return_value,FunctionState * state)1047 void AddLeaveInlined(HBasicBlock* block,
1048 HValue* return_value,
1049 FunctionState* state) {
1050 block->AddLeaveInlined(return_value, state, position_);
1051 }
AddLeaveInlined(HValue * return_value,FunctionState * state)1052 void AddLeaveInlined(HValue* return_value, FunctionState* state) {
1053 return AddLeaveInlined(current_block(), return_value, state);
1054 }
1055
1056 template<class I>
NewUncasted()1057 HInstruction* NewUncasted() { return I::New(zone(), context()); }
1058
1059 template<class I>
New()1060 I* New() { return I::New(zone(), context()); }
1061
1062 template<class I>
AddUncasted()1063 HInstruction* AddUncasted() { return AddInstruction(NewUncasted<I>());}
1064
1065 template<class I>
Add()1066 I* Add() { return AddInstructionTyped(New<I>());}
1067
1068 template<class I, class P1>
NewUncasted(P1 p1)1069 HInstruction* NewUncasted(P1 p1) {
1070 return I::New(zone(), context(), p1);
1071 }
1072
1073 template<class I, class P1>
New(P1 p1)1074 I* New(P1 p1) { return I::New(zone(), context(), p1); }
1075
1076 template<class I, class P1>
AddUncasted(P1 p1)1077 HInstruction* AddUncasted(P1 p1) {
1078 HInstruction* result = AddInstruction(NewUncasted<I>(p1));
1079 // Specializations must have their parameters properly casted
1080 // to avoid landing here.
1081 ASSERT(!result->IsReturn() && !result->IsSimulate() &&
1082 !result->IsDeoptimize());
1083 return result;
1084 }
1085
1086 template<class I, class P1>
Add(P1 p1)1087 I* Add(P1 p1) {
1088 I* result = AddInstructionTyped(New<I>(p1));
1089 // Specializations must have their parameters properly casted
1090 // to avoid landing here.
1091 ASSERT(!result->IsReturn() && !result->IsSimulate() &&
1092 !result->IsDeoptimize());
1093 return result;
1094 }
1095
1096 template<class I, class P1, class P2>
NewUncasted(P1 p1,P2 p2)1097 HInstruction* NewUncasted(P1 p1, P2 p2) {
1098 return I::New(zone(), context(), p1, p2);
1099 }
1100
1101 template<class I, class P1, class P2>
New(P1 p1,P2 p2)1102 I* New(P1 p1, P2 p2) {
1103 return I::New(zone(), context(), p1, p2);
1104 }
1105
1106 template<class I, class P1, class P2>
AddUncasted(P1 p1,P2 p2)1107 HInstruction* AddUncasted(P1 p1, P2 p2) {
1108 HInstruction* result = AddInstruction(NewUncasted<I>(p1, p2));
1109 // Specializations must have their parameters properly casted
1110 // to avoid landing here.
1111 ASSERT(!result->IsSimulate());
1112 return result;
1113 }
1114
1115 template<class I, class P1, class P2>
Add(P1 p1,P2 p2)1116 I* Add(P1 p1, P2 p2) {
1117 I* result = AddInstructionTyped(New<I>(p1, p2));
1118 // Specializations must have their parameters properly casted
1119 // to avoid landing here.
1120 ASSERT(!result->IsSimulate());
1121 return result;
1122 }
1123
1124 template<class I, class P1, class P2, class P3>
NewUncasted(P1 p1,P2 p2,P3 p3)1125 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3) {
1126 return I::New(zone(), context(), p1, p2, p3);
1127 }
1128
1129 template<class I, class P1, class P2, class P3>
New(P1 p1,P2 p2,P3 p3)1130 I* New(P1 p1, P2 p2, P3 p3) {
1131 return I::New(zone(), context(), p1, p2, p3);
1132 }
1133
1134 template<class I, class P1, class P2, class P3>
AddUncasted(P1 p1,P2 p2,P3 p3)1135 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3) {
1136 return AddInstruction(NewUncasted<I>(p1, p2, p3));
1137 }
1138
1139 template<class I, class P1, class P2, class P3>
Add(P1 p1,P2 p2,P3 p3)1140 I* Add(P1 p1, P2 p2, P3 p3) {
1141 return AddInstructionTyped(New<I>(p1, p2, p3));
1142 }
1143
1144 template<class I, class P1, class P2, class P3, class P4>
NewUncasted(P1 p1,P2 p2,P3 p3,P4 p4)1145 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
1146 return I::New(zone(), context(), p1, p2, p3, p4);
1147 }
1148
1149 template<class I, class P1, class P2, class P3, class P4>
New(P1 p1,P2 p2,P3 p3,P4 p4)1150 I* New(P1 p1, P2 p2, P3 p3, P4 p4) {
1151 return I::New(zone(), context(), p1, p2, p3, p4);
1152 }
1153
1154 template<class I, class P1, class P2, class P3, class P4>
AddUncasted(P1 p1,P2 p2,P3 p3,P4 p4)1155 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
1156 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4));
1157 }
1158
1159 template<class I, class P1, class P2, class P3, class P4>
Add(P1 p1,P2 p2,P3 p3,P4 p4)1160 I* Add(P1 p1, P2 p2, P3 p3, P4 p4) {
1161 return AddInstructionTyped(New<I>(p1, p2, p3, p4));
1162 }
1163
1164 template<class I, class P1, class P2, class P3, class P4, class P5>
NewUncasted(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5)1165 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1166 return I::New(zone(), context(), p1, p2, p3, p4, p5);
1167 }
1168
1169 template<class I, class P1, class P2, class P3, class P4, class P5>
New(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5)1170 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1171 return I::New(zone(), context(), p1, p2, p3, p4, p5);
1172 }
1173
1174 template<class I, class P1, class P2, class P3, class P4, class P5>
AddUncasted(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5)1175 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1176 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5));
1177 }
1178
1179 template<class I, class P1, class P2, class P3, class P4, class P5>
Add(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5)1180 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1181 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5));
1182 }
1183
1184 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
NewUncasted(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6)1185 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1186 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6);
1187 }
1188
1189 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
New(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6)1190 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1191 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6);
1192 }
1193
1194 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
AddUncasted(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6)1195 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1196 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6));
1197 }
1198
1199 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
Add(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6)1200 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1201 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6));
1202 }
1203
1204 template<class I, class P1, class P2, class P3, class P4,
1205 class P5, class P6, class P7>
NewUncasted(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7)1206 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1207 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7);
1208 }
1209
1210 template<class I, class P1, class P2, class P3, class P4,
1211 class P5, class P6, class P7>
New(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7)1212 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1213 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7);
1214 }
1215
1216 template<class I, class P1, class P2, class P3,
1217 class P4, class P5, class P6, class P7>
AddUncasted(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7)1218 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1219 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7));
1220 }
1221
1222 template<class I, class P1, class P2, class P3,
1223 class P4, class P5, class P6, class P7>
Add(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7)1224 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1225 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7));
1226 }
1227
1228 template<class I, class P1, class P2, class P3, class P4,
1229 class P5, class P6, class P7, class P8>
NewUncasted(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7,P8 p8)1230 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
1231 P5 p5, P6 p6, P7 p7, P8 p8) {
1232 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8);
1233 }
1234
1235 template<class I, class P1, class P2, class P3, class P4,
1236 class P5, class P6, class P7, class P8>
New(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7,P8 p8)1237 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
1238 return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8);
1239 }
1240
1241 template<class I, class P1, class P2, class P3, class P4,
1242 class P5, class P6, class P7, class P8>
AddUncasted(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7,P8 p8)1243 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
1244 P5 p5, P6 p6, P7 p7, P8 p8) {
1245 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8));
1246 }
1247
1248 template<class I, class P1, class P2, class P3, class P4,
1249 class P5, class P6, class P7, class P8>
Add(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7,P8 p8)1250 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
1251 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7, p8));
1252 }
1253
1254 void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE);
1255
position()1256 int position() const { return position_; }
1257
1258 protected:
1259 virtual bool BuildGraph() = 0;
1260
1261 HBasicBlock* CreateBasicBlock(HEnvironment* env);
1262 HBasicBlock* CreateLoopHeaderBlock();
1263
1264 HValue* BuildCheckHeapObject(HValue* object);
1265 HValue* BuildCheckMap(HValue* obj, Handle<Map> map);
1266 HValue* BuildCheckString(HValue* string);
1267 HValue* BuildWrapReceiver(HValue* object, HValue* function);
1268
1269 // Building common constructs
1270 HValue* BuildCheckForCapacityGrow(HValue* object,
1271 HValue* elements,
1272 ElementsKind kind,
1273 HValue* length,
1274 HValue* key,
1275 bool is_js_array);
1276
1277 HValue* BuildCopyElementsOnWrite(HValue* object,
1278 HValue* elements,
1279 ElementsKind kind,
1280 HValue* length);
1281
1282 void BuildTransitionElementsKind(HValue* object,
1283 HValue* map,
1284 ElementsKind from_kind,
1285 ElementsKind to_kind,
1286 bool is_jsarray);
1287
1288 HValue* BuildNumberToString(HValue* object, Handle<Type> type);
1289
1290 HValue* BuildUncheckedDictionaryElementLoad(HValue* receiver,
1291 HValue* key);
1292
1293 // Computes the size for a sequential string of the given length and encoding.
1294 HValue* BuildSeqStringSizeFor(HValue* length,
1295 String::Encoding encoding);
1296 // Copies characters from one sequential string to another.
1297 void BuildCopySeqStringChars(HValue* src,
1298 HValue* src_offset,
1299 String::Encoding src_encoding,
1300 HValue* dst,
1301 HValue* dst_offset,
1302 String::Encoding dst_encoding,
1303 HValue* length);
1304 // Both operands are non-empty strings.
1305 HValue* BuildUncheckedStringAdd(HValue* left,
1306 HValue* right,
1307 PretenureFlag pretenure_flag);
1308 // Both operands are strings.
1309 HValue* BuildStringAdd(HValue* left,
1310 HValue* right,
1311 PretenureFlag pretenure_flag);
1312
1313 HInstruction* BuildUncheckedMonomorphicElementAccess(
1314 HValue* checked_object,
1315 HValue* key,
1316 HValue* val,
1317 bool is_js_array,
1318 ElementsKind elements_kind,
1319 bool is_store,
1320 LoadKeyedHoleMode load_mode,
1321 KeyedAccessStoreMode store_mode);
1322
1323 HInstruction* AddElementAccess(
1324 HValue* elements,
1325 HValue* checked_key,
1326 HValue* val,
1327 HValue* dependency,
1328 ElementsKind elements_kind,
1329 bool is_store,
1330 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE);
1331
1332 HLoadNamedField* BuildLoadNamedField(HValue* object, HObjectAccess access);
1333 HInstruction* AddLoadNamedField(HValue* object, HObjectAccess access);
1334 HInstruction* BuildLoadStringLength(HValue* object, HValue* checked_value);
1335 HStoreNamedField* AddStoreMapConstant(HValue* object, Handle<Map> map);
AddStoreMapConstantNoWriteBarrier(HValue * object,Handle<Map> map)1336 HStoreNamedField* AddStoreMapConstantNoWriteBarrier(HValue* object,
1337 Handle<Map> map) {
1338 HStoreNamedField* store_map = AddStoreMapConstant(object, map);
1339 store_map->SkipWriteBarrier();
1340 return store_map;
1341 }
1342 HLoadNamedField* AddLoadElements(HValue* object);
1343
1344 bool MatchRotateRight(HValue* left,
1345 HValue* right,
1346 HValue** operand,
1347 HValue** shift_amount);
1348
1349 HValue* BuildBinaryOperation(Token::Value op,
1350 HValue* left,
1351 HValue* right,
1352 Handle<Type> left_type,
1353 Handle<Type> right_type,
1354 Handle<Type> result_type,
1355 Maybe<int> fixed_right_arg);
1356
1357 HLoadNamedField* AddLoadFixedArrayLength(HValue *object);
1358
1359 HValue* AddLoadJSBuiltin(Builtins::JavaScript builtin);
1360
1361 HValue* EnforceNumberType(HValue* number, Handle<Type> expected);
1362 HValue* TruncateToNumber(HValue* value, Handle<Type>* expected);
1363
1364 void FinishExitWithHardDeoptimization(const char* reason,
1365 HBasicBlock* continuation);
1366
1367 void AddIncrementCounter(StatsCounter* counter);
1368
1369 class IfBuilder V8_FINAL {
1370 public:
1371 explicit IfBuilder(HGraphBuilder* builder);
1372 IfBuilder(HGraphBuilder* builder,
1373 HIfContinuation* continuation);
1374
~IfBuilder()1375 ~IfBuilder() {
1376 if (!finished_) End();
1377 }
1378
1379 template<class Condition>
If(HValue * p)1380 Condition* If(HValue *p) {
1381 Condition* compare = builder()->New<Condition>(p);
1382 AddCompare(compare);
1383 return compare;
1384 }
1385
1386 template<class Condition, class P2>
If(HValue * p1,P2 p2)1387 Condition* If(HValue* p1, P2 p2) {
1388 Condition* compare = builder()->New<Condition>(p1, p2);
1389 AddCompare(compare);
1390 return compare;
1391 }
1392
1393 template<class Condition, class P2, class P3>
If(HValue * p1,P2 p2,P3 p3)1394 Condition* If(HValue* p1, P2 p2, P3 p3) {
1395 Condition* compare = builder()->New<Condition>(p1, p2, p3);
1396 AddCompare(compare);
1397 return compare;
1398 }
1399
1400 template<class Condition>
IfNot(HValue * p)1401 Condition* IfNot(HValue* p) {
1402 Condition* compare = If<Condition>(p);
1403 compare->Not();
1404 return compare;
1405 }
1406
1407 template<class Condition, class P2>
IfNot(HValue * p1,P2 p2)1408 Condition* IfNot(HValue* p1, P2 p2) {
1409 Condition* compare = If<Condition>(p1, p2);
1410 compare->Not();
1411 return compare;
1412 }
1413
1414 template<class Condition, class P2, class P3>
IfNot(HValue * p1,P2 p2,P3 p3)1415 Condition* IfNot(HValue* p1, P2 p2, P3 p3) {
1416 Condition* compare = If<Condition>(p1, p2, p3);
1417 compare->Not();
1418 return compare;
1419 }
1420
1421 template<class Condition>
OrIf(HValue * p)1422 Condition* OrIf(HValue *p) {
1423 Or();
1424 return If<Condition>(p);
1425 }
1426
1427 template<class Condition, class P2>
OrIf(HValue * p1,P2 p2)1428 Condition* OrIf(HValue* p1, P2 p2) {
1429 Or();
1430 return If<Condition>(p1, p2);
1431 }
1432
1433 template<class Condition, class P2, class P3>
OrIf(HValue * p1,P2 p2,P3 p3)1434 Condition* OrIf(HValue* p1, P2 p2, P3 p3) {
1435 Or();
1436 return If<Condition>(p1, p2, p3);
1437 }
1438
1439 template<class Condition>
AndIf(HValue * p)1440 Condition* AndIf(HValue *p) {
1441 And();
1442 return If<Condition>(p);
1443 }
1444
1445 template<class Condition, class P2>
AndIf(HValue * p1,P2 p2)1446 Condition* AndIf(HValue* p1, P2 p2) {
1447 And();
1448 return If<Condition>(p1, p2);
1449 }
1450
1451 template<class Condition, class P2, class P3>
AndIf(HValue * p1,P2 p2,P3 p3)1452 Condition* AndIf(HValue* p1, P2 p2, P3 p3) {
1453 And();
1454 return If<Condition>(p1, p2, p3);
1455 }
1456
1457 void Or();
1458 void And();
1459
1460 // Captures the current state of this IfBuilder in the specified
1461 // continuation and ends this IfBuilder.
1462 void CaptureContinuation(HIfContinuation* continuation);
1463
1464 // Joins the specified continuation from this IfBuilder and ends this
1465 // IfBuilder. This appends a Goto instruction from the true branch of
1466 // this IfBuilder to the true branch of the continuation unless the
1467 // true branch of this IfBuilder is already finished. And vice versa
1468 // for the false branch.
1469 //
1470 // The basic idea is as follows: You have several nested IfBuilder's
1471 // that you want to join based on two possible outcomes (i.e. success
1472 // and failure, or whatever). You can do this easily using this method
1473 // now, for example:
1474 //
1475 // HIfContinuation cont(graph()->CreateBasicBlock(),
1476 // graph()->CreateBasicBlock());
1477 // ...
1478 // IfBuilder if_whatever(this);
1479 // if_whatever.If<Condition>(arg);
1480 // if_whatever.Then();
1481 // ...
1482 // if_whatever.Else();
1483 // ...
1484 // if_whatever.JoinContinuation(&cont);
1485 // ...
1486 // IfBuilder if_something(this);
1487 // if_something.If<Condition>(arg1, arg2);
1488 // if_something.Then();
1489 // ...
1490 // if_something.Else();
1491 // ...
1492 // if_something.JoinContinuation(&cont);
1493 // ...
1494 // IfBuilder if_finally(this, &cont);
1495 // if_finally.Then();
1496 // // continues after then code of if_whatever or if_something.
1497 // ...
1498 // if_finally.Else();
1499 // // continues after else code of if_whatever or if_something.
1500 // ...
1501 // if_finally.End();
1502 void JoinContinuation(HIfContinuation* continuation);
1503
1504 void Then();
1505 void Else();
1506 void End();
1507
1508 void Deopt(const char* reason);
ThenDeopt(const char * reason)1509 void ThenDeopt(const char* reason) {
1510 Then();
1511 Deopt(reason);
1512 }
ElseDeopt(const char * reason)1513 void ElseDeopt(const char* reason) {
1514 Else();
1515 Deopt(reason);
1516 }
1517
1518 void Return(HValue* value);
1519
1520 private:
1521 HControlInstruction* AddCompare(HControlInstruction* compare);
1522
builder()1523 HGraphBuilder* builder() const { return builder_; }
1524
1525 void AddMergeAtJoinBlock(bool deopt);
1526
1527 void Finish();
1528 void Finish(HBasicBlock** then_continuation,
1529 HBasicBlock** else_continuation);
1530
1531 class MergeAtJoinBlock : public ZoneObject {
1532 public:
MergeAtJoinBlock(HBasicBlock * block,bool deopt,MergeAtJoinBlock * next)1533 MergeAtJoinBlock(HBasicBlock* block,
1534 bool deopt,
1535 MergeAtJoinBlock* next)
1536 : block_(block),
1537 deopt_(deopt),
1538 next_(next) {}
1539 HBasicBlock* block_;
1540 bool deopt_;
1541 MergeAtJoinBlock* next_;
1542 };
1543
1544 HGraphBuilder* builder_;
1545 bool finished_ : 1;
1546 bool did_then_ : 1;
1547 bool did_else_ : 1;
1548 bool did_else_if_ : 1;
1549 bool did_and_ : 1;
1550 bool did_or_ : 1;
1551 bool captured_ : 1;
1552 bool needs_compare_ : 1;
1553 bool pending_merge_block_ : 1;
1554 HBasicBlock* first_true_block_;
1555 HBasicBlock* first_false_block_;
1556 HBasicBlock* split_edge_merge_block_;
1557 MergeAtJoinBlock* merge_at_join_blocks_;
1558 int normal_merge_at_join_block_count_;
1559 int deopt_merge_at_join_block_count_;
1560 };
1561
1562 class LoopBuilder V8_FINAL {
1563 public:
1564 enum Direction {
1565 kPreIncrement,
1566 kPostIncrement,
1567 kPreDecrement,
1568 kPostDecrement
1569 };
1570
1571 LoopBuilder(HGraphBuilder* builder,
1572 HValue* context,
1573 Direction direction);
1574 LoopBuilder(HGraphBuilder* builder,
1575 HValue* context,
1576 Direction direction,
1577 HValue* increment_amount);
1578
~LoopBuilder()1579 ~LoopBuilder() {
1580 ASSERT(finished_);
1581 }
1582
1583 HValue* BeginBody(
1584 HValue* initial,
1585 HValue* terminating,
1586 Token::Value token);
1587
1588 void Break();
1589
1590 void EndBody();
1591
1592 private:
zone()1593 Zone* zone() { return builder_->zone(); }
1594
1595 HGraphBuilder* builder_;
1596 HValue* context_;
1597 HValue* increment_amount_;
1598 HInstruction* increment_;
1599 HPhi* phi_;
1600 HBasicBlock* header_block_;
1601 HBasicBlock* body_block_;
1602 HBasicBlock* exit_block_;
1603 HBasicBlock* exit_trampoline_block_;
1604 Direction direction_;
1605 bool finished_;
1606 };
1607
1608 HValue* BuildNewElementsCapacity(HValue* old_capacity);
1609
1610 void BuildNewSpaceArrayCheck(HValue* length,
1611 ElementsKind kind);
1612
1613 class JSArrayBuilder V8_FINAL {
1614 public:
1615 JSArrayBuilder(HGraphBuilder* builder,
1616 ElementsKind kind,
1617 HValue* allocation_site_payload,
1618 HValue* constructor_function,
1619 AllocationSiteOverrideMode override_mode);
1620
1621 JSArrayBuilder(HGraphBuilder* builder,
1622 ElementsKind kind,
1623 HValue* constructor_function = NULL);
1624
1625 enum FillMode {
1626 DONT_FILL_WITH_HOLE,
1627 FILL_WITH_HOLE
1628 };
1629
kind()1630 ElementsKind kind() { return kind_; }
1631
1632 HValue* AllocateEmptyArray();
1633 HValue* AllocateArray(HValue* capacity, HValue* length_field,
1634 FillMode fill_mode = FILL_WITH_HOLE);
GetElementsLocation()1635 HValue* GetElementsLocation() { return elements_location_; }
1636 HValue* EmitMapCode();
1637
1638 private:
zone()1639 Zone* zone() const { return builder_->zone(); }
elements_size()1640 int elements_size() const {
1641 return IsFastDoubleElementsKind(kind_) ? kDoubleSize : kPointerSize;
1642 }
builder()1643 HGraphBuilder* builder() { return builder_; }
graph()1644 HGraph* graph() { return builder_->graph(); }
initial_capacity()1645 int initial_capacity() {
1646 STATIC_ASSERT(JSArray::kPreallocatedArrayElements > 0);
1647 return JSArray::kPreallocatedArrayElements;
1648 }
1649
1650 HValue* EmitInternalMapCode();
1651 HValue* EstablishEmptyArrayAllocationSize();
1652 HValue* EstablishAllocationSize(HValue* length_node);
1653 HValue* AllocateArray(HValue* size_in_bytes, HValue* capacity,
1654 HValue* length_field,
1655 FillMode fill_mode = FILL_WITH_HOLE);
1656
1657 HGraphBuilder* builder_;
1658 ElementsKind kind_;
1659 AllocationSiteMode mode_;
1660 HValue* allocation_site_payload_;
1661 HValue* constructor_function_;
1662 HInnerAllocatedObject* elements_location_;
1663 };
1664
1665 HValue* BuildAllocateArrayFromLength(JSArrayBuilder* array_builder,
1666 HValue* length_argument);
1667
1668 HValue* BuildAllocateElements(ElementsKind kind,
1669 HValue* capacity);
1670
1671 void BuildInitializeElementsHeader(HValue* elements,
1672 ElementsKind kind,
1673 HValue* capacity);
1674
1675 HValue* BuildAllocateElementsAndInitializeElementsHeader(ElementsKind kind,
1676 HValue* capacity);
1677
1678 // array must have been allocated with enough room for
1679 // 1) the JSArray, 2) a AllocationMemento if mode requires it,
1680 // 3) a FixedArray or FixedDoubleArray.
1681 // A pointer to the Fixed(Double)Array is returned.
1682 HInnerAllocatedObject* BuildJSArrayHeader(HValue* array,
1683 HValue* array_map,
1684 AllocationSiteMode mode,
1685 ElementsKind elements_kind,
1686 HValue* allocation_site_payload,
1687 HValue* length_field);
1688
1689 HValue* BuildGrowElementsCapacity(HValue* object,
1690 HValue* elements,
1691 ElementsKind kind,
1692 ElementsKind new_kind,
1693 HValue* length,
1694 HValue* new_capacity);
1695
1696 void BuildFillElementsWithHole(HValue* elements,
1697 ElementsKind elements_kind,
1698 HValue* from,
1699 HValue* to);
1700
1701 void BuildCopyElements(HValue* from_elements,
1702 ElementsKind from_elements_kind,
1703 HValue* to_elements,
1704 ElementsKind to_elements_kind,
1705 HValue* length,
1706 HValue* capacity);
1707
1708 HValue* BuildCloneShallowArray(HValue* boilerplate,
1709 HValue* allocation_site,
1710 AllocationSiteMode mode,
1711 ElementsKind kind,
1712 int length);
1713
1714 HValue* BuildElementIndexHash(HValue* index);
1715
1716 void BuildCompareNil(
1717 HValue* value,
1718 Handle<Type> type,
1719 HIfContinuation* continuation);
1720
1721 void BuildCreateAllocationMemento(HValue* previous_object,
1722 HValue* previous_object_size,
1723 HValue* payload);
1724
1725 HInstruction* BuildConstantMapCheck(Handle<JSObject> constant,
1726 CompilationInfo* info);
1727 HInstruction* BuildCheckPrototypeMaps(Handle<JSObject> prototype,
1728 Handle<JSObject> holder);
1729
1730 HInstruction* BuildGetNativeContext();
1731 HInstruction* BuildGetArrayFunction();
1732
1733 protected:
SetSourcePosition(int position)1734 void SetSourcePosition(int position) {
1735 ASSERT(position != RelocInfo::kNoPosition);
1736 position_ = position;
1737 }
1738
1739 template <typename ViewClass>
1740 void BuildArrayBufferViewInitialization(HValue* obj,
1741 HValue* buffer,
1742 HValue* byte_offset,
1743 HValue* byte_length);
1744
1745 private:
1746 HGraphBuilder();
1747
1748 HValue* BuildUncheckedDictionaryElementLoadHelper(
1749 HValue* elements,
1750 HValue* key,
1751 HValue* hash,
1752 HValue* mask,
1753 int current_probe);
1754
1755 void PadEnvironmentForContinuation(HBasicBlock* from,
1756 HBasicBlock* continuation);
1757
1758 template <class I>
AddInstructionTyped(I * instr)1759 I* AddInstructionTyped(I* instr) {
1760 return I::cast(AddInstruction(instr));
1761 }
1762
1763 CompilationInfo* info_;
1764 HGraph* graph_;
1765 HBasicBlock* current_block_;
1766 int position_;
1767 };
1768
1769
1770 template<>
1771 inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>(
1772 const char* reason, Deoptimizer::BailoutType type) {
1773 if (type == Deoptimizer::SOFT) {
1774 isolate()->counters()->soft_deopts_requested()->Increment();
1775 if (FLAG_always_opt) return NULL;
1776 }
1777 if (current_block()->IsDeoptimizing()) return NULL;
1778 HBasicBlock* after_deopt_block = CreateBasicBlock(
1779 current_block()->last_environment());
1780 HDeoptimize* instr = New<HDeoptimize>(reason, type, after_deopt_block);
1781 if (type == Deoptimizer::SOFT) {
1782 isolate()->counters()->soft_deopts_inserted()->Increment();
1783 }
1784 FinishCurrentBlock(instr);
1785 set_current_block(after_deopt_block);
1786 return instr;
1787 }
1788
1789
1790 template<>
1791 inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>(
1792 const char* reason, Deoptimizer::BailoutType type) {
1793 return Add<HDeoptimize>(reason, type);
1794 }
1795
1796
1797 template<>
1798 inline HSimulate* HGraphBuilder::Add<HSimulate>(
1799 BailoutId id,
1800 RemovableSimulate removable) {
1801 HSimulate* instr = current_block()->CreateSimulate(id, removable);
1802 AddInstruction(instr);
1803 return instr;
1804 }
1805
1806
1807 template<>
1808 inline HSimulate* HGraphBuilder::Add<HSimulate>(
1809 BailoutId id) {
1810 return Add<HSimulate>(id, FIXED_SIMULATE);
1811 }
1812
1813
1814 template<>
1815 inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(BailoutId id) {
1816 return Add<HSimulate>(id, FIXED_SIMULATE);
1817 }
1818
1819
1820 template<>
1821 inline HReturn* HGraphBuilder::Add<HReturn>(HValue* value) {
1822 int num_parameters = graph()->info()->num_parameters();
1823 HValue* params = AddUncasted<HConstant>(num_parameters);
1824 HReturn* return_instruction = New<HReturn>(value, params);
1825 FinishExitCurrentBlock(return_instruction);
1826 return return_instruction;
1827 }
1828
1829
1830 template<>
1831 inline HReturn* HGraphBuilder::Add<HReturn>(HConstant* value) {
1832 return Add<HReturn>(static_cast<HValue*>(value));
1833 }
1834
1835 template<>
1836 inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HValue* value) {
1837 return Add<HReturn>(value);
1838 }
1839
1840
1841 template<>
1842 inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HConstant* value) {
1843 return Add<HReturn>(value);
1844 }
1845
1846
1847 template<>
1848 inline HCallRuntime* HGraphBuilder::Add<HCallRuntime>(
1849 Handle<String> name,
1850 const Runtime::Function* c_function,
1851 int argument_count) {
1852 HCallRuntime* instr = New<HCallRuntime>(name, c_function, argument_count);
1853 if (graph()->info()->IsStub()) {
1854 // When compiling code stubs, we don't want to save all double registers
1855 // upon entry to the stub, but instead have the call runtime instruction
1856 // save the double registers only on-demand (in the fallback case).
1857 instr->set_save_doubles(kSaveFPRegs);
1858 }
1859 AddInstruction(instr);
1860 return instr;
1861 }
1862
1863
1864 template<>
1865 inline HInstruction* HGraphBuilder::AddUncasted<HCallRuntime>(
1866 Handle<String> name,
1867 const Runtime::Function* c_function,
1868 int argument_count) {
1869 return Add<HCallRuntime>(name, c_function, argument_count);
1870 }
1871
1872
1873 template<>
1874 inline HContext* HGraphBuilder::New<HContext>() {
1875 return HContext::New(zone());
1876 }
1877
1878
1879 template<>
1880 inline HInstruction* HGraphBuilder::NewUncasted<HContext>() {
1881 return New<HContext>();
1882 }
1883
1884 class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
1885 public:
1886 // A class encapsulating (lazily-allocated) break and continue blocks for
1887 // a breakable statement. Separated from BreakAndContinueScope so that it
1888 // can have a separate lifetime.
1889 class BreakAndContinueInfo V8_FINAL BASE_EMBEDDED {
1890 public:
1891 explicit BreakAndContinueInfo(BreakableStatement* target,
1892 int drop_extra = 0)
target_(target)1893 : target_(target),
1894 break_block_(NULL),
1895 continue_block_(NULL),
1896 drop_extra_(drop_extra) {
1897 }
1898
target()1899 BreakableStatement* target() { return target_; }
break_block()1900 HBasicBlock* break_block() { return break_block_; }
set_break_block(HBasicBlock * block)1901 void set_break_block(HBasicBlock* block) { break_block_ = block; }
continue_block()1902 HBasicBlock* continue_block() { return continue_block_; }
set_continue_block(HBasicBlock * block)1903 void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
drop_extra()1904 int drop_extra() { return drop_extra_; }
1905
1906 private:
1907 BreakableStatement* target_;
1908 HBasicBlock* break_block_;
1909 HBasicBlock* continue_block_;
1910 int drop_extra_;
1911 };
1912
1913 // A helper class to maintain a stack of current BreakAndContinueInfo
1914 // structures mirroring BreakableStatement nesting.
1915 class BreakAndContinueScope V8_FINAL BASE_EMBEDDED {
1916 public:
BreakAndContinueScope(BreakAndContinueInfo * info,HOptimizedGraphBuilder * owner)1917 BreakAndContinueScope(BreakAndContinueInfo* info,
1918 HOptimizedGraphBuilder* owner)
1919 : info_(info), owner_(owner), next_(owner->break_scope()) {
1920 owner->set_break_scope(this);
1921 }
1922
~BreakAndContinueScope()1923 ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
1924
info()1925 BreakAndContinueInfo* info() { return info_; }
owner()1926 HOptimizedGraphBuilder* owner() { return owner_; }
next()1927 BreakAndContinueScope* next() { return next_; }
1928
1929 // Search the break stack for a break or continue target.
1930 enum BreakType { BREAK, CONTINUE };
1931 HBasicBlock* Get(BreakableStatement* stmt, BreakType type, int* drop_extra);
1932
1933 private:
1934 BreakAndContinueInfo* info_;
1935 HOptimizedGraphBuilder* owner_;
1936 BreakAndContinueScope* next_;
1937 };
1938
1939 explicit HOptimizedGraphBuilder(CompilationInfo* info);
1940
1941 virtual bool BuildGraph() V8_OVERRIDE;
1942
1943 // Simple accessors.
break_scope()1944 BreakAndContinueScope* break_scope() const { return break_scope_; }
set_break_scope(BreakAndContinueScope * head)1945 void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
1946
inline_bailout()1947 bool inline_bailout() { return inline_bailout_; }
1948
context()1949 HValue* context() { return environment()->context(); }
1950
osr()1951 HOsrBuilder* osr() const { return osr_; }
1952
1953 void Bailout(BailoutReason reason);
1954
1955 HBasicBlock* CreateJoin(HBasicBlock* first,
1956 HBasicBlock* second,
1957 BailoutId join_id);
1958
function_state()1959 FunctionState* function_state() const { return function_state_; }
1960
1961 void VisitDeclarations(ZoneList<Declaration*>* declarations);
1962
new(size_t size,Zone * zone)1963 void* operator new(size_t size, Zone* zone) {
1964 return zone->New(static_cast<int>(size));
1965 }
delete(void * pointer,Zone * zone)1966 void operator delete(void* pointer, Zone* zone) { }
delete(void * pointer)1967 void operator delete(void* pointer) { }
1968
1969 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
1970
1971 protected:
1972 // Type of a member function that generates inline code for a native function.
1973 typedef void (HOptimizedGraphBuilder::*InlineFunctionGenerator)
1974 (CallRuntime* call);
1975
1976 // Forward declarations for inner scope classes.
1977 class SubgraphScope;
1978
1979 static const InlineFunctionGenerator kInlineFunctionGenerators[];
1980
1981 static const int kMaxCallPolymorphism = 4;
1982 static const int kMaxLoadPolymorphism = 4;
1983 static const int kMaxStorePolymorphism = 4;
1984
1985 // Even in the 'unlimited' case we have to have some limit in order not to
1986 // overflow the stack.
1987 static const int kUnlimitedMaxInlinedSourceSize = 100000;
1988 static const int kUnlimitedMaxInlinedNodes = 10000;
1989 static const int kUnlimitedMaxInlinedNodesCumulative = 10000;
1990
1991 // Maximum depth and total number of elements and properties for literal
1992 // graphs to be considered for fast deep-copying.
1993 static const int kMaxFastLiteralDepth = 3;
1994 static const int kMaxFastLiteralProperties = 8;
1995
1996 // Simple accessors.
set_function_state(FunctionState * state)1997 void set_function_state(FunctionState* state) { function_state_ = state; }
1998
ast_context()1999 AstContext* ast_context() const { return ast_context_; }
set_ast_context(AstContext * context)2000 void set_ast_context(AstContext* context) { ast_context_ = context; }
2001
2002 // Accessors forwarded to the function state.
current_info()2003 CompilationInfo* current_info() const {
2004 return function_state()->compilation_info();
2005 }
call_context()2006 AstContext* call_context() const {
2007 return function_state()->call_context();
2008 }
function_return()2009 HBasicBlock* function_return() const {
2010 return function_state()->function_return();
2011 }
inlined_test_context()2012 TestContext* inlined_test_context() const {
2013 return function_state()->test_context();
2014 }
ClearInlinedTestContext()2015 void ClearInlinedTestContext() {
2016 function_state()->ClearInlinedTestContext();
2017 }
function_strict_mode_flag()2018 StrictModeFlag function_strict_mode_flag() {
2019 return function_state()->compilation_info()->is_classic_mode()
2020 ? kNonStrictMode : kStrictMode;
2021 }
2022
2023 // Generators for inline runtime functions.
2024 #define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \
2025 void Generate##Name(CallRuntime* call);
2026
2027 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
2028 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
2029 #undef INLINE_FUNCTION_GENERATOR_DECLARATION
2030
2031 void VisitDelete(UnaryOperation* expr);
2032 void VisitVoid(UnaryOperation* expr);
2033 void VisitTypeof(UnaryOperation* expr);
2034 void VisitNot(UnaryOperation* expr);
2035
2036 void VisitComma(BinaryOperation* expr);
2037 void VisitLogicalExpression(BinaryOperation* expr);
2038 void VisitArithmeticExpression(BinaryOperation* expr);
2039
2040 bool PreProcessOsrEntry(IterationStatement* statement);
2041 void VisitLoopBody(IterationStatement* stmt,
2042 HBasicBlock* loop_entry,
2043 BreakAndContinueInfo* break_info);
2044
2045 // Create a back edge in the flow graph. body_exit is the predecessor
2046 // block and loop_entry is the successor block. loop_successor is the
2047 // block where control flow exits the loop normally (e.g., via failure of
2048 // the condition) and break_block is the block where control flow breaks
2049 // from the loop. All blocks except loop_entry can be NULL. The return
2050 // value is the new successor block which is the join of loop_successor
2051 // and break_block, or NULL.
2052 HBasicBlock* CreateLoop(IterationStatement* statement,
2053 HBasicBlock* loop_entry,
2054 HBasicBlock* body_exit,
2055 HBasicBlock* loop_successor,
2056 HBasicBlock* break_block);
2057
2058 // Build a loop entry
2059 HBasicBlock* BuildLoopEntry();
2060
2061 // Builds a loop entry respectful of OSR requirements
2062 HBasicBlock* BuildLoopEntry(IterationStatement* statement);
2063
2064 HBasicBlock* JoinContinue(IterationStatement* statement,
2065 HBasicBlock* exit_block,
2066 HBasicBlock* continue_block);
2067
Top()2068 HValue* Top() const { return environment()->Top(); }
Drop(int n)2069 void Drop(int n) { environment()->Drop(n); }
Bind(Variable * var,HValue * value)2070 void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
IsEligibleForEnvironmentLivenessAnalysis(Variable * var,int index,HValue * value,HEnvironment * env)2071 bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var,
2072 int index,
2073 HValue* value,
2074 HEnvironment* env) {
2075 if (!FLAG_analyze_environment_liveness) return false;
2076 // |this| and |arguments| are always live; zapping parameters isn't
2077 // safe because function.arguments can inspect them at any time.
2078 return !var->is_this() &&
2079 !var->is_arguments() &&
2080 !value->IsArgumentsObject() &&
2081 env->is_local_index(index);
2082 }
BindIfLive(Variable * var,HValue * value)2083 void BindIfLive(Variable* var, HValue* value) {
2084 HEnvironment* env = environment();
2085 int index = env->IndexFor(var);
2086 env->Bind(index, value);
2087 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
2088 HEnvironmentMarker* bind =
2089 Add<HEnvironmentMarker>(HEnvironmentMarker::BIND, index);
2090 USE(bind);
2091 #ifdef DEBUG
2092 bind->set_closure(env->closure());
2093 #endif
2094 }
2095 }
2096
LookupAndMakeLive(Variable * var)2097 HValue* LookupAndMakeLive(Variable* var) {
2098 HEnvironment* env = environment();
2099 int index = env->IndexFor(var);
2100 HValue* value = env->Lookup(index);
2101 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
2102 HEnvironmentMarker* lookup =
2103 Add<HEnvironmentMarker>(HEnvironmentMarker::LOOKUP, index);
2104 USE(lookup);
2105 #ifdef DEBUG
2106 lookup->set_closure(env->closure());
2107 #endif
2108 }
2109 return value;
2110 }
2111
2112 // The value of the arguments object is allowed in some but not most value
2113 // contexts. (It's allowed in all effect contexts and disallowed in all
2114 // test contexts.)
2115 void VisitForValue(Expression* expr,
2116 ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
2117 void VisitForTypeOf(Expression* expr);
2118 void VisitForEffect(Expression* expr);
2119 void VisitForControl(Expression* expr,
2120 HBasicBlock* true_block,
2121 HBasicBlock* false_block);
2122
2123 // Visit an argument subexpression and emit a push to the outgoing arguments.
2124 void VisitArgument(Expression* expr);
2125
2126 void VisitArgumentList(ZoneList<Expression*>* arguments);
2127
2128 // Visit a list of expressions from left to right, each in a value context.
2129 void VisitExpressions(ZoneList<Expression*>* exprs);
2130
2131 // Remove the arguments from the bailout environment and emit instructions
2132 // to push them as outgoing parameters.
2133 template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
2134
2135 void SetUpScope(Scope* scope);
2136 virtual void VisitStatements(ZoneList<Statement*>* statements) V8_OVERRIDE;
2137
2138 #define DECLARE_VISIT(type) virtual void Visit##type(type* node) V8_OVERRIDE;
2139 AST_NODE_LIST(DECLARE_VISIT)
2140 #undef DECLARE_VISIT
2141
2142 private:
2143 // Helpers for flow graph construction.
2144 enum GlobalPropertyAccess {
2145 kUseCell,
2146 kUseGeneric
2147 };
2148 GlobalPropertyAccess LookupGlobalProperty(Variable* var,
2149 LookupResult* lookup,
2150 bool is_store);
2151
2152 void EnsureArgumentsArePushedForAccess();
2153 bool TryArgumentsAccess(Property* expr);
2154
2155 // Try to optimize fun.apply(receiver, arguments) pattern.
2156 bool TryCallApply(Call* expr);
2157
2158 int InliningAstSize(Handle<JSFunction> target);
2159 bool TryInline(CallKind call_kind,
2160 Handle<JSFunction> target,
2161 int arguments_count,
2162 HValue* implicit_return_value,
2163 BailoutId ast_id,
2164 BailoutId return_id,
2165 InliningKind inlining_kind);
2166
2167 bool TryInlineCall(Call* expr, bool drop_extra = false);
2168 bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value);
2169 bool TryInlineGetter(Handle<JSFunction> getter,
2170 BailoutId ast_id,
2171 BailoutId return_id);
2172 bool TryInlineSetter(Handle<JSFunction> setter,
2173 BailoutId id,
2174 BailoutId assignment_id,
2175 HValue* implicit_return_value);
2176 bool TryInlineApply(Handle<JSFunction> function,
2177 Call* expr,
2178 int arguments_count);
2179 bool TryInlineBuiltinMethodCall(Call* expr,
2180 HValue* receiver,
2181 Handle<Map> receiver_map,
2182 CheckType check_type);
2183 bool TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra);
2184
2185 // If --trace-inlining, print a line of the inlining trace. Inlining
2186 // succeeded if the reason string is NULL and failed if there is a
2187 // non-NULL reason string.
2188 void TraceInline(Handle<JSFunction> target,
2189 Handle<JSFunction> caller,
2190 const char* failure_reason);
2191
2192 void HandleGlobalVariableAssignment(Variable* var,
2193 HValue* value,
2194 BailoutId ast_id);
2195
2196 void HandlePropertyAssignment(Assignment* expr);
2197 void HandleCompoundAssignment(Assignment* expr);
2198 void HandlePolymorphicLoadNamedField(BailoutId ast_id,
2199 BailoutId return_id,
2200 HValue* object,
2201 SmallMapList* types,
2202 Handle<String> name);
2203
2204 void VisitTypedArrayInitialize(CallRuntime* expr);
2205
2206 bool IsCallNewArrayInlineable(CallNew* expr);
2207 void BuildInlinedCallNewArray(CallNew* expr);
2208
2209 void VisitDataViewInitialize(CallRuntime* expr);
2210
2211 class PropertyAccessInfo {
2212 public:
PropertyAccessInfo(Isolate * isolate,Handle<Map> map,Handle<String> name)2213 PropertyAccessInfo(Isolate* isolate, Handle<Map> map, Handle<String> name)
2214 : lookup_(isolate),
2215 map_(map),
2216 name_(name),
2217 access_(HObjectAccess::ForMap()) { }
2218
2219 // Checkes whether this PropertyAccessInfo can be handled as a monomorphic
2220 // load named. It additionally fills in the fields necessary to generate the
2221 // lookup code.
2222 bool CanLoadMonomorphic();
2223
2224 // Checks whether all types behave uniform when loading name. If all maps
2225 // behave the same, a single monomorphic load instruction can be emitted,
2226 // guarded by a single map-checks instruction that whether the receiver is
2227 // an instance of any of the types.
2228 // This method skips the first type in types, assuming that this
2229 // PropertyAccessInfo is built for types->first().
2230 bool CanLoadAsMonomorphic(SmallMapList* types);
2231
IsJSObjectFieldAccessor()2232 bool IsJSObjectFieldAccessor() {
2233 int offset; // unused
2234 return Accessors::IsJSObjectFieldAccessor(map_, name_, &offset);
2235 }
2236
GetJSObjectFieldAccess(HObjectAccess * access)2237 bool GetJSObjectFieldAccess(HObjectAccess* access) {
2238 if (IsStringLength()) {
2239 *access = HObjectAccess::ForStringLength();
2240 return true;
2241 } else if (IsArrayLength()) {
2242 *access = HObjectAccess::ForArrayLength(map_->elements_kind());
2243 return true;
2244 } else {
2245 int offset;
2246 if (Accessors::IsJSObjectFieldAccessor(map_, name_, &offset)) {
2247 *access = HObjectAccess::ForJSObjectOffset(offset);
2248 return true;
2249 }
2250 return false;
2251 }
2252 }
2253
has_holder()2254 bool has_holder() { return !holder_.is_null(); }
2255
lookup()2256 LookupResult* lookup() { return &lookup_; }
map()2257 Handle<Map> map() { return map_; }
holder()2258 Handle<JSObject> holder() { return holder_; }
accessor()2259 Handle<JSFunction> accessor() { return accessor_; }
constant()2260 Handle<Object> constant() { return constant_; }
access()2261 HObjectAccess access() { return access_; }
2262
2263 private:
isolate()2264 Isolate* isolate() { return lookup_.isolate(); }
2265
IsStringLength()2266 bool IsStringLength() {
2267 return map_->instance_type() < FIRST_NONSTRING_TYPE &&
2268 name_->Equals(isolate()->heap()->length_string());
2269 }
2270
IsArrayLength()2271 bool IsArrayLength() {
2272 return map_->instance_type() == JS_ARRAY_TYPE &&
2273 name_->Equals(isolate()->heap()->length_string());
2274 }
2275
2276 bool LoadResult(Handle<Map> map);
2277 bool LookupDescriptor();
2278 bool LookupInPrototypes();
2279 bool IsCompatibleForLoad(PropertyAccessInfo* other);
2280
GeneralizeRepresentation(Representation r)2281 void GeneralizeRepresentation(Representation r) {
2282 access_ = access_.WithRepresentation(
2283 access_.representation().generalize(r));
2284 }
2285
2286 LookupResult lookup_;
2287 Handle<Map> map_;
2288 Handle<String> name_;
2289 Handle<JSObject> holder_;
2290 Handle<JSFunction> accessor_;
2291 Handle<Object> constant_;
2292 HObjectAccess access_;
2293 };
2294
2295 HInstruction* BuildLoadMonomorphic(PropertyAccessInfo* info,
2296 HValue* object,
2297 HInstruction* checked_object,
2298 BailoutId ast_id,
2299 BailoutId return_id,
2300 bool can_inline_accessor = true);
2301
2302 void HandlePolymorphicStoreNamedField(BailoutId assignment_id,
2303 HValue* object,
2304 HValue* value,
2305 SmallMapList* types,
2306 Handle<String> name);
2307 bool TryStorePolymorphicAsMonomorphic(BailoutId assignment_id,
2308 HValue* object,
2309 HValue* value,
2310 SmallMapList* types,
2311 Handle<String> name);
2312 void HandlePolymorphicCallNamed(Call* expr,
2313 HValue* receiver,
2314 SmallMapList* types,
2315 Handle<String> name);
2316 bool TryCallPolymorphicAsMonomorphic(Call* expr,
2317 HValue* receiver,
2318 SmallMapList* types,
2319 Handle<String> name);
2320 void HandleLiteralCompareTypeof(CompareOperation* expr,
2321 Expression* sub_expr,
2322 Handle<String> check);
2323 void HandleLiteralCompareNil(CompareOperation* expr,
2324 Expression* sub_expr,
2325 NilValue nil);
2326
2327 HInstruction* BuildStringCharCodeAt(HValue* string,
2328 HValue* index);
2329 HValue* BuildBinaryOperation(BinaryOperation* expr,
2330 HValue* left,
2331 HValue* right);
2332 HInstruction* BuildIncrement(bool returns_original_input,
2333 CountOperation* expr);
2334 HInstruction* BuildLoadKeyedGeneric(HValue* object,
2335 HValue* key);
2336
2337 HInstruction* TryBuildConsolidatedElementLoad(HValue* object,
2338 HValue* key,
2339 HValue* val,
2340 SmallMapList* maps);
2341
2342 LoadKeyedHoleMode BuildKeyedHoleMode(Handle<Map> map);
2343
2344 HInstruction* BuildMonomorphicElementAccess(HValue* object,
2345 HValue* key,
2346 HValue* val,
2347 HValue* dependency,
2348 Handle<Map> map,
2349 bool is_store,
2350 KeyedAccessStoreMode store_mode);
2351
2352 HValue* HandlePolymorphicElementAccess(HValue* object,
2353 HValue* key,
2354 HValue* val,
2355 SmallMapList* maps,
2356 bool is_store,
2357 KeyedAccessStoreMode store_mode,
2358 bool* has_side_effects);
2359
2360 HValue* HandleKeyedElementAccess(HValue* obj,
2361 HValue* key,
2362 HValue* val,
2363 Expression* expr,
2364 bool is_store,
2365 bool* has_side_effects);
2366
2367 HInstruction* BuildLoadNamedGeneric(HValue* object,
2368 Handle<String> name,
2369 Property* expr);
2370
2371 HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map);
2372
2373 void BuildLoad(Property* property,
2374 BailoutId ast_id);
2375 void PushLoad(Property* property,
2376 HValue* object,
2377 HValue* key);
2378
2379 void BuildStoreForEffect(Expression* expression,
2380 Property* prop,
2381 BailoutId ast_id,
2382 BailoutId return_id,
2383 HValue* object,
2384 HValue* key,
2385 HValue* value);
2386
2387 void BuildStore(Expression* expression,
2388 Property* prop,
2389 BailoutId ast_id,
2390 BailoutId return_id,
2391 bool is_uninitialized = false);
2392
2393 HInstruction* BuildStoreNamedField(HValue* object,
2394 Handle<String> name,
2395 HValue* value,
2396 Handle<Map> map,
2397 LookupResult* lookup);
2398 HInstruction* BuildStoreNamedGeneric(HValue* object,
2399 Handle<String> name,
2400 HValue* value);
2401 HInstruction* BuildStoreNamedMonomorphic(HValue* object,
2402 Handle<String> name,
2403 HValue* value,
2404 Handle<Map> map);
2405 HInstruction* BuildStoreKeyedGeneric(HValue* object,
2406 HValue* key,
2407 HValue* value);
2408
2409 HValue* BuildContextChainWalk(Variable* var);
2410
2411 HInstruction* BuildThisFunction();
2412
2413 HInstruction* BuildFastLiteral(Handle<JSObject> boilerplate_object,
2414 AllocationSiteUsageContext* site_context);
2415
2416 void BuildEmitObjectHeader(Handle<JSObject> boilerplate_object,
2417 HInstruction* object);
2418
2419 void BuildInitElementsInObjectHeader(Handle<JSObject> boilerplate_object,
2420 HInstruction* object,
2421 HInstruction* object_elements);
2422
2423 void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object,
2424 HInstruction* object,
2425 AllocationSiteUsageContext* site_context,
2426 PretenureFlag pretenure_flag);
2427
2428 void BuildEmitElements(Handle<JSObject> boilerplate_object,
2429 Handle<FixedArrayBase> elements,
2430 HValue* object_elements,
2431 AllocationSiteUsageContext* site_context);
2432
2433 void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements,
2434 ElementsKind kind,
2435 HValue* object_elements);
2436
2437 void BuildEmitFixedArray(Handle<FixedArrayBase> elements,
2438 ElementsKind kind,
2439 HValue* object_elements,
2440 AllocationSiteUsageContext* site_context);
2441
2442 void AddCheckPrototypeMaps(Handle<JSObject> holder,
2443 Handle<Map> receiver_map);
2444
2445 void AddCheckConstantFunction(Handle<JSObject> holder,
2446 HValue* receiver,
2447 Handle<Map> receiver_map);
2448
2449 // The translation state of the currently-being-translated function.
2450 FunctionState* function_state_;
2451
2452 // The base of the function state stack.
2453 FunctionState initial_function_state_;
2454
2455 // Expression context of the currently visited subexpression. NULL when
2456 // visiting statements.
2457 AstContext* ast_context_;
2458
2459 // A stack of breakable statements entered.
2460 BreakAndContinueScope* break_scope_;
2461
2462 int inlined_count_;
2463 ZoneList<Handle<Object> > globals_;
2464
2465 bool inline_bailout_;
2466
2467 HOsrBuilder* osr_;
2468
2469 friend class FunctionState; // Pushes and pops the state stack.
2470 friend class AstContext; // Pushes and pops the AST context stack.
2471 friend class KeyedLoadFastElementStub;
2472 friend class HOsrBuilder;
2473
2474 DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder);
2475 };
2476
2477
zone()2478 Zone* AstContext::zone() const { return owner_->zone(); }
2479
2480
2481 class HStatistics V8_FINAL: public Malloced {
2482 public:
HStatistics()2483 HStatistics()
2484 : times_(5),
2485 names_(5),
2486 sizes_(5),
2487 total_size_(0),
2488 source_size_(0) { }
2489
2490 void Initialize(CompilationInfo* info);
2491 void Print();
2492 void SaveTiming(const char* name, TimeDelta time, unsigned size);
2493
IncrementFullCodeGen(TimeDelta full_code_gen)2494 void IncrementFullCodeGen(TimeDelta full_code_gen) {
2495 full_code_gen_ += full_code_gen;
2496 }
2497
IncrementSubtotals(TimeDelta create_graph,TimeDelta optimize_graph,TimeDelta generate_code)2498 void IncrementSubtotals(TimeDelta create_graph,
2499 TimeDelta optimize_graph,
2500 TimeDelta generate_code) {
2501 create_graph_ += create_graph;
2502 optimize_graph_ += optimize_graph;
2503 generate_code_ += generate_code;
2504 }
2505
2506 private:
2507 List<TimeDelta> times_;
2508 List<const char*> names_;
2509 List<unsigned> sizes_;
2510 TimeDelta create_graph_;
2511 TimeDelta optimize_graph_;
2512 TimeDelta generate_code_;
2513 unsigned total_size_;
2514 TimeDelta full_code_gen_;
2515 double source_size_;
2516 };
2517
2518
2519 class HPhase : public CompilationPhase {
2520 public:
HPhase(const char * name,HGraph * graph)2521 HPhase(const char* name, HGraph* graph)
2522 : CompilationPhase(name, graph->info()),
2523 graph_(graph) { }
2524 ~HPhase();
2525
2526 protected:
graph()2527 HGraph* graph() const { return graph_; }
2528
2529 private:
2530 HGraph* graph_;
2531
2532 DISALLOW_COPY_AND_ASSIGN(HPhase);
2533 };
2534
2535
2536 class HTracer V8_FINAL : public Malloced {
2537 public:
HTracer(int isolate_id)2538 explicit HTracer(int isolate_id)
2539 : trace_(&string_allocator_), indent_(0) {
2540 if (FLAG_trace_hydrogen_file == NULL) {
2541 OS::SNPrintF(filename_,
2542 "hydrogen-%d-%d.cfg",
2543 OS::GetCurrentProcessId(),
2544 isolate_id);
2545 } else {
2546 OS::StrNCpy(filename_, FLAG_trace_hydrogen_file, filename_.length());
2547 }
2548 WriteChars(filename_.start(), "", 0, false);
2549 }
2550
2551 void TraceCompilation(CompilationInfo* info);
2552 void TraceHydrogen(const char* name, HGraph* graph);
2553 void TraceLithium(const char* name, LChunk* chunk);
2554 void TraceLiveRanges(const char* name, LAllocator* allocator);
2555
2556 private:
2557 class Tag V8_FINAL BASE_EMBEDDED {
2558 public:
Tag(HTracer * tracer,const char * name)2559 Tag(HTracer* tracer, const char* name) {
2560 name_ = name;
2561 tracer_ = tracer;
2562 tracer->PrintIndent();
2563 tracer->trace_.Add("begin_%s\n", name);
2564 tracer->indent_++;
2565 }
2566
~Tag()2567 ~Tag() {
2568 tracer_->indent_--;
2569 tracer_->PrintIndent();
2570 tracer_->trace_.Add("end_%s\n", name_);
2571 ASSERT(tracer_->indent_ >= 0);
2572 tracer_->FlushToFile();
2573 }
2574
2575 private:
2576 HTracer* tracer_;
2577 const char* name_;
2578 };
2579
2580 void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
2581 void Trace(const char* name, HGraph* graph, LChunk* chunk);
2582 void FlushToFile();
2583
PrintEmptyProperty(const char * name)2584 void PrintEmptyProperty(const char* name) {
2585 PrintIndent();
2586 trace_.Add("%s\n", name);
2587 }
2588
PrintStringProperty(const char * name,const char * value)2589 void PrintStringProperty(const char* name, const char* value) {
2590 PrintIndent();
2591 trace_.Add("%s \"%s\"\n", name, value);
2592 }
2593
PrintLongProperty(const char * name,int64_t value)2594 void PrintLongProperty(const char* name, int64_t value) {
2595 PrintIndent();
2596 trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
2597 }
2598
PrintBlockProperty(const char * name,int block_id)2599 void PrintBlockProperty(const char* name, int block_id) {
2600 PrintIndent();
2601 trace_.Add("%s \"B%d\"\n", name, block_id);
2602 }
2603
PrintIntProperty(const char * name,int value)2604 void PrintIntProperty(const char* name, int value) {
2605 PrintIndent();
2606 trace_.Add("%s %d\n", name, value);
2607 }
2608
PrintIndent()2609 void PrintIndent() {
2610 for (int i = 0; i < indent_; i++) {
2611 trace_.Add(" ");
2612 }
2613 }
2614
2615 EmbeddedVector<char, 64> filename_;
2616 HeapStringAllocator string_allocator_;
2617 StringStream trace_;
2618 int indent_;
2619 };
2620
2621
2622 class NoObservableSideEffectsScope V8_FINAL {
2623 public:
NoObservableSideEffectsScope(HGraphBuilder * builder)2624 explicit NoObservableSideEffectsScope(HGraphBuilder* builder) :
2625 builder_(builder) {
2626 builder_->graph()->IncrementInNoSideEffectsScope();
2627 }
~NoObservableSideEffectsScope()2628 ~NoObservableSideEffectsScope() {
2629 builder_->graph()->DecrementInNoSideEffectsScope();
2630 }
2631
2632 private:
2633 HGraphBuilder* builder_;
2634 };
2635
2636
2637 } } // namespace v8::internal
2638
2639 #endif // V8_HYDROGEN_H_
2640