1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_CRANKSHAFT_HYDROGEN_H_
6 #define V8_CRANKSHAFT_HYDROGEN_H_
7
8 #include "src/accessors.h"
9 #include "src/allocation.h"
10 #include "src/ast/ast-type-bounds.h"
11 #include "src/ast/ast.h"
12 #include "src/ast/scopes.h"
13 #include "src/bailout-reason.h"
14 #include "src/compiler.h"
15 #include "src/crankshaft/compilation-phase.h"
16 #include "src/crankshaft/hydrogen-instructions.h"
17 #include "src/parsing/parser.h"
18 #include "src/zone.h"
19
20 namespace v8 {
21 namespace internal {
22
23 // Forward declarations.
24 class BitVector;
25 class FunctionState;
26 class HEnvironment;
27 class HGraph;
28 class HLoopInformation;
29 class HOsrBuilder;
30 class HTracer;
31 class LAllocator;
32 class LChunk;
33 class LiveRange;
34
35 class HCompilationJob final : public CompilationJob {
36 public:
HCompilationJob(Handle<JSFunction> function)37 explicit HCompilationJob(Handle<JSFunction> function)
38 : CompilationJob(&info_, "Crankshaft"),
39 zone_(function->GetIsolate()->allocator()),
40 parse_info_(&zone_, function),
41 info_(&parse_info_, function),
42 graph_(nullptr),
43 chunk_(nullptr) {}
44
45 protected:
46 virtual Status CreateGraphImpl();
47 virtual Status OptimizeGraphImpl();
48 virtual Status GenerateCodeImpl();
49
50 private:
51 Zone zone_;
52 ParseInfo parse_info_;
53 CompilationInfo info_;
54 HGraph* graph_;
55 LChunk* chunk_;
56 };
57
58 class HBasicBlock final : public ZoneObject {
59 public:
60 explicit HBasicBlock(HGraph* graph);
~HBasicBlock()61 ~HBasicBlock() { }
62
63 // Simple accessors.
block_id()64 int block_id() const { return block_id_; }
set_block_id(int id)65 void set_block_id(int id) { block_id_ = id; }
graph()66 HGraph* graph() const { return graph_; }
67 Isolate* isolate() const;
phis()68 const ZoneList<HPhi*>* phis() const { return &phis_; }
first()69 HInstruction* first() const { return first_; }
last()70 HInstruction* last() const { return last_; }
set_last(HInstruction * instr)71 void set_last(HInstruction* instr) { last_ = instr; }
end()72 HControlInstruction* end() const { return end_; }
loop_information()73 HLoopInformation* loop_information() const { return loop_information_; }
current_loop()74 HLoopInformation* current_loop() const {
75 return IsLoopHeader() ? loop_information()
76 : (parent_loop_header() != NULL
77 ? parent_loop_header()->loop_information() : NULL);
78 }
predecessors()79 const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; }
HasPredecessor()80 bool HasPredecessor() const { return predecessors_.length() > 0; }
dominated_blocks()81 const ZoneList<HBasicBlock*>* dominated_blocks() const {
82 return &dominated_blocks_;
83 }
deleted_phis()84 const ZoneList<int>* deleted_phis() const {
85 return &deleted_phis_;
86 }
RecordDeletedPhi(int merge_index)87 void RecordDeletedPhi(int merge_index) {
88 deleted_phis_.Add(merge_index, zone());
89 }
dominator()90 HBasicBlock* dominator() const { return dominator_; }
last_environment()91 HEnvironment* last_environment() const { return last_environment_; }
argument_count()92 int argument_count() const { return argument_count_; }
set_argument_count(int count)93 void set_argument_count(int count) { argument_count_ = count; }
first_instruction_index()94 int first_instruction_index() const { return first_instruction_index_; }
set_first_instruction_index(int index)95 void set_first_instruction_index(int index) {
96 first_instruction_index_ = index;
97 }
last_instruction_index()98 int last_instruction_index() const { return last_instruction_index_; }
set_last_instruction_index(int index)99 void set_last_instruction_index(int index) {
100 last_instruction_index_ = index;
101 }
is_osr_entry()102 bool is_osr_entry() { return is_osr_entry_; }
set_osr_entry()103 void set_osr_entry() { is_osr_entry_ = true; }
104
105 void AttachLoopInformation();
106 void DetachLoopInformation();
IsLoopHeader()107 bool IsLoopHeader() const { return loop_information() != NULL; }
IsStartBlock()108 bool IsStartBlock() const { return block_id() == 0; }
109 void PostProcessLoopHeader(IterationStatement* stmt);
110
IsFinished()111 bool IsFinished() const { return end_ != NULL; }
112 void AddPhi(HPhi* phi);
113 void RemovePhi(HPhi* phi);
114 void AddInstruction(HInstruction* instr, SourcePosition position);
115 bool Dominates(HBasicBlock* other) const;
116 bool EqualToOrDominates(HBasicBlock* other) const;
117 int LoopNestingDepth() const;
118
119 void SetInitialEnvironment(HEnvironment* env);
ClearEnvironment()120 void ClearEnvironment() {
121 DCHECK(IsFinished());
122 DCHECK(end()->SuccessorCount() == 0);
123 last_environment_ = NULL;
124 }
HasEnvironment()125 bool HasEnvironment() const { return last_environment_ != NULL; }
126 void UpdateEnvironment(HEnvironment* env);
parent_loop_header()127 HBasicBlock* parent_loop_header() const { return parent_loop_header_; }
128
set_parent_loop_header(HBasicBlock * block)129 void set_parent_loop_header(HBasicBlock* block) {
130 DCHECK(parent_loop_header_ == NULL);
131 parent_loop_header_ = block;
132 }
133
HasParentLoopHeader()134 bool HasParentLoopHeader() const { return parent_loop_header_ != NULL; }
135
136 void SetJoinId(BailoutId ast_id);
137
138 int PredecessorIndexOf(HBasicBlock* predecessor) const;
139 HPhi* AddNewPhi(int merged_index);
140 HSimulate* AddNewSimulate(BailoutId ast_id, SourcePosition position,
141 RemovableSimulate removable = FIXED_SIMULATE) {
142 HSimulate* instr = CreateSimulate(ast_id, removable);
143 AddInstruction(instr, position);
144 return instr;
145 }
146 void AssignCommonDominator(HBasicBlock* other);
147 void AssignLoopSuccessorDominators();
148
149 // If a target block is tagged as an inline function return, all
150 // predecessors should contain the inlined exit sequence:
151 //
152 // LeaveInlined
153 // Simulate (caller's environment)
154 // Goto (target block)
IsInlineReturnTarget()155 bool IsInlineReturnTarget() const { return is_inline_return_target_; }
MarkAsInlineReturnTarget(HBasicBlock * inlined_entry_block)156 void MarkAsInlineReturnTarget(HBasicBlock* inlined_entry_block) {
157 is_inline_return_target_ = true;
158 inlined_entry_block_ = inlined_entry_block;
159 }
inlined_entry_block()160 HBasicBlock* inlined_entry_block() { return inlined_entry_block_; }
161
IsDeoptimizing()162 bool IsDeoptimizing() const {
163 return end() != NULL && end()->IsDeoptimize();
164 }
165
166 void MarkUnreachable();
IsUnreachable()167 bool IsUnreachable() const { return !is_reachable_; }
IsReachable()168 bool IsReachable() const { return is_reachable_; }
169
IsLoopSuccessorDominator()170 bool IsLoopSuccessorDominator() const {
171 return dominates_loop_successors_;
172 }
MarkAsLoopSuccessorDominator()173 void MarkAsLoopSuccessorDominator() {
174 dominates_loop_successors_ = true;
175 }
176
IsOrdered()177 bool IsOrdered() const { return is_ordered_; }
MarkAsOrdered()178 void MarkAsOrdered() { is_ordered_ = true; }
179
180 void MarkSuccEdgeUnreachable(int succ);
181
182 inline Zone* zone() const;
183
184 #ifdef DEBUG
185 void Verify();
186 #endif
187
188 protected:
189 friend class HGraphBuilder;
190
191 HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable);
192 void Finish(HControlInstruction* last, SourcePosition position);
193 void FinishExit(HControlInstruction* instruction, SourcePosition position);
194 void Goto(HBasicBlock* block, SourcePosition position,
195 FunctionState* state = NULL, bool add_simulate = true);
GotoNoSimulate(HBasicBlock * block,SourcePosition position)196 void GotoNoSimulate(HBasicBlock* block, SourcePosition position) {
197 Goto(block, position, NULL, false);
198 }
199
200 // Add the inlined function exit sequence, adding an HLeaveInlined
201 // instruction and updating the bailout environment.
202 void AddLeaveInlined(HValue* return_value, FunctionState* state,
203 SourcePosition position);
204
205 private:
206 void RegisterPredecessor(HBasicBlock* pred);
207 void AddDominatedBlock(HBasicBlock* block);
208
209 int block_id_;
210 HGraph* graph_;
211 ZoneList<HPhi*> phis_;
212 HInstruction* first_;
213 HInstruction* last_;
214 HControlInstruction* end_;
215 HLoopInformation* loop_information_;
216 ZoneList<HBasicBlock*> predecessors_;
217 HBasicBlock* dominator_;
218 ZoneList<HBasicBlock*> dominated_blocks_;
219 HEnvironment* last_environment_;
220 // Outgoing parameter count at block exit, set during lithium translation.
221 int argument_count_;
222 // Instruction indices into the lithium code stream.
223 int first_instruction_index_;
224 int last_instruction_index_;
225 ZoneList<int> deleted_phis_;
226 HBasicBlock* parent_loop_header_;
227 // For blocks marked as inline return target: the block with HEnterInlined.
228 HBasicBlock* inlined_entry_block_;
229 bool is_inline_return_target_ : 1;
230 bool is_reachable_ : 1;
231 bool dominates_loop_successors_ : 1;
232 bool is_osr_entry_ : 1;
233 bool is_ordered_ : 1;
234 };
235
236
237 std::ostream& operator<<(std::ostream& os, const HBasicBlock& b);
238
239
240 class HPredecessorIterator final BASE_EMBEDDED {
241 public:
HPredecessorIterator(HBasicBlock * block)242 explicit HPredecessorIterator(HBasicBlock* block)
243 : predecessor_list_(block->predecessors()), current_(0) { }
244
Done()245 bool Done() { return current_ >= predecessor_list_->length(); }
Current()246 HBasicBlock* Current() { return predecessor_list_->at(current_); }
Advance()247 void Advance() { current_++; }
248
249 private:
250 const ZoneList<HBasicBlock*>* predecessor_list_;
251 int current_;
252 };
253
254
255 class HInstructionIterator final BASE_EMBEDDED {
256 public:
HInstructionIterator(HBasicBlock * block)257 explicit HInstructionIterator(HBasicBlock* block)
258 : instr_(block->first()) {
259 next_ = Done() ? NULL : instr_->next();
260 }
261
Done()262 inline bool Done() const { return instr_ == NULL; }
Current()263 inline HInstruction* Current() { return instr_; }
Advance()264 inline void Advance() {
265 instr_ = next_;
266 next_ = Done() ? NULL : instr_->next();
267 }
268
269 private:
270 HInstruction* instr_;
271 HInstruction* next_;
272 };
273
274
275 class HLoopInformation final : public ZoneObject {
276 public:
HLoopInformation(HBasicBlock * loop_header,Zone * zone)277 HLoopInformation(HBasicBlock* loop_header, Zone* zone)
278 : back_edges_(4, zone),
279 loop_header_(loop_header),
280 blocks_(8, zone),
281 stack_check_(NULL) {
282 blocks_.Add(loop_header, zone);
283 }
~HLoopInformation()284 ~HLoopInformation() {}
285
back_edges()286 const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; }
blocks()287 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
loop_header()288 HBasicBlock* loop_header() const { return loop_header_; }
289 HBasicBlock* GetLastBackEdge() const;
290 void RegisterBackEdge(HBasicBlock* block);
291
stack_check()292 HStackCheck* stack_check() const { return stack_check_; }
set_stack_check(HStackCheck * stack_check)293 void set_stack_check(HStackCheck* stack_check) {
294 stack_check_ = stack_check;
295 }
296
IsNestedInThisLoop(HLoopInformation * other)297 bool IsNestedInThisLoop(HLoopInformation* other) {
298 while (other != NULL) {
299 if (other == this) {
300 return true;
301 }
302 other = other->parent_loop();
303 }
304 return false;
305 }
parent_loop()306 HLoopInformation* parent_loop() {
307 HBasicBlock* parent_header = loop_header()->parent_loop_header();
308 return parent_header != NULL ? parent_header->loop_information() : NULL;
309 }
310
311 private:
312 void AddBlock(HBasicBlock* block);
313
314 ZoneList<HBasicBlock*> back_edges_;
315 HBasicBlock* loop_header_;
316 ZoneList<HBasicBlock*> blocks_;
317 HStackCheck* stack_check_;
318 };
319
320 struct HInlinedFunctionInfo {
HInlinedFunctionInfoHInlinedFunctionInfo321 explicit HInlinedFunctionInfo(int start_position)
322 : start_position(start_position) {}
323 int start_position;
324 };
325
326 class HGraph final : public ZoneObject {
327 public:
328 explicit HGraph(CompilationInfo* info, CallInterfaceDescriptor descriptor);
329
isolate()330 Isolate* isolate() const { return isolate_; }
zone()331 Zone* zone() const { return zone_; }
info()332 CompilationInfo* info() const { return info_; }
descriptor()333 CallInterfaceDescriptor descriptor() const { return descriptor_; }
334
blocks()335 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
phi_list()336 const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
entry_block()337 HBasicBlock* entry_block() const { return entry_block_; }
start_environment()338 HEnvironment* start_environment() const { return start_environment_; }
339
340 void FinalizeUniqueness();
341 void OrderBlocks();
342 void AssignDominators();
343 void RestoreActualValues();
344
345 // Returns false if there are phi-uses of the arguments-object
346 // which are not supported by the optimizing compiler.
347 bool CheckArgumentsPhiUses();
348
349 // Returns false if there are phi-uses of an uninitialized const
350 // which are not supported by the optimizing compiler.
351 bool CheckConstPhiUses();
352
353 void CollectPhis();
354
355 HConstant* GetConstantUndefined();
356 HConstant* GetConstant0();
357 HConstant* GetConstant1();
358 HConstant* GetConstantMinus1();
359 HConstant* GetConstantTrue();
360 HConstant* GetConstantFalse();
361 HConstant* GetConstantBool(bool value);
362 HConstant* GetConstantHole();
363 HConstant* GetConstantNull();
364 HConstant* GetConstantOptimizedOut();
365 HConstant* GetInvalidContext();
366
367 bool IsConstantUndefined(HConstant* constant);
368 bool IsConstant0(HConstant* constant);
369 bool IsConstant1(HConstant* constant);
370 bool IsConstantMinus1(HConstant* constant);
371 bool IsConstantTrue(HConstant* constant);
372 bool IsConstantFalse(HConstant* constant);
373 bool IsConstantHole(HConstant* constant);
374 bool IsConstantNull(HConstant* constant);
375 bool IsStandardConstant(HConstant* constant);
376
377 HBasicBlock* CreateBasicBlock();
378
GetMaximumValueID()379 int GetMaximumValueID() const { return values_.length(); }
GetNextBlockID()380 int GetNextBlockID() { return next_block_id_++; }
GetNextValueID(HValue * value)381 int GetNextValueID(HValue* value) {
382 DCHECK(!disallow_adding_new_values_);
383 values_.Add(value, zone());
384 return values_.length() - 1;
385 }
LookupValue(int id)386 HValue* LookupValue(int id) const {
387 if (id >= 0 && id < values_.length()) return values_[id];
388 return NULL;
389 }
DisallowAddingNewValues()390 void DisallowAddingNewValues() {
391 disallow_adding_new_values_ = true;
392 }
393
394 bool Optimize(BailoutReason* bailout_reason);
395
396 #ifdef DEBUG
397 void Verify(bool do_full_verify) const;
398 #endif
399
has_osr()400 bool has_osr() {
401 return osr_ != NULL;
402 }
403
set_osr(HOsrBuilder * osr)404 void set_osr(HOsrBuilder* osr) {
405 osr_ = osr;
406 }
407
osr()408 HOsrBuilder* osr() {
409 return osr_;
410 }
411
update_type_change_checksum(int delta)412 int update_type_change_checksum(int delta) {
413 type_change_checksum_ += delta;
414 return type_change_checksum_;
415 }
416
update_maximum_environment_size(int environment_size)417 void update_maximum_environment_size(int environment_size) {
418 if (environment_size > maximum_environment_size_) {
419 maximum_environment_size_ = environment_size;
420 }
421 }
maximum_environment_size()422 int maximum_environment_size() { return maximum_environment_size_; }
423
allow_code_motion()424 bool allow_code_motion() const { return allow_code_motion_; }
set_allow_code_motion(bool value)425 void set_allow_code_motion(bool value) { allow_code_motion_ = value; }
426
use_optimistic_licm()427 bool use_optimistic_licm() const { return use_optimistic_licm_; }
set_use_optimistic_licm(bool value)428 void set_use_optimistic_licm(bool value) { use_optimistic_licm_ = value; }
429
MarkDependsOnEmptyArrayProtoElements()430 void MarkDependsOnEmptyArrayProtoElements() {
431 // Add map dependency if not already added.
432 if (depends_on_empty_array_proto_elements_) return;
433 info()->dependencies()->AssumePropertyCell(
434 isolate()->factory()->array_protector());
435 depends_on_empty_array_proto_elements_ = true;
436 }
437
depends_on_empty_array_proto_elements()438 bool depends_on_empty_array_proto_elements() {
439 return depends_on_empty_array_proto_elements_;
440 }
441
has_uint32_instructions()442 bool has_uint32_instructions() {
443 DCHECK(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
444 return uint32_instructions_ != NULL;
445 }
446
uint32_instructions()447 ZoneList<HInstruction*>* uint32_instructions() {
448 DCHECK(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
449 return uint32_instructions_;
450 }
451
RecordUint32Instruction(HInstruction * instr)452 void RecordUint32Instruction(HInstruction* instr) {
453 DCHECK(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
454 if (uint32_instructions_ == NULL) {
455 uint32_instructions_ = new(zone()) ZoneList<HInstruction*>(4, zone());
456 }
457 uint32_instructions_->Add(instr, zone());
458 }
459
IncrementInNoSideEffectsScope()460 void IncrementInNoSideEffectsScope() { no_side_effects_scope_count_++; }
DecrementInNoSideEffectsScope()461 void DecrementInNoSideEffectsScope() { no_side_effects_scope_count_--; }
IsInsideNoSideEffectsScope()462 bool IsInsideNoSideEffectsScope() { return no_side_effects_scope_count_ > 0; }
463
464 // If we are tracking source positions then this function assigns a unique
465 // identifier to each inlining and dumps function source if it was inlined
466 // for the first time during the current optimization.
467 int TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
468 SourcePosition position);
469
470 // Converts given SourcePosition to the absolute offset from the start of
471 // the corresponding script.
472 int SourcePositionToScriptPosition(SourcePosition position);
473
inlined_function_infos()474 ZoneVector<HInlinedFunctionInfo>& inlined_function_infos() {
475 return inlined_function_infos_;
476 }
477
478 private:
479 HConstant* ReinsertConstantIfNecessary(HConstant* constant);
480 HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
481 int32_t integer_value);
482
483 template<class Phase>
Run()484 void Run() {
485 Phase phase(this);
486 phase.Run();
487 }
488
489 Isolate* isolate_;
490 int next_block_id_;
491 HBasicBlock* entry_block_;
492 HEnvironment* start_environment_;
493 ZoneList<HBasicBlock*> blocks_;
494 ZoneList<HValue*> values_;
495 ZoneList<HPhi*>* phi_list_;
496 ZoneList<HInstruction*>* uint32_instructions_;
497 SetOncePointer<HConstant> constant_undefined_;
498 SetOncePointer<HConstant> constant_0_;
499 SetOncePointer<HConstant> constant_1_;
500 SetOncePointer<HConstant> constant_minus1_;
501 SetOncePointer<HConstant> constant_true_;
502 SetOncePointer<HConstant> constant_false_;
503 SetOncePointer<HConstant> constant_the_hole_;
504 SetOncePointer<HConstant> constant_null_;
505 SetOncePointer<HConstant> constant_optimized_out_;
506 SetOncePointer<HConstant> constant_invalid_context_;
507
508 HOsrBuilder* osr_;
509
510 CompilationInfo* info_;
511 CallInterfaceDescriptor descriptor_;
512 Zone* zone_;
513
514 bool allow_code_motion_;
515 bool use_optimistic_licm_;
516 bool depends_on_empty_array_proto_elements_;
517 int type_change_checksum_;
518 int maximum_environment_size_;
519 int no_side_effects_scope_count_;
520 bool disallow_adding_new_values_;
521
522 ZoneVector<HInlinedFunctionInfo> inlined_function_infos_;
523
524 DISALLOW_COPY_AND_ASSIGN(HGraph);
525 };
526
527
zone()528 Zone* HBasicBlock::zone() const { return graph_->zone(); }
529
530
531 // Type of stack frame an environment might refer to.
532 enum FrameType {
533 JS_FUNCTION,
534 JS_CONSTRUCT,
535 JS_GETTER,
536 JS_SETTER,
537 ARGUMENTS_ADAPTOR,
538 TAIL_CALLER_FUNCTION,
539 STUB
540 };
541
542 class HEnvironment final : public ZoneObject {
543 public:
544 HEnvironment(HEnvironment* outer,
545 Scope* scope,
546 Handle<JSFunction> closure,
547 Zone* zone);
548
549 HEnvironment(Zone* zone, int parameter_count);
550
arguments_environment()551 HEnvironment* arguments_environment() {
552 return outer()->frame_type() == ARGUMENTS_ADAPTOR ? outer() : this;
553 }
554
555 // Simple accessors.
closure()556 Handle<JSFunction> closure() const { return closure_; }
values()557 const ZoneList<HValue*>* values() const { return &values_; }
assigned_variables()558 const GrowableBitVector* assigned_variables() const {
559 return &assigned_variables_;
560 }
frame_type()561 FrameType frame_type() const { return frame_type_; }
parameter_count()562 int parameter_count() const { return parameter_count_; }
specials_count()563 int specials_count() const { return specials_count_; }
local_count()564 int local_count() const { return local_count_; }
outer()565 HEnvironment* outer() const { return outer_; }
pop_count()566 int pop_count() const { return pop_count_; }
push_count()567 int push_count() const { return push_count_; }
568
ast_id()569 BailoutId ast_id() const { return ast_id_; }
set_ast_id(BailoutId id)570 void set_ast_id(BailoutId id) { ast_id_ = id; }
571
entry()572 HEnterInlined* entry() const { return entry_; }
set_entry(HEnterInlined * entry)573 void set_entry(HEnterInlined* entry) { entry_ = entry; }
574
length()575 int length() const { return values_.length(); }
576
first_expression_index()577 int first_expression_index() const {
578 return parameter_count() + specials_count() + local_count();
579 }
580
first_local_index()581 int first_local_index() const {
582 return parameter_count() + specials_count();
583 }
584
Bind(Variable * variable,HValue * value)585 void Bind(Variable* variable, HValue* value) {
586 Bind(IndexFor(variable), value);
587 }
588
589 void Bind(int index, HValue* value);
590
BindContext(HValue * value)591 void BindContext(HValue* value) {
592 Bind(parameter_count(), value);
593 }
594
Lookup(Variable * variable)595 HValue* Lookup(Variable* variable) const {
596 return Lookup(IndexFor(variable));
597 }
598
Lookup(int index)599 HValue* Lookup(int index) const {
600 HValue* result = values_[index];
601 DCHECK(result != NULL);
602 return result;
603 }
604
context()605 HValue* context() const {
606 // Return first special.
607 return Lookup(parameter_count());
608 }
609
Push(HValue * value)610 void Push(HValue* value) {
611 DCHECK(value != NULL);
612 ++push_count_;
613 values_.Add(value, zone());
614 }
615
Pop()616 HValue* Pop() {
617 DCHECK(!ExpressionStackIsEmpty());
618 if (push_count_ > 0) {
619 --push_count_;
620 } else {
621 ++pop_count_;
622 }
623 return values_.RemoveLast();
624 }
625
626 void Drop(int count);
627
Top()628 HValue* Top() const { return ExpressionStackAt(0); }
629
630 bool ExpressionStackIsEmpty() const;
631
ExpressionStackAt(int index_from_top)632 HValue* ExpressionStackAt(int index_from_top) const {
633 int index = length() - index_from_top - 1;
634 DCHECK(HasExpressionAt(index));
635 return values_[index];
636 }
637
638 void SetExpressionStackAt(int index_from_top, HValue* value);
639 HValue* RemoveExpressionStackAt(int index_from_top);
640
641 void Print() const;
642
643 HEnvironment* Copy() const;
644 HEnvironment* CopyWithoutHistory() const;
645 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const;
646
647 // Create an "inlined version" of this environment, where the original
648 // environment is the outer environment but the top expression stack
649 // elements are moved to an inner environment as parameters.
650 HEnvironment* CopyForInlining(Handle<JSFunction> target, int arguments,
651 FunctionLiteral* function, HConstant* undefined,
652 InliningKind inlining_kind,
653 TailCallMode syntactic_tail_call_mode) const;
654
DiscardInlined(bool drop_extra)655 HEnvironment* DiscardInlined(bool drop_extra) {
656 HEnvironment* outer = outer_;
657 while (outer->frame_type() != JS_FUNCTION &&
658 outer->frame_type() != TAIL_CALLER_FUNCTION) {
659 outer = outer->outer_;
660 }
661 if (drop_extra) outer->Drop(1);
662 if (outer->frame_type() == TAIL_CALLER_FUNCTION) {
663 outer->ClearTailCallerMark();
664 }
665 return outer;
666 }
667
668 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
669
ClearHistory()670 void ClearHistory() {
671 pop_count_ = 0;
672 push_count_ = 0;
673 assigned_variables_.Clear();
674 }
675
SetValueAt(int index,HValue * value)676 void SetValueAt(int index, HValue* value) {
677 DCHECK(index < length());
678 values_[index] = value;
679 }
680
681 // Map a variable to an environment index. Parameter indices are shifted
682 // by 1 (receiver is parameter index -1 but environment index 0).
683 // Stack-allocated local indices are shifted by the number of parameters.
IndexFor(Variable * variable)684 int IndexFor(Variable* variable) const {
685 DCHECK(variable->IsStackAllocated());
686 int shift = variable->IsParameter()
687 ? 1
688 : parameter_count_ + specials_count_;
689 return variable->index() + shift;
690 }
691
is_local_index(int i)692 bool is_local_index(int i) const {
693 return i >= first_local_index() && i < first_expression_index();
694 }
695
is_parameter_index(int i)696 bool is_parameter_index(int i) const {
697 return i >= 0 && i < parameter_count();
698 }
699
is_special_index(int i)700 bool is_special_index(int i) const {
701 return i >= parameter_count() && i < parameter_count() + specials_count();
702 }
703
zone()704 Zone* zone() const { return zone_; }
705
706 private:
707 HEnvironment(const HEnvironment* other, Zone* zone);
708
709 HEnvironment(HEnvironment* outer,
710 Handle<JSFunction> closure,
711 FrameType frame_type,
712 int arguments,
713 Zone* zone);
714
715 // Create an artificial stub environment (e.g. for argument adaptor or
716 // constructor stub).
717 HEnvironment* CreateStubEnvironment(HEnvironment* outer,
718 Handle<JSFunction> target,
719 FrameType frame_type,
720 int arguments) const;
721
722 // Marks current environment as tail caller by setting frame type to
723 // TAIL_CALLER_FUNCTION.
724 void MarkAsTailCaller();
725 void ClearTailCallerMark();
726
727 // True if index is included in the expression stack part of the environment.
728 bool HasExpressionAt(int index) const;
729
730 void Initialize(int parameter_count, int local_count, int stack_height);
731 void Initialize(const HEnvironment* other);
732
733 Handle<JSFunction> closure_;
734 // Value array [parameters] [specials] [locals] [temporaries].
735 ZoneList<HValue*> values_;
736 GrowableBitVector assigned_variables_;
737 FrameType frame_type_;
738 int parameter_count_;
739 int specials_count_;
740 int local_count_;
741 HEnvironment* outer_;
742 HEnterInlined* entry_;
743 int pop_count_;
744 int push_count_;
745 BailoutId ast_id_;
746 Zone* zone_;
747 };
748
749
750 std::ostream& operator<<(std::ostream& os, const HEnvironment& env);
751
752
753 class HOptimizedGraphBuilder;
754
755 enum ArgumentsAllowedFlag {
756 ARGUMENTS_NOT_ALLOWED,
757 ARGUMENTS_ALLOWED,
758 ARGUMENTS_FAKED
759 };
760
761
762 class HIfContinuation;
763
764 // This class is not BASE_EMBEDDED because our inlining implementation uses
765 // new and delete.
766 class AstContext {
767 public:
IsEffect()768 bool IsEffect() const { return kind_ == Expression::kEffect; }
IsValue()769 bool IsValue() const { return kind_ == Expression::kValue; }
IsTest()770 bool IsTest() const { return kind_ == Expression::kTest; }
771
772 // 'Fill' this context with a hydrogen value. The value is assumed to
773 // have already been inserted in the instruction stream (or not need to
774 // be, e.g., HPhi). Call this function in tail position in the Visit
775 // functions for expressions.
776 virtual void ReturnValue(HValue* value) = 0;
777
778 // Add a hydrogen instruction to the instruction stream (recording an
779 // environment simulation if necessary) and then fill this context with
780 // the instruction as value.
781 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id) = 0;
782
783 // Finishes the current basic block and materialize a boolean for
784 // value context, nothing for effect, generate a branch for test context.
785 // Call this function in tail position in the Visit functions for
786 // expressions.
787 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id) = 0;
788
789 // Finishes the current basic block and materialize a boolean for
790 // value context, nothing for effect, generate a branch for test context.
791 // Call this function in tail position in the Visit functions for
792 // expressions that use an IfBuilder.
793 virtual void ReturnContinuation(HIfContinuation* continuation,
794 BailoutId ast_id) = 0;
795
set_typeof_mode(TypeofMode typeof_mode)796 void set_typeof_mode(TypeofMode typeof_mode) { typeof_mode_ = typeof_mode; }
typeof_mode()797 TypeofMode typeof_mode() { return typeof_mode_; }
798
799 protected:
800 AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind);
801 virtual ~AstContext();
802
owner()803 HOptimizedGraphBuilder* owner() const { return owner_; }
804
805 inline Zone* zone() const;
806
807 // We want to be able to assert, in a context-specific way, that the stack
808 // height makes sense when the context is filled.
809 #ifdef DEBUG
810 int original_length_;
811 #endif
812
813 private:
814 HOptimizedGraphBuilder* owner_;
815 Expression::Context kind_;
816 AstContext* outer_;
817 TypeofMode typeof_mode_;
818 };
819
820
821 class EffectContext final : public AstContext {
822 public:
EffectContext(HOptimizedGraphBuilder * owner)823 explicit EffectContext(HOptimizedGraphBuilder* owner)
824 : AstContext(owner, Expression::kEffect) {
825 }
826 ~EffectContext() override;
827
828 void ReturnValue(HValue* value) override;
829 void ReturnInstruction(HInstruction* instr, BailoutId ast_id) override;
830 void ReturnControl(HControlInstruction* instr, BailoutId ast_id) override;
831 void ReturnContinuation(HIfContinuation* continuation,
832 BailoutId ast_id) override;
833 };
834
835
836 class ValueContext final : public AstContext {
837 public:
ValueContext(HOptimizedGraphBuilder * owner,ArgumentsAllowedFlag flag)838 ValueContext(HOptimizedGraphBuilder* owner, ArgumentsAllowedFlag flag)
839 : AstContext(owner, Expression::kValue), flag_(flag) {
840 }
841 ~ValueContext() override;
842
843 void ReturnValue(HValue* value) override;
844 void ReturnInstruction(HInstruction* instr, BailoutId ast_id) override;
845 void ReturnControl(HControlInstruction* instr, BailoutId ast_id) override;
846 void ReturnContinuation(HIfContinuation* continuation,
847 BailoutId ast_id) override;
848
arguments_allowed()849 bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
850
851 private:
852 ArgumentsAllowedFlag flag_;
853 };
854
855
856 class TestContext final : public AstContext {
857 public:
TestContext(HOptimizedGraphBuilder * owner,Expression * condition,HBasicBlock * if_true,HBasicBlock * if_false)858 TestContext(HOptimizedGraphBuilder* owner,
859 Expression* condition,
860 HBasicBlock* if_true,
861 HBasicBlock* if_false)
862 : AstContext(owner, Expression::kTest),
863 condition_(condition),
864 if_true_(if_true),
865 if_false_(if_false) {
866 }
867
868 void ReturnValue(HValue* value) override;
869 void ReturnInstruction(HInstruction* instr, BailoutId ast_id) override;
870 void ReturnControl(HControlInstruction* instr, BailoutId ast_id) override;
871 void ReturnContinuation(HIfContinuation* continuation,
872 BailoutId ast_id) override;
873
cast(AstContext * context)874 static TestContext* cast(AstContext* context) {
875 DCHECK(context->IsTest());
876 return reinterpret_cast<TestContext*>(context);
877 }
878
condition()879 Expression* condition() const { return condition_; }
if_true()880 HBasicBlock* if_true() const { return if_true_; }
if_false()881 HBasicBlock* if_false() const { return if_false_; }
882
883 private:
884 // Build the shared core part of the translation unpacking a value into
885 // control flow.
886 void BuildBranch(HValue* value);
887
888 Expression* condition_;
889 HBasicBlock* if_true_;
890 HBasicBlock* if_false_;
891 };
892
893
894 class FunctionState final {
895 public:
896 FunctionState(HOptimizedGraphBuilder* owner, CompilationInfo* info,
897 InliningKind inlining_kind, int inlining_id,
898 TailCallMode tail_call_mode);
899 ~FunctionState();
900
compilation_info()901 CompilationInfo* compilation_info() { return compilation_info_; }
call_context()902 AstContext* call_context() { return call_context_; }
inlining_kind()903 InliningKind inlining_kind() const { return inlining_kind_; }
function_return()904 HBasicBlock* function_return() { return function_return_; }
test_context()905 TestContext* test_context() { return test_context_; }
ClearInlinedTestContext()906 void ClearInlinedTestContext() {
907 delete test_context_;
908 test_context_ = NULL;
909 }
910
outer()911 FunctionState* outer() { return outer_; }
912
ComputeTailCallMode(TailCallMode tail_call_mode)913 TailCallMode ComputeTailCallMode(TailCallMode tail_call_mode) const {
914 if (tail_call_mode_ == TailCallMode::kDisallow) return tail_call_mode_;
915 return tail_call_mode;
916 }
917
entry()918 HEnterInlined* entry() { return entry_; }
set_entry(HEnterInlined * entry)919 void set_entry(HEnterInlined* entry) { entry_ = entry; }
920
arguments_object()921 HArgumentsObject* arguments_object() { return arguments_object_; }
set_arguments_object(HArgumentsObject * arguments_object)922 void set_arguments_object(HArgumentsObject* arguments_object) {
923 arguments_object_ = arguments_object;
924 }
925
arguments_elements()926 HArgumentsElements* arguments_elements() { return arguments_elements_; }
set_arguments_elements(HArgumentsElements * arguments_elements)927 void set_arguments_elements(HArgumentsElements* arguments_elements) {
928 arguments_elements_ = arguments_elements;
929 }
930
arguments_pushed()931 bool arguments_pushed() { return arguments_elements() != NULL; }
932
inlining_id()933 int inlining_id() const { return inlining_id_; }
934
IncrementInDoExpressionScope()935 void IncrementInDoExpressionScope() { do_expression_scope_count_++; }
DecrementInDoExpressionScope()936 void DecrementInDoExpressionScope() { do_expression_scope_count_--; }
IsInsideDoExpressionScope()937 bool IsInsideDoExpressionScope() { return do_expression_scope_count_ > 0; }
938
939 private:
940 HOptimizedGraphBuilder* owner_;
941
942 CompilationInfo* compilation_info_;
943
944 // During function inlining, expression context of the call being
945 // inlined. NULL when not inlining.
946 AstContext* call_context_;
947
948 // The kind of call which is currently being inlined.
949 InliningKind inlining_kind_;
950
951 // Defines whether the calls with TailCallMode::kAllow in the function body
952 // can be generated as tail calls.
953 TailCallMode tail_call_mode_;
954
955 // When inlining in an effect or value context, this is the return block.
956 // It is NULL otherwise. When inlining in a test context, there are a
957 // pair of return blocks in the context. When not inlining, there is no
958 // local return point.
959 HBasicBlock* function_return_;
960
961 // When inlining a call in a test context, a context containing a pair of
962 // return blocks. NULL in all other cases.
963 TestContext* test_context_;
964
965 // When inlining HEnterInlined instruction corresponding to the function
966 // entry.
967 HEnterInlined* entry_;
968
969 HArgumentsObject* arguments_object_;
970 HArgumentsElements* arguments_elements_;
971
972 int inlining_id_;
973 SourcePosition outer_source_position_;
974
975 int do_expression_scope_count_;
976
977 FunctionState* outer_;
978 };
979
980
981 class HIfContinuation final {
982 public:
HIfContinuation()983 HIfContinuation()
984 : continuation_captured_(false),
985 true_branch_(NULL),
986 false_branch_(NULL) {}
HIfContinuation(HBasicBlock * true_branch,HBasicBlock * false_branch)987 HIfContinuation(HBasicBlock* true_branch,
988 HBasicBlock* false_branch)
989 : continuation_captured_(true), true_branch_(true_branch),
990 false_branch_(false_branch) {}
~HIfContinuation()991 ~HIfContinuation() { DCHECK(!continuation_captured_); }
992
Capture(HBasicBlock * true_branch,HBasicBlock * false_branch)993 void Capture(HBasicBlock* true_branch,
994 HBasicBlock* false_branch) {
995 DCHECK(!continuation_captured_);
996 true_branch_ = true_branch;
997 false_branch_ = false_branch;
998 continuation_captured_ = true;
999 }
1000
Continue(HBasicBlock ** true_branch,HBasicBlock ** false_branch)1001 void Continue(HBasicBlock** true_branch,
1002 HBasicBlock** false_branch) {
1003 DCHECK(continuation_captured_);
1004 *true_branch = true_branch_;
1005 *false_branch = false_branch_;
1006 continuation_captured_ = false;
1007 }
1008
IsTrueReachable()1009 bool IsTrueReachable() { return true_branch_ != NULL; }
IsFalseReachable()1010 bool IsFalseReachable() { return false_branch_ != NULL; }
TrueAndFalseReachable()1011 bool TrueAndFalseReachable() {
1012 return IsTrueReachable() || IsFalseReachable();
1013 }
1014
true_branch()1015 HBasicBlock* true_branch() const { return true_branch_; }
false_branch()1016 HBasicBlock* false_branch() const { return false_branch_; }
1017
1018 private:
1019 bool continuation_captured_;
1020 HBasicBlock* true_branch_;
1021 HBasicBlock* false_branch_;
1022 };
1023
1024
1025 class HAllocationMode final BASE_EMBEDDED {
1026 public:
HAllocationMode(Handle<AllocationSite> feedback_site)1027 explicit HAllocationMode(Handle<AllocationSite> feedback_site)
1028 : current_site_(NULL), feedback_site_(feedback_site),
1029 pretenure_flag_(NOT_TENURED) {}
HAllocationMode(HValue * current_site)1030 explicit HAllocationMode(HValue* current_site)
1031 : current_site_(current_site), pretenure_flag_(NOT_TENURED) {}
HAllocationMode(PretenureFlag pretenure_flag)1032 explicit HAllocationMode(PretenureFlag pretenure_flag)
1033 : current_site_(NULL), pretenure_flag_(pretenure_flag) {}
HAllocationMode()1034 HAllocationMode()
1035 : current_site_(NULL), pretenure_flag_(NOT_TENURED) {}
1036
current_site()1037 HValue* current_site() const { return current_site_; }
feedback_site()1038 Handle<AllocationSite> feedback_site() const { return feedback_site_; }
1039
CreateAllocationMementos()1040 bool CreateAllocationMementos() const WARN_UNUSED_RESULT {
1041 return current_site() != NULL;
1042 }
1043
GetPretenureMode()1044 PretenureFlag GetPretenureMode() const WARN_UNUSED_RESULT {
1045 if (!feedback_site().is_null()) return feedback_site()->GetPretenureMode();
1046 return pretenure_flag_;
1047 }
1048
1049 private:
1050 HValue* current_site_;
1051 Handle<AllocationSite> feedback_site_;
1052 PretenureFlag pretenure_flag_;
1053 };
1054
1055
1056 class HGraphBuilder {
1057 public:
HGraphBuilder(CompilationInfo * info,CallInterfaceDescriptor descriptor)1058 explicit HGraphBuilder(CompilationInfo* info,
1059 CallInterfaceDescriptor descriptor)
1060 : info_(info),
1061 descriptor_(descriptor),
1062 graph_(NULL),
1063 current_block_(NULL),
1064 scope_(info->scope()),
1065 position_(SourcePosition::Unknown()),
1066 start_position_(0) {}
~HGraphBuilder()1067 virtual ~HGraphBuilder() {}
1068
scope()1069 Scope* scope() const { return scope_; }
set_scope(Scope * scope)1070 void set_scope(Scope* scope) { scope_ = scope; }
1071
current_block()1072 HBasicBlock* current_block() const { return current_block_; }
set_current_block(HBasicBlock * block)1073 void set_current_block(HBasicBlock* block) { current_block_ = block; }
environment()1074 HEnvironment* environment() const {
1075 return current_block()->last_environment();
1076 }
zone()1077 Zone* zone() const { return info_->zone(); }
graph()1078 HGraph* graph() const { return graph_; }
isolate()1079 Isolate* isolate() const { return graph_->isolate(); }
top_info()1080 CompilationInfo* top_info() { return info_; }
1081
1082 HGraph* CreateGraph();
1083
1084 // Bailout environment manipulation.
Push(HValue * value)1085 void Push(HValue* value) { environment()->Push(value); }
Pop()1086 HValue* Pop() { return environment()->Pop(); }
1087
1088 virtual HValue* context() = 0;
1089
1090 // Adding instructions.
1091 HInstruction* AddInstruction(HInstruction* instr);
1092 void FinishCurrentBlock(HControlInstruction* last);
1093 void FinishExitCurrentBlock(HControlInstruction* instruction);
1094
1095 void Goto(HBasicBlock* from,
1096 HBasicBlock* target,
1097 FunctionState* state = NULL,
1098 bool add_simulate = true) {
1099 from->Goto(target, source_position(), state, add_simulate);
1100 }
1101 void Goto(HBasicBlock* target,
1102 FunctionState* state = NULL,
1103 bool add_simulate = true) {
1104 Goto(current_block(), target, state, add_simulate);
1105 }
GotoNoSimulate(HBasicBlock * from,HBasicBlock * target)1106 void GotoNoSimulate(HBasicBlock* from, HBasicBlock* target) {
1107 Goto(from, target, NULL, false);
1108 }
GotoNoSimulate(HBasicBlock * target)1109 void GotoNoSimulate(HBasicBlock* target) {
1110 Goto(target, NULL, false);
1111 }
AddLeaveInlined(HBasicBlock * block,HValue * return_value,FunctionState * state)1112 void AddLeaveInlined(HBasicBlock* block,
1113 HValue* return_value,
1114 FunctionState* state) {
1115 block->AddLeaveInlined(return_value, state, source_position());
1116 }
AddLeaveInlined(HValue * return_value,FunctionState * state)1117 void AddLeaveInlined(HValue* return_value, FunctionState* state) {
1118 return AddLeaveInlined(current_block(), return_value, state);
1119 }
1120
1121 template <class I>
NewUncasted()1122 HInstruction* NewUncasted() {
1123 return I::New(isolate(), zone(), context());
1124 }
1125
1126 template <class I>
New()1127 I* New() {
1128 return I::New(isolate(), zone(), context());
1129 }
1130
1131 template<class I>
AddUncasted()1132 HInstruction* AddUncasted() { return AddInstruction(NewUncasted<I>());}
1133
1134 template<class I>
Add()1135 I* Add() { return AddInstructionTyped(New<I>());}
1136
1137 template<class I, class P1>
NewUncasted(P1 p1)1138 HInstruction* NewUncasted(P1 p1) {
1139 return I::New(isolate(), zone(), context(), p1);
1140 }
1141
1142 template <class I, class P1>
New(P1 p1)1143 I* New(P1 p1) {
1144 return I::New(isolate(), zone(), context(), p1);
1145 }
1146
1147 template<class I, class P1>
AddUncasted(P1 p1)1148 HInstruction* AddUncasted(P1 p1) {
1149 HInstruction* result = AddInstruction(NewUncasted<I>(p1));
1150 // Specializations must have their parameters properly casted
1151 // to avoid landing here.
1152 DCHECK(!result->IsReturn() && !result->IsSimulate() &&
1153 !result->IsDeoptimize());
1154 return result;
1155 }
1156
1157 template<class I, class P1>
Add(P1 p1)1158 I* Add(P1 p1) {
1159 I* result = AddInstructionTyped(New<I>(p1));
1160 // Specializations must have their parameters properly casted
1161 // to avoid landing here.
1162 DCHECK(!result->IsReturn() && !result->IsSimulate() &&
1163 !result->IsDeoptimize());
1164 return result;
1165 }
1166
1167 template<class I, class P1, class P2>
NewUncasted(P1 p1,P2 p2)1168 HInstruction* NewUncasted(P1 p1, P2 p2) {
1169 return I::New(isolate(), zone(), context(), p1, p2);
1170 }
1171
1172 template<class I, class P1, class P2>
New(P1 p1,P2 p2)1173 I* New(P1 p1, P2 p2) {
1174 return I::New(isolate(), zone(), context(), p1, p2);
1175 }
1176
1177 template<class I, class P1, class P2>
AddUncasted(P1 p1,P2 p2)1178 HInstruction* AddUncasted(P1 p1, P2 p2) {
1179 HInstruction* result = AddInstruction(NewUncasted<I>(p1, p2));
1180 // Specializations must have their parameters properly casted
1181 // to avoid landing here.
1182 DCHECK(!result->IsSimulate());
1183 return result;
1184 }
1185
1186 template<class I, class P1, class P2>
Add(P1 p1,P2 p2)1187 I* Add(P1 p1, P2 p2) {
1188 I* result = AddInstructionTyped(New<I>(p1, p2));
1189 // Specializations must have their parameters properly casted
1190 // to avoid landing here.
1191 DCHECK(!result->IsSimulate());
1192 return result;
1193 }
1194
1195 template<class I, class P1, class P2, class P3>
NewUncasted(P1 p1,P2 p2,P3 p3)1196 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3) {
1197 return I::New(isolate(), zone(), context(), p1, p2, p3);
1198 }
1199
1200 template<class I, class P1, class P2, class P3>
New(P1 p1,P2 p2,P3 p3)1201 I* New(P1 p1, P2 p2, P3 p3) {
1202 return I::New(isolate(), zone(), context(), p1, p2, p3);
1203 }
1204
1205 template<class I, class P1, class P2, class P3>
AddUncasted(P1 p1,P2 p2,P3 p3)1206 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3) {
1207 return AddInstruction(NewUncasted<I>(p1, p2, p3));
1208 }
1209
1210 template<class I, class P1, class P2, class P3>
Add(P1 p1,P2 p2,P3 p3)1211 I* Add(P1 p1, P2 p2, P3 p3) {
1212 return AddInstructionTyped(New<I>(p1, p2, p3));
1213 }
1214
1215 template<class I, class P1, class P2, class P3, class P4>
NewUncasted(P1 p1,P2 p2,P3 p3,P4 p4)1216 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
1217 return I::New(isolate(), zone(), context(), p1, p2, p3, p4);
1218 }
1219
1220 template<class I, class P1, class P2, class P3, class P4>
New(P1 p1,P2 p2,P3 p3,P4 p4)1221 I* New(P1 p1, P2 p2, P3 p3, P4 p4) {
1222 return I::New(isolate(), zone(), context(), p1, p2, p3, p4);
1223 }
1224
1225 template<class I, class P1, class P2, class P3, class P4>
AddUncasted(P1 p1,P2 p2,P3 p3,P4 p4)1226 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
1227 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4));
1228 }
1229
1230 template<class I, class P1, class P2, class P3, class P4>
Add(P1 p1,P2 p2,P3 p3,P4 p4)1231 I* Add(P1 p1, P2 p2, P3 p3, P4 p4) {
1232 return AddInstructionTyped(New<I>(p1, p2, p3, p4));
1233 }
1234
1235 template<class I, class P1, class P2, class P3, class P4, class P5>
NewUncasted(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5)1236 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1237 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5);
1238 }
1239
1240 template<class I, class P1, class P2, class P3, class P4, class P5>
New(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5)1241 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1242 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5);
1243 }
1244
1245 template<class I, class P1, class P2, class P3, class P4, class P5>
AddUncasted(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5)1246 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1247 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5));
1248 }
1249
1250 template<class I, class P1, class P2, class P3, class P4, class P5>
Add(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5)1251 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1252 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5));
1253 }
1254
1255 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)1256 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1257 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6);
1258 }
1259
1260 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)1261 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1262 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6);
1263 }
1264
1265 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)1266 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1267 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6));
1268 }
1269
1270 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)1271 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1272 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6));
1273 }
1274
1275 template<class I, class P1, class P2, class P3, class P4,
1276 class P5, class P6, class P7>
NewUncasted(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7)1277 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1278 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7);
1279 }
1280
1281 template<class I, class P1, class P2, class P3, class P4,
1282 class P5, class P6, class P7>
New(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7)1283 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1284 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7);
1285 }
1286
1287 template<class I, class P1, class P2, class P3,
1288 class P4, class P5, class P6, class P7>
AddUncasted(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7)1289 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1290 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7));
1291 }
1292
1293 template<class I, class P1, class P2, class P3,
1294 class P4, class P5, class P6, class P7>
Add(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7)1295 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1296 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7));
1297 }
1298
1299 template<class I, class P1, class P2, class P3, class P4,
1300 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)1301 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
1302 P5 p5, P6 p6, P7 p7, P8 p8) {
1303 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8);
1304 }
1305
1306 template<class I, class P1, class P2, class P3, class P4,
1307 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)1308 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
1309 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8);
1310 }
1311
1312 template<class I, class P1, class P2, class P3, class P4,
1313 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)1314 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
1315 P5 p5, P6 p6, P7 p7, P8 p8) {
1316 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8));
1317 }
1318
1319 template<class I, class P1, class P2, class P3, class P4,
1320 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)1321 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
1322 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7, p8));
1323 }
1324
1325 template <class I, class P1, class P2, class P3, class P4, class P5, class P6,
1326 class P7, class P8, class P9>
New(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7,P8 p8,P9 p9)1327 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) {
1328 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8,
1329 p9);
1330 }
1331
1332 template <class I, class P1, class P2, class P3, class P4, class P5, class P6,
1333 class P7, class P8, class P9>
AddUncasted(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7,P8 p8,P9 p9)1334 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7,
1335 P8 p8, P9 p9) {
1336 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8, p9));
1337 }
1338
1339 template <class I, class P1, class P2, class P3, class P4, class P5, class P6,
1340 class P7, class P8, class P9>
Add(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7,P8 p8,P9 p9)1341 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) {
1342 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7, p8, p9));
1343 }
1344
1345 void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE);
1346
1347 // When initializing arrays, we'll unfold the loop if the number of elements
1348 // is known at compile time and is <= kElementLoopUnrollThreshold.
1349 static const int kElementLoopUnrollThreshold = 8;
1350
1351 protected:
1352 virtual bool BuildGraph() = 0;
1353
1354 HBasicBlock* CreateBasicBlock(HEnvironment* env);
1355 HBasicBlock* CreateLoopHeaderBlock();
1356
1357 template <class BitFieldClass>
BuildDecodeField(HValue * encoded_field)1358 HValue* BuildDecodeField(HValue* encoded_field) {
1359 HValue* mask_value = Add<HConstant>(static_cast<int>(BitFieldClass::kMask));
1360 HValue* masked_field =
1361 AddUncasted<HBitwise>(Token::BIT_AND, encoded_field, mask_value);
1362 return AddUncasted<HShr>(masked_field,
1363 Add<HConstant>(static_cast<int>(BitFieldClass::kShift)));
1364 }
1365
1366 HValue* BuildGetElementsKind(HValue* object);
1367
1368 HValue* BuildEnumLength(HValue* map);
1369
1370 HValue* BuildCheckHeapObject(HValue* object);
1371 HValue* BuildCheckString(HValue* string);
1372 HValue* BuildWrapReceiver(HValue* object, HValue* function);
1373
1374 // Building common constructs
1375 HValue* BuildCheckForCapacityGrow(HValue* object,
1376 HValue* elements,
1377 ElementsKind kind,
1378 HValue* length,
1379 HValue* key,
1380 bool is_js_array,
1381 PropertyAccessType access_type);
1382
1383 HValue* BuildCheckAndGrowElementsCapacity(HValue* object, HValue* elements,
1384 ElementsKind kind, HValue* length,
1385 HValue* capacity, HValue* key);
1386
1387 HValue* BuildCopyElementsOnWrite(HValue* object,
1388 HValue* elements,
1389 ElementsKind kind,
1390 HValue* length);
1391
1392 void BuildTransitionElementsKind(HValue* object,
1393 HValue* map,
1394 ElementsKind from_kind,
1395 ElementsKind to_kind,
1396 bool is_jsarray);
1397
1398 HValue* BuildNumberToString(HValue* object, Type* type);
1399 HValue* BuildToNumber(HValue* input);
1400 HValue* BuildToObject(HValue* receiver);
1401
1402 void BuildJSObjectCheck(HValue* receiver,
1403 int bit_field_mask);
1404
1405 // Checks a key value that's being used for a keyed element access context. If
1406 // the key is a index, i.e. a smi or a number in a unique string with a cached
1407 // numeric value, the "true" of the continuation is joined. Otherwise,
1408 // if the key is a name or a unique string, the "false" of the continuation is
1409 // joined. Otherwise, a deoptimization is triggered. In both paths of the
1410 // continuation, the key is pushed on the top of the environment.
1411 void BuildKeyedIndexCheck(HValue* key,
1412 HIfContinuation* join_continuation);
1413
1414 // Checks the properties of an object if they are in dictionary case, in which
1415 // case "true" of continuation is taken, otherwise the "false"
1416 void BuildTestForDictionaryProperties(HValue* object,
1417 HIfContinuation* continuation);
1418
1419 void BuildNonGlobalObjectCheck(HValue* receiver);
1420
1421 HValue* BuildKeyedLookupCacheHash(HValue* object,
1422 HValue* key);
1423
1424 HValue* BuildUncheckedDictionaryElementLoad(HValue* receiver,
1425 HValue* elements, HValue* key,
1426 HValue* hash);
1427
1428 // ES6 section 7.4.7 CreateIterResultObject ( value, done )
1429 HValue* BuildCreateIterResultObject(HValue* value, HValue* done);
1430
1431 HValue* BuildRegExpConstructResult(HValue* length,
1432 HValue* index,
1433 HValue* input);
1434
1435 // Allocates a new object according with the given allocation properties.
1436 HAllocate* BuildAllocate(HValue* object_size,
1437 HType type,
1438 InstanceType instance_type,
1439 HAllocationMode allocation_mode);
1440 // Computes the sum of two string lengths, taking care of overflow handling.
1441 HValue* BuildAddStringLengths(HValue* left_length, HValue* right_length);
1442 // Creates a cons string using the two input strings.
1443 HValue* BuildCreateConsString(HValue* length,
1444 HValue* left,
1445 HValue* right,
1446 HAllocationMode allocation_mode);
1447 // Copies characters from one sequential string to another.
1448 void BuildCopySeqStringChars(HValue* src,
1449 HValue* src_offset,
1450 String::Encoding src_encoding,
1451 HValue* dst,
1452 HValue* dst_offset,
1453 String::Encoding dst_encoding,
1454 HValue* length);
1455
1456 // Align an object size to object alignment boundary
1457 HValue* BuildObjectSizeAlignment(HValue* unaligned_size, int header_size);
1458
1459 // Both operands are non-empty strings.
1460 HValue* BuildUncheckedStringAdd(HValue* left,
1461 HValue* right,
1462 HAllocationMode allocation_mode);
1463 // Add two strings using allocation mode, validating type feedback.
1464 HValue* BuildStringAdd(HValue* left,
1465 HValue* right,
1466 HAllocationMode allocation_mode);
1467
1468 HInstruction* BuildUncheckedMonomorphicElementAccess(
1469 HValue* checked_object,
1470 HValue* key,
1471 HValue* val,
1472 bool is_js_array,
1473 ElementsKind elements_kind,
1474 PropertyAccessType access_type,
1475 LoadKeyedHoleMode load_mode,
1476 KeyedAccessStoreMode store_mode);
1477
1478 HInstruction* AddElementAccess(
1479 HValue* elements, HValue* checked_key, HValue* val, HValue* dependency,
1480 HValue* backing_store_owner, ElementsKind elements_kind,
1481 PropertyAccessType access_type,
1482 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE);
1483
1484 HInstruction* AddLoadStringInstanceType(HValue* string);
1485 HInstruction* AddLoadStringLength(HValue* string);
1486 HInstruction* BuildLoadStringLength(HValue* string);
AddStoreMapConstant(HValue * object,Handle<Map> map)1487 HStoreNamedField* AddStoreMapConstant(HValue* object, Handle<Map> map) {
1488 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(),
1489 Add<HConstant>(map));
1490 }
1491 HLoadNamedField* AddLoadMap(HValue* object,
1492 HValue* dependency = NULL);
1493 HLoadNamedField* AddLoadElements(HValue* object,
1494 HValue* dependency = NULL);
1495
1496 bool MatchRotateRight(HValue* left,
1497 HValue* right,
1498 HValue** operand,
1499 HValue** shift_amount);
1500
1501 HValue* BuildBinaryOperation(Token::Value op, HValue* left, HValue* right,
1502 Type* left_type, Type* right_type,
1503 Type* result_type, Maybe<int> fixed_right_arg,
1504 HAllocationMode allocation_mode,
1505 BailoutId opt_id = BailoutId::None());
1506
1507 HLoadNamedField* AddLoadFixedArrayLength(HValue *object,
1508 HValue *dependency = NULL);
1509
1510 HLoadNamedField* AddLoadArrayLength(HValue *object,
1511 ElementsKind kind,
1512 HValue *dependency = NULL);
1513
1514 HValue* AddLoadJSBuiltin(int context_index);
1515
1516 HValue* EnforceNumberType(HValue* number, Type* expected);
1517 HValue* TruncateToNumber(HValue* value, Type** expected);
1518
1519 void FinishExitWithHardDeoptimization(Deoptimizer::DeoptReason reason);
1520
1521 void AddIncrementCounter(StatsCounter* counter);
1522
1523 class IfBuilder final {
1524 public:
1525 // If using this constructor, Initialize() must be called explicitly!
1526 IfBuilder();
1527
1528 explicit IfBuilder(HGraphBuilder* builder);
1529 IfBuilder(HGraphBuilder* builder,
1530 HIfContinuation* continuation);
1531
~IfBuilder()1532 ~IfBuilder() {
1533 if (!finished_) End();
1534 }
1535
1536 void Initialize(HGraphBuilder* builder);
1537
1538 template<class Condition>
If(HValue * p)1539 Condition* If(HValue *p) {
1540 Condition* compare = builder()->New<Condition>(p);
1541 AddCompare(compare);
1542 return compare;
1543 }
1544
1545 template<class Condition, class P2>
If(HValue * p1,P2 p2)1546 Condition* If(HValue* p1, P2 p2) {
1547 Condition* compare = builder()->New<Condition>(p1, p2);
1548 AddCompare(compare);
1549 return compare;
1550 }
1551
1552 template<class Condition, class P2, class P3>
If(HValue * p1,P2 p2,P3 p3)1553 Condition* If(HValue* p1, P2 p2, P3 p3) {
1554 Condition* compare = builder()->New<Condition>(p1, p2, p3);
1555 AddCompare(compare);
1556 return compare;
1557 }
1558
1559 template<class Condition>
IfNot(HValue * p)1560 Condition* IfNot(HValue* p) {
1561 Condition* compare = If<Condition>(p);
1562 compare->Not();
1563 return compare;
1564 }
1565
1566 template<class Condition, class P2>
IfNot(HValue * p1,P2 p2)1567 Condition* IfNot(HValue* p1, P2 p2) {
1568 Condition* compare = If<Condition>(p1, p2);
1569 compare->Not();
1570 return compare;
1571 }
1572
1573 template<class Condition, class P2, class P3>
IfNot(HValue * p1,P2 p2,P3 p3)1574 Condition* IfNot(HValue* p1, P2 p2, P3 p3) {
1575 Condition* compare = If<Condition>(p1, p2, p3);
1576 compare->Not();
1577 return compare;
1578 }
1579
1580 template<class Condition>
OrIf(HValue * p)1581 Condition* OrIf(HValue *p) {
1582 Or();
1583 return If<Condition>(p);
1584 }
1585
1586 template<class Condition, class P2>
OrIf(HValue * p1,P2 p2)1587 Condition* OrIf(HValue* p1, P2 p2) {
1588 Or();
1589 return If<Condition>(p1, p2);
1590 }
1591
1592 template<class Condition, class P2, class P3>
OrIf(HValue * p1,P2 p2,P3 p3)1593 Condition* OrIf(HValue* p1, P2 p2, P3 p3) {
1594 Or();
1595 return If<Condition>(p1, p2, p3);
1596 }
1597
1598 template<class Condition>
AndIf(HValue * p)1599 Condition* AndIf(HValue *p) {
1600 And();
1601 return If<Condition>(p);
1602 }
1603
1604 template<class Condition, class P2>
AndIf(HValue * p1,P2 p2)1605 Condition* AndIf(HValue* p1, P2 p2) {
1606 And();
1607 return If<Condition>(p1, p2);
1608 }
1609
1610 template<class Condition, class P2, class P3>
AndIf(HValue * p1,P2 p2,P3 p3)1611 Condition* AndIf(HValue* p1, P2 p2, P3 p3) {
1612 And();
1613 return If<Condition>(p1, p2, p3);
1614 }
1615
1616 void Or();
1617 void And();
1618
1619 // Captures the current state of this IfBuilder in the specified
1620 // continuation and ends this IfBuilder.
1621 void CaptureContinuation(HIfContinuation* continuation);
1622
1623 // Joins the specified continuation from this IfBuilder and ends this
1624 // IfBuilder. This appends a Goto instruction from the true branch of
1625 // this IfBuilder to the true branch of the continuation unless the
1626 // true branch of this IfBuilder is already finished. And vice versa
1627 // for the false branch.
1628 //
1629 // The basic idea is as follows: You have several nested IfBuilder's
1630 // that you want to join based on two possible outcomes (i.e. success
1631 // and failure, or whatever). You can do this easily using this method
1632 // now, for example:
1633 //
1634 // HIfContinuation cont(graph()->CreateBasicBlock(),
1635 // graph()->CreateBasicBlock());
1636 // ...
1637 // IfBuilder if_whatever(this);
1638 // if_whatever.If<Condition>(arg);
1639 // if_whatever.Then();
1640 // ...
1641 // if_whatever.Else();
1642 // ...
1643 // if_whatever.JoinContinuation(&cont);
1644 // ...
1645 // IfBuilder if_something(this);
1646 // if_something.If<Condition>(arg1, arg2);
1647 // if_something.Then();
1648 // ...
1649 // if_something.Else();
1650 // ...
1651 // if_something.JoinContinuation(&cont);
1652 // ...
1653 // IfBuilder if_finally(this, &cont);
1654 // if_finally.Then();
1655 // // continues after then code of if_whatever or if_something.
1656 // ...
1657 // if_finally.Else();
1658 // // continues after else code of if_whatever or if_something.
1659 // ...
1660 // if_finally.End();
1661 void JoinContinuation(HIfContinuation* continuation);
1662
1663 void Then();
1664 void Else();
1665 void End();
1666 void EndUnreachable();
1667
1668 void Deopt(Deoptimizer::DeoptReason reason);
ThenDeopt(Deoptimizer::DeoptReason reason)1669 void ThenDeopt(Deoptimizer::DeoptReason reason) {
1670 Then();
1671 Deopt(reason);
1672 }
ElseDeopt(Deoptimizer::DeoptReason reason)1673 void ElseDeopt(Deoptimizer::DeoptReason reason) {
1674 Else();
1675 Deopt(reason);
1676 }
1677
1678 void Return(HValue* value);
1679
1680 private:
1681 void InitializeDontCreateBlocks(HGraphBuilder* builder);
1682
1683 HControlInstruction* AddCompare(HControlInstruction* compare);
1684
builder()1685 HGraphBuilder* builder() const {
1686 DCHECK(builder_ != NULL); // Have you called "Initialize"?
1687 return builder_;
1688 }
1689
1690 void AddMergeAtJoinBlock(bool deopt);
1691
1692 void Finish();
1693 void Finish(HBasicBlock** then_continuation,
1694 HBasicBlock** else_continuation);
1695
1696 class MergeAtJoinBlock : public ZoneObject {
1697 public:
MergeAtJoinBlock(HBasicBlock * block,bool deopt,MergeAtJoinBlock * next)1698 MergeAtJoinBlock(HBasicBlock* block,
1699 bool deopt,
1700 MergeAtJoinBlock* next)
1701 : block_(block),
1702 deopt_(deopt),
1703 next_(next) {}
1704 HBasicBlock* block_;
1705 bool deopt_;
1706 MergeAtJoinBlock* next_;
1707 };
1708
1709 HGraphBuilder* builder_;
1710 bool finished_ : 1;
1711 bool did_then_ : 1;
1712 bool did_else_ : 1;
1713 bool did_else_if_ : 1;
1714 bool did_and_ : 1;
1715 bool did_or_ : 1;
1716 bool captured_ : 1;
1717 bool needs_compare_ : 1;
1718 bool pending_merge_block_ : 1;
1719 HBasicBlock* first_true_block_;
1720 HBasicBlock* first_false_block_;
1721 HBasicBlock* split_edge_merge_block_;
1722 MergeAtJoinBlock* merge_at_join_blocks_;
1723 int normal_merge_at_join_block_count_;
1724 int deopt_merge_at_join_block_count_;
1725 };
1726
1727 class LoopBuilder final {
1728 public:
1729 enum Direction {
1730 kPreIncrement,
1731 kPostIncrement,
1732 kPreDecrement,
1733 kPostDecrement,
1734 kWhileTrue
1735 };
1736
1737 explicit LoopBuilder(HGraphBuilder* builder); // while (true) {...}
1738 LoopBuilder(HGraphBuilder* builder,
1739 HValue* context,
1740 Direction direction);
1741 LoopBuilder(HGraphBuilder* builder,
1742 HValue* context,
1743 Direction direction,
1744 HValue* increment_amount);
1745
~LoopBuilder()1746 ~LoopBuilder() {
1747 DCHECK(finished_);
1748 }
1749
1750 HValue* BeginBody(
1751 HValue* initial,
1752 HValue* terminating,
1753 Token::Value token);
1754
1755 void BeginBody(int drop_count);
1756
1757 void Break();
1758
1759 void EndBody();
1760
1761 private:
1762 void Initialize(HGraphBuilder* builder, HValue* context,
1763 Direction direction, HValue* increment_amount);
zone()1764 Zone* zone() { return builder_->zone(); }
1765
1766 HGraphBuilder* builder_;
1767 HValue* context_;
1768 HValue* increment_amount_;
1769 HInstruction* increment_;
1770 HPhi* phi_;
1771 HBasicBlock* header_block_;
1772 HBasicBlock* body_block_;
1773 HBasicBlock* exit_block_;
1774 HBasicBlock* exit_trampoline_block_;
1775 Direction direction_;
1776 bool finished_;
1777 };
1778
1779 HValue* BuildNewElementsCapacity(HValue* old_capacity);
1780
1781 class JSArrayBuilder final {
1782 public:
1783 JSArrayBuilder(HGraphBuilder* builder,
1784 ElementsKind kind,
1785 HValue* allocation_site_payload,
1786 HValue* constructor_function,
1787 AllocationSiteOverrideMode override_mode);
1788
1789 JSArrayBuilder(HGraphBuilder* builder,
1790 ElementsKind kind,
1791 HValue* constructor_function = NULL);
1792
1793 enum FillMode {
1794 DONT_FILL_WITH_HOLE,
1795 FILL_WITH_HOLE
1796 };
1797
kind()1798 ElementsKind kind() { return kind_; }
elements_location()1799 HAllocate* elements_location() { return elements_location_; }
1800
1801 HAllocate* AllocateEmptyArray();
1802 HAllocate* AllocateArray(HValue* capacity,
1803 HValue* length_field,
1804 FillMode fill_mode = FILL_WITH_HOLE);
GetElementsLocation()1805 HValue* GetElementsLocation() { return elements_location_; }
1806 HValue* EmitMapCode();
1807
1808 private:
zone()1809 Zone* zone() const { return builder_->zone(); }
elements_size()1810 int elements_size() const {
1811 return IsFastDoubleElementsKind(kind_) ? kDoubleSize : kPointerSize;
1812 }
builder()1813 HGraphBuilder* builder() { return builder_; }
graph()1814 HGraph* graph() { return builder_->graph(); }
initial_capacity()1815 int initial_capacity() {
1816 STATIC_ASSERT(JSArray::kPreallocatedArrayElements > 0);
1817 return JSArray::kPreallocatedArrayElements;
1818 }
1819
1820 HValue* EmitInternalMapCode();
1821
1822 HGraphBuilder* builder_;
1823 ElementsKind kind_;
1824 AllocationSiteMode mode_;
1825 HValue* allocation_site_payload_;
1826 HValue* constructor_function_;
1827 HAllocate* elements_location_;
1828 };
1829
1830 HValue* BuildAllocateArrayFromLength(JSArrayBuilder* array_builder,
1831 HValue* length_argument);
1832 HValue* BuildCalculateElementsSize(ElementsKind kind,
1833 HValue* capacity);
1834 HAllocate* AllocateJSArrayObject(AllocationSiteMode mode);
1835 HConstant* EstablishElementsAllocationSize(ElementsKind kind, int capacity);
1836
1837 HAllocate* BuildAllocateElements(ElementsKind kind, HValue* size_in_bytes);
1838
1839 void BuildInitializeElementsHeader(HValue* elements,
1840 ElementsKind kind,
1841 HValue* capacity);
1842
1843 // Build allocation and header initialization code for respective successor
1844 // of FixedArrayBase.
1845 HValue* BuildAllocateAndInitializeArray(ElementsKind kind, HValue* capacity);
1846
1847 // |array| must have been allocated with enough room for
1848 // 1) the JSArray and 2) an AllocationMemento if mode requires it.
1849 // If the |elements| value provided is NULL then the array elements storage
1850 // is initialized with empty array.
1851 void BuildJSArrayHeader(HValue* array,
1852 HValue* array_map,
1853 HValue* elements,
1854 AllocationSiteMode mode,
1855 ElementsKind elements_kind,
1856 HValue* allocation_site_payload,
1857 HValue* length_field);
1858
1859 HValue* BuildGrowElementsCapacity(HValue* object,
1860 HValue* elements,
1861 ElementsKind kind,
1862 ElementsKind new_kind,
1863 HValue* length,
1864 HValue* new_capacity);
1865
1866 void BuildFillElementsWithValue(HValue* elements,
1867 ElementsKind elements_kind,
1868 HValue* from,
1869 HValue* to,
1870 HValue* value);
1871
1872 void BuildFillElementsWithHole(HValue* elements,
1873 ElementsKind elements_kind,
1874 HValue* from,
1875 HValue* to);
1876
1877 void BuildCopyProperties(HValue* from_properties, HValue* to_properties,
1878 HValue* length, HValue* capacity);
1879
1880 void BuildCopyElements(HValue* from_elements,
1881 ElementsKind from_elements_kind,
1882 HValue* to_elements,
1883 ElementsKind to_elements_kind,
1884 HValue* length,
1885 HValue* capacity);
1886
1887 HValue* BuildCloneShallowArrayCow(HValue* boilerplate,
1888 HValue* allocation_site,
1889 AllocationSiteMode mode,
1890 ElementsKind kind);
1891
1892 HValue* BuildCloneShallowArrayEmpty(HValue* boilerplate,
1893 HValue* allocation_site,
1894 AllocationSiteMode mode);
1895
1896 HValue* BuildCloneShallowArrayNonEmpty(HValue* boilerplate,
1897 HValue* allocation_site,
1898 AllocationSiteMode mode,
1899 ElementsKind kind);
1900
1901 HValue* BuildElementIndexHash(HValue* index);
1902
1903 void BuildCreateAllocationMemento(HValue* previous_object,
1904 HValue* previous_object_size,
1905 HValue* payload);
1906
1907 HInstruction* BuildConstantMapCheck(Handle<JSObject> constant);
1908 HInstruction* BuildCheckPrototypeMaps(Handle<JSObject> prototype,
1909 Handle<JSObject> holder);
1910
1911 HInstruction* BuildGetNativeContext(HValue* closure);
1912 HInstruction* BuildGetNativeContext();
1913 HInstruction* BuildGetScriptContext(int context_index);
1914 // Builds a loop version if |depth| is specified or unrolls the loop to
1915 // |depth_value| iterations otherwise.
1916 HValue* BuildGetParentContext(HValue* depth, int depth_value);
1917
1918 HInstruction* BuildGetArrayFunction();
1919 HValue* BuildArrayBufferViewFieldAccessor(HValue* object,
1920 HValue* checked_object,
1921 FieldIndex index);
1922
1923
1924 protected:
SetSourcePosition(int position)1925 void SetSourcePosition(int position) {
1926 if (position != RelocInfo::kNoPosition) {
1927 position_.set_position(position - start_position_);
1928 }
1929 // Otherwise position remains unknown.
1930 }
1931
EnterInlinedSource(int start_position,int id)1932 void EnterInlinedSource(int start_position, int id) {
1933 if (top_info()->is_tracking_positions()) {
1934 start_position_ = start_position;
1935 position_.set_inlining_id(id);
1936 }
1937 }
1938
1939 // Convert the given absolute offset from the start of the script to
1940 // the SourcePosition assuming that this position corresponds to the
1941 // same function as current position_.
ScriptPositionToSourcePosition(int position)1942 SourcePosition ScriptPositionToSourcePosition(int position) {
1943 if (position == RelocInfo::kNoPosition) {
1944 return SourcePosition::Unknown();
1945 }
1946 SourcePosition pos = position_;
1947 pos.set_position(position - start_position_);
1948 return pos;
1949 }
1950
source_position()1951 SourcePosition source_position() { return position_; }
set_source_position(SourcePosition position)1952 void set_source_position(SourcePosition position) { position_ = position; }
1953
1954 int TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
1955 SourcePosition position);
1956
1957 HValue* BuildAllocateEmptyArrayBuffer(HValue* byte_length);
1958 template <typename ViewClass>
1959 void BuildArrayBufferViewInitialization(HValue* obj,
1960 HValue* buffer,
1961 HValue* byte_offset,
1962 HValue* byte_length);
1963
1964 private:
1965 HGraphBuilder();
1966
1967 template <class I>
AddInstructionTyped(I * instr)1968 I* AddInstructionTyped(I* instr) {
1969 return I::cast(AddInstruction(instr));
1970 }
1971
1972 CompilationInfo* info_;
1973 CallInterfaceDescriptor descriptor_;
1974 HGraph* graph_;
1975 HBasicBlock* current_block_;
1976 Scope* scope_;
1977 SourcePosition position_;
1978 int start_position_;
1979 };
1980
1981
1982 template <>
1983 inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>(
1984 Deoptimizer::DeoptReason reason, Deoptimizer::BailoutType type) {
1985 if (type == Deoptimizer::SOFT) {
1986 isolate()->counters()->soft_deopts_requested()->Increment();
1987 if (FLAG_always_opt) return NULL;
1988 }
1989 if (current_block()->IsDeoptimizing()) return NULL;
1990 HBasicBlock* after_deopt_block = CreateBasicBlock(
1991 current_block()->last_environment());
1992 HDeoptimize* instr = New<HDeoptimize>(reason, type, after_deopt_block);
1993 if (type == Deoptimizer::SOFT) {
1994 isolate()->counters()->soft_deopts_inserted()->Increment();
1995 }
1996 FinishCurrentBlock(instr);
1997 set_current_block(after_deopt_block);
1998 return instr;
1999 }
2000
2001
2002 template <>
2003 inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>(
2004 Deoptimizer::DeoptReason reason, Deoptimizer::BailoutType type) {
2005 return Add<HDeoptimize>(reason, type);
2006 }
2007
2008
2009 template<>
2010 inline HSimulate* HGraphBuilder::Add<HSimulate>(
2011 BailoutId id,
2012 RemovableSimulate removable) {
2013 HSimulate* instr = current_block()->CreateSimulate(id, removable);
2014 AddInstruction(instr);
2015 return instr;
2016 }
2017
2018
2019 template<>
2020 inline HSimulate* HGraphBuilder::Add<HSimulate>(
2021 BailoutId id) {
2022 return Add<HSimulate>(id, FIXED_SIMULATE);
2023 }
2024
2025
2026 template<>
2027 inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(BailoutId id) {
2028 return Add<HSimulate>(id, FIXED_SIMULATE);
2029 }
2030
2031
2032 template<>
2033 inline HReturn* HGraphBuilder::Add<HReturn>(HValue* value) {
2034 int num_parameters = graph()->info()->num_parameters();
2035 HValue* params = AddUncasted<HConstant>(num_parameters);
2036 HReturn* return_instruction = New<HReturn>(value, params);
2037 FinishExitCurrentBlock(return_instruction);
2038 return return_instruction;
2039 }
2040
2041
2042 template<>
2043 inline HReturn* HGraphBuilder::Add<HReturn>(HConstant* value) {
2044 return Add<HReturn>(static_cast<HValue*>(value));
2045 }
2046
2047 template<>
2048 inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HValue* value) {
2049 return Add<HReturn>(value);
2050 }
2051
2052
2053 template<>
2054 inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HConstant* value) {
2055 return Add<HReturn>(value);
2056 }
2057
2058
2059 template<>
2060 inline HCallRuntime* HGraphBuilder::Add<HCallRuntime>(
2061 const Runtime::Function* c_function,
2062 int argument_count) {
2063 HCallRuntime* instr = New<HCallRuntime>(c_function, argument_count);
2064 if (graph()->info()->IsStub()) {
2065 // When compiling code stubs, we don't want to save all double registers
2066 // upon entry to the stub, but instead have the call runtime instruction
2067 // save the double registers only on-demand (in the fallback case).
2068 instr->set_save_doubles(kSaveFPRegs);
2069 }
2070 AddInstruction(instr);
2071 return instr;
2072 }
2073
2074
2075 template<>
2076 inline HInstruction* HGraphBuilder::AddUncasted<HCallRuntime>(
2077 Handle<String> name,
2078 const Runtime::Function* c_function,
2079 int argument_count) {
2080 return Add<HCallRuntime>(c_function, argument_count);
2081 }
2082
2083
2084 template <>
2085 inline HParameter* HGraphBuilder::New<HParameter>(unsigned index) {
2086 return HParameter::New(isolate(), zone(), nullptr, index);
2087 }
2088
2089
2090 template <>
2091 inline HParameter* HGraphBuilder::New<HParameter>(
2092 unsigned index, HParameter::ParameterKind kind) {
2093 return HParameter::New(isolate(), zone(), nullptr, index, kind);
2094 }
2095
2096
2097 template <>
2098 inline HParameter* HGraphBuilder::New<HParameter>(
2099 unsigned index, HParameter::ParameterKind kind, Representation r) {
2100 return HParameter::New(isolate(), zone(), nullptr, index, kind, r);
2101 }
2102
2103
2104 template <>
2105 inline HPrologue* HGraphBuilder::New<HPrologue>() {
2106 return HPrologue::New(zone());
2107 }
2108
2109
2110 template <>
2111 inline HContext* HGraphBuilder::New<HContext>() {
2112 return HContext::New(zone());
2113 }
2114
2115
2116 class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
2117 public:
2118 // A class encapsulating (lazily-allocated) break and continue blocks for
2119 // a breakable statement. Separated from BreakAndContinueScope so that it
2120 // can have a separate lifetime.
2121 class BreakAndContinueInfo final BASE_EMBEDDED {
2122 public:
2123 explicit BreakAndContinueInfo(BreakableStatement* target,
2124 Scope* scope,
2125 int drop_extra = 0)
target_(target)2126 : target_(target),
2127 break_block_(NULL),
2128 continue_block_(NULL),
2129 scope_(scope),
2130 drop_extra_(drop_extra) {
2131 }
2132
target()2133 BreakableStatement* target() { return target_; }
break_block()2134 HBasicBlock* break_block() { return break_block_; }
set_break_block(HBasicBlock * block)2135 void set_break_block(HBasicBlock* block) { break_block_ = block; }
continue_block()2136 HBasicBlock* continue_block() { return continue_block_; }
set_continue_block(HBasicBlock * block)2137 void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
scope()2138 Scope* scope() { return scope_; }
drop_extra()2139 int drop_extra() { return drop_extra_; }
2140
2141 private:
2142 BreakableStatement* target_;
2143 HBasicBlock* break_block_;
2144 HBasicBlock* continue_block_;
2145 Scope* scope_;
2146 int drop_extra_;
2147 };
2148
2149 // A helper class to maintain a stack of current BreakAndContinueInfo
2150 // structures mirroring BreakableStatement nesting.
2151 class BreakAndContinueScope final BASE_EMBEDDED {
2152 public:
BreakAndContinueScope(BreakAndContinueInfo * info,HOptimizedGraphBuilder * owner)2153 BreakAndContinueScope(BreakAndContinueInfo* info,
2154 HOptimizedGraphBuilder* owner)
2155 : info_(info), owner_(owner), next_(owner->break_scope()) {
2156 owner->set_break_scope(this);
2157 }
2158
~BreakAndContinueScope()2159 ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
2160
info()2161 BreakAndContinueInfo* info() { return info_; }
owner()2162 HOptimizedGraphBuilder* owner() { return owner_; }
next()2163 BreakAndContinueScope* next() { return next_; }
2164
2165 // Search the break stack for a break or continue target.
2166 enum BreakType { BREAK, CONTINUE };
2167 HBasicBlock* Get(BreakableStatement* stmt, BreakType type,
2168 Scope** scope, int* drop_extra);
2169
2170 private:
2171 BreakAndContinueInfo* info_;
2172 HOptimizedGraphBuilder* owner_;
2173 BreakAndContinueScope* next_;
2174 };
2175
2176 explicit HOptimizedGraphBuilder(CompilationInfo* info);
2177
2178 bool BuildGraph() override;
2179
2180 // Simple accessors.
break_scope()2181 BreakAndContinueScope* break_scope() const { return break_scope_; }
set_break_scope(BreakAndContinueScope * head)2182 void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
2183
context()2184 HValue* context() override { return environment()->context(); }
2185
osr()2186 HOsrBuilder* osr() const { return osr_; }
2187
2188 void Bailout(BailoutReason reason);
2189
2190 HBasicBlock* CreateJoin(HBasicBlock* first,
2191 HBasicBlock* second,
2192 BailoutId join_id);
2193
function_state()2194 FunctionState* function_state() const { return function_state_; }
2195
2196 void VisitDeclarations(ZoneList<Declaration*>* declarations) override;
2197
bounds()2198 AstTypeBounds* bounds() { return &bounds_; }
2199
new(size_t size,Zone * zone)2200 void* operator new(size_t size, Zone* zone) { return zone->New(size); }
delete(void * pointer,Zone * zone)2201 void operator delete(void* pointer, Zone* zone) { }
delete(void * pointer)2202 void operator delete(void* pointer) { }
2203
2204 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
2205
2206 protected:
2207 // Forward declarations for inner scope classes.
2208 class SubgraphScope;
2209
2210 static const int kMaxCallPolymorphism = 4;
2211 static const int kMaxLoadPolymorphism = 4;
2212 static const int kMaxStorePolymorphism = 4;
2213
2214 // Even in the 'unlimited' case we have to have some limit in order not to
2215 // overflow the stack.
2216 static const int kUnlimitedMaxInlinedSourceSize = 100000;
2217 static const int kUnlimitedMaxInlinedNodes = 10000;
2218 static const int kUnlimitedMaxInlinedNodesCumulative = 10000;
2219
2220 // Maximum depth and total number of elements and properties for literal
2221 // graphs to be considered for fast deep-copying.
2222 static const int kMaxFastLiteralDepth = 3;
2223 static const int kMaxFastLiteralProperties = 8;
2224
2225 // Simple accessors.
set_function_state(FunctionState * state)2226 void set_function_state(FunctionState* state) { function_state_ = state; }
2227
ast_context()2228 AstContext* ast_context() const { return ast_context_; }
set_ast_context(AstContext * context)2229 void set_ast_context(AstContext* context) { ast_context_ = context; }
2230
2231 // Accessors forwarded to the function state.
current_info()2232 CompilationInfo* current_info() const {
2233 return function_state()->compilation_info();
2234 }
call_context()2235 AstContext* call_context() const {
2236 return function_state()->call_context();
2237 }
function_return()2238 HBasicBlock* function_return() const {
2239 return function_state()->function_return();
2240 }
inlined_test_context()2241 TestContext* inlined_test_context() const {
2242 return function_state()->test_context();
2243 }
current_closure()2244 Handle<JSFunction> current_closure() const {
2245 return current_info()->closure();
2246 }
current_shared_info()2247 Handle<SharedFunctionInfo> current_shared_info() const {
2248 return current_info()->shared_info();
2249 }
current_feedback_vector()2250 TypeFeedbackVector* current_feedback_vector() const {
2251 return current_closure()->feedback_vector();
2252 }
ClearInlinedTestContext()2253 void ClearInlinedTestContext() {
2254 function_state()->ClearInlinedTestContext();
2255 }
function_language_mode()2256 LanguageMode function_language_mode() {
2257 return function_state()->compilation_info()->parse_info()->language_mode();
2258 }
2259
2260 #define FOR_EACH_HYDROGEN_INTRINSIC(F) \
2261 F(IsSmi) \
2262 F(IsArray) \
2263 F(IsTypedArray) \
2264 F(IsRegExp) \
2265 F(IsJSProxy) \
2266 F(Call) \
2267 F(NewObject) \
2268 F(ValueOf) \
2269 F(StringCharFromCode) \
2270 F(ToInteger) \
2271 F(ToName) \
2272 F(ToObject) \
2273 F(ToString) \
2274 F(ToLength) \
2275 F(ToNumber) \
2276 F(IsJSReceiver) \
2277 F(MathPow) \
2278 F(HasCachedArrayIndex) \
2279 F(GetCachedArrayIndex) \
2280 F(DebugBreakInOptimizedCode) \
2281 F(StringCharCodeAt) \
2282 F(SubString) \
2283 F(RegExpExec) \
2284 F(RegExpConstructResult) \
2285 F(RegExpFlags) \
2286 F(RegExpSource) \
2287 F(NumberToString) \
2288 F(DebugIsActive) \
2289 /* Typed Arrays */ \
2290 F(TypedArrayInitialize) \
2291 F(MaxSmi) \
2292 F(TypedArrayMaxSizeInHeap) \
2293 F(ArrayBufferViewGetByteLength) \
2294 F(ArrayBufferViewGetByteOffset) \
2295 F(TypedArrayGetLength) \
2296 /* ArrayBuffer */ \
2297 F(ArrayBufferGetByteLength) \
2298 /* Maths */ \
2299 F(DoubleHi) \
2300 F(DoubleLo) \
2301 /* ES6 Collections */ \
2302 F(MapClear) \
2303 F(MapInitialize) \
2304 F(SetClear) \
2305 F(SetInitialize) \
2306 F(FixedArrayGet) \
2307 F(FixedArraySet) \
2308 F(JSCollectionGetTable) \
2309 F(StringGetRawHashField) \
2310 F(TheHole) \
2311 /* ES6 Iterators */ \
2312 F(CreateIterResultObject) \
2313 /* Arrays */ \
2314 F(HasFastPackedElements)
2315
2316 #define GENERATOR_DECLARATION(Name) void Generate##Name(CallRuntime* call);
2317 FOR_EACH_HYDROGEN_INTRINSIC(GENERATOR_DECLARATION)
2318 #undef GENERATOR_DECLARATION
2319
2320 void VisitDelete(UnaryOperation* expr);
2321 void VisitVoid(UnaryOperation* expr);
2322 void VisitTypeof(UnaryOperation* expr);
2323 void VisitNot(UnaryOperation* expr);
2324
2325 void VisitComma(BinaryOperation* expr);
2326 void VisitLogicalExpression(BinaryOperation* expr);
2327 void VisitArithmeticExpression(BinaryOperation* expr);
2328
2329 void VisitLoopBody(IterationStatement* stmt,
2330 HBasicBlock* loop_entry);
2331
2332 void BuildForInBody(ForInStatement* stmt, Variable* each_var,
2333 HValue* enumerable);
2334
2335 // Create a back edge in the flow graph. body_exit is the predecessor
2336 // block and loop_entry is the successor block. loop_successor is the
2337 // block where control flow exits the loop normally (e.g., via failure of
2338 // the condition) and break_block is the block where control flow breaks
2339 // from the loop. All blocks except loop_entry can be NULL. The return
2340 // value is the new successor block which is the join of loop_successor
2341 // and break_block, or NULL.
2342 HBasicBlock* CreateLoop(IterationStatement* statement,
2343 HBasicBlock* loop_entry,
2344 HBasicBlock* body_exit,
2345 HBasicBlock* loop_successor,
2346 HBasicBlock* break_block);
2347
2348 // Build a loop entry
2349 HBasicBlock* BuildLoopEntry();
2350
2351 // Builds a loop entry respectful of OSR requirements
2352 HBasicBlock* BuildLoopEntry(IterationStatement* statement);
2353
2354 HBasicBlock* JoinContinue(IterationStatement* statement,
2355 HBasicBlock* exit_block,
2356 HBasicBlock* continue_block);
2357
Top()2358 HValue* Top() const { return environment()->Top(); }
Drop(int n)2359 void Drop(int n) { environment()->Drop(n); }
Bind(Variable * var,HValue * value)2360 void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
IsEligibleForEnvironmentLivenessAnalysis(Variable * var,int index,HEnvironment * env)2361 bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var,
2362 int index,
2363 HEnvironment* env) {
2364 if (!FLAG_analyze_environment_liveness) return false;
2365 // |this| and |arguments| are always live; zapping parameters isn't
2366 // safe because function.arguments can inspect them at any time.
2367 return !var->is_this() &&
2368 !var->is_arguments() &&
2369 env->is_local_index(index);
2370 }
BindIfLive(Variable * var,HValue * value)2371 void BindIfLive(Variable* var, HValue* value) {
2372 HEnvironment* env = environment();
2373 int index = env->IndexFor(var);
2374 env->Bind(index, value);
2375 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, env)) {
2376 HEnvironmentMarker* bind =
2377 Add<HEnvironmentMarker>(HEnvironmentMarker::BIND, index);
2378 USE(bind);
2379 #ifdef DEBUG
2380 bind->set_closure(env->closure());
2381 #endif
2382 }
2383 }
LookupAndMakeLive(Variable * var)2384 HValue* LookupAndMakeLive(Variable* var) {
2385 HEnvironment* env = environment();
2386 int index = env->IndexFor(var);
2387 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, env)) {
2388 HEnvironmentMarker* lookup =
2389 Add<HEnvironmentMarker>(HEnvironmentMarker::LOOKUP, index);
2390 USE(lookup);
2391 #ifdef DEBUG
2392 lookup->set_closure(env->closure());
2393 #endif
2394 }
2395 return env->Lookup(index);
2396 }
2397
2398 // The value of the arguments object is allowed in some but not most value
2399 // contexts. (It's allowed in all effect contexts and disallowed in all
2400 // test contexts.)
2401 void VisitForValue(Expression* expr,
2402 ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
2403 void VisitForTypeOf(Expression* expr);
2404 void VisitForEffect(Expression* expr);
2405 void VisitForControl(Expression* expr,
2406 HBasicBlock* true_block,
2407 HBasicBlock* false_block);
2408
2409 // Visit a list of expressions from left to right, each in a value context.
2410 void VisitExpressions(ZoneList<Expression*>* exprs) override;
2411 void VisitExpressions(ZoneList<Expression*>* exprs,
2412 ArgumentsAllowedFlag flag);
2413
2414 // Remove the arguments from the bailout environment and emit instructions
2415 // to push them as outgoing parameters.
2416 template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
2417 void PushArgumentsFromEnvironment(int count);
2418
2419 void SetUpScope(Scope* scope);
2420 void VisitStatements(ZoneList<Statement*>* statements) override;
2421
2422 #define DECLARE_VISIT(type) void Visit##type(type* node) override;
2423 AST_NODE_LIST(DECLARE_VISIT)
2424 #undef DECLARE_VISIT
2425
2426 private:
2427 // Helpers for flow graph construction.
2428 enum GlobalPropertyAccess {
2429 kUseCell,
2430 kUseGeneric
2431 };
2432 GlobalPropertyAccess LookupGlobalProperty(Variable* var, LookupIterator* it,
2433 PropertyAccessType access_type);
2434
2435 void EnsureArgumentsArePushedForAccess();
2436 bool TryArgumentsAccess(Property* expr);
2437
2438 // Shared code for .call and .apply optimizations.
2439 void HandleIndirectCall(Call* expr, HValue* function, int arguments_count);
2440 // Try to optimize indirect calls such as fun.apply(receiver, arguments)
2441 // or fun.call(...).
2442 bool TryIndirectCall(Call* expr);
2443 void BuildFunctionApply(Call* expr);
2444 void BuildFunctionCall(Call* expr);
2445
2446 bool TryHandleArrayCall(Call* expr, HValue* function);
2447 bool TryHandleArrayCallNew(CallNew* expr, HValue* function);
2448 void BuildArrayCall(Expression* expr, int arguments_count, HValue* function,
2449 Handle<AllocationSite> cell);
2450
2451 enum ArrayIndexOfMode { kFirstIndexOf, kLastIndexOf };
2452 HValue* BuildArrayIndexOf(HValue* receiver,
2453 HValue* search_element,
2454 ElementsKind kind,
2455 ArrayIndexOfMode mode);
2456
2457 HValue* ImplicitReceiverFor(HValue* function,
2458 Handle<JSFunction> target);
2459
2460 int InliningAstSize(Handle<JSFunction> target);
2461 bool TryInline(Handle<JSFunction> target, int arguments_count,
2462 HValue* implicit_return_value, BailoutId ast_id,
2463 BailoutId return_id, InliningKind inlining_kind,
2464 TailCallMode syntactic_tail_call_mode);
2465
2466 bool TryInlineCall(Call* expr);
2467 bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value);
2468 bool TryInlineGetter(Handle<Object> getter, Handle<Map> receiver_map,
2469 BailoutId ast_id, BailoutId return_id);
2470 bool TryInlineSetter(Handle<Object> setter, Handle<Map> receiver_map,
2471 BailoutId id, BailoutId assignment_id,
2472 HValue* implicit_return_value);
2473 bool TryInlineIndirectCall(Handle<JSFunction> function, Call* expr,
2474 int arguments_count);
2475 bool TryInlineBuiltinGetterCall(Handle<JSFunction> function,
2476 Handle<Map> receiver_map, BailoutId ast_id);
2477 bool TryInlineBuiltinMethodCall(Handle<JSFunction> function,
2478 Handle<Map> receiver_map, BailoutId ast_id,
2479 int args_count_no_receiver);
2480 bool TryInlineBuiltinFunctionCall(Call* expr);
2481 enum ApiCallType {
2482 kCallApiFunction,
2483 kCallApiMethod,
2484 kCallApiGetter,
2485 kCallApiSetter
2486 };
2487 bool TryInlineApiMethodCall(Call* expr,
2488 HValue* receiver,
2489 SmallMapList* receiver_types);
2490 bool TryInlineApiFunctionCall(Call* expr, HValue* receiver);
2491 bool TryInlineApiGetter(Handle<Object> function, Handle<Map> receiver_map,
2492 BailoutId ast_id);
2493 bool TryInlineApiSetter(Handle<Object> function, Handle<Map> receiver_map,
2494 BailoutId ast_id);
2495 bool TryInlineApiCall(Handle<Object> function, HValue* receiver,
2496 SmallMapList* receiver_maps, int argc, BailoutId ast_id,
2497 ApiCallType call_type,
2498 TailCallMode syntactic_tail_call_mode);
2499 static bool IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map);
2500 static bool CanInlineArrayResizeOperation(Handle<Map> receiver_map);
2501
2502 // If --trace-inlining, print a line of the inlining trace. Inlining
2503 // succeeded if the reason string is NULL and failed if there is a
2504 // non-NULL reason string.
2505 void TraceInline(Handle<JSFunction> target, Handle<JSFunction> caller,
2506 const char* failure_reason,
2507 TailCallMode tail_call_mode = TailCallMode::kDisallow);
2508
2509 void HandleGlobalVariableAssignment(Variable* var, HValue* value,
2510 FeedbackVectorSlot slot,
2511 BailoutId ast_id);
2512
2513 void HandlePropertyAssignment(Assignment* expr);
2514 void HandleCompoundAssignment(Assignment* expr);
2515 void HandlePolymorphicNamedFieldAccess(
2516 PropertyAccessType access_type, Expression* expr, FeedbackVectorSlot slot,
2517 BailoutId ast_id, BailoutId return_id, HValue* object, HValue* value,
2518 SmallMapList* types, Handle<Name> name);
2519
2520 HValue* BuildAllocateExternalElements(
2521 ExternalArrayType array_type,
2522 bool is_zero_byte_offset,
2523 HValue* buffer, HValue* byte_offset, HValue* length);
2524 HValue* BuildAllocateFixedTypedArray(ExternalArrayType array_type,
2525 size_t element_size,
2526 ElementsKind fixed_elements_kind,
2527 HValue* byte_length, HValue* length,
2528 bool initialize);
2529
2530 // TODO(adamk): Move all OrderedHashTable functions to their own class.
2531 HValue* BuildOrderedHashTableHashToBucket(HValue* hash, HValue* num_buckets);
2532 template <typename CollectionType>
2533 HValue* BuildOrderedHashTableHashToEntry(HValue* table, HValue* hash,
2534 HValue* num_buckets);
2535 template <typename CollectionType>
2536 HValue* BuildOrderedHashTableEntryToIndex(HValue* entry, HValue* num_buckets);
2537 template <typename CollectionType>
2538 HValue* BuildOrderedHashTableFindEntry(HValue* table, HValue* key,
2539 HValue* hash);
2540 template <typename CollectionType>
2541 HValue* BuildOrderedHashTableAddEntry(HValue* table, HValue* key,
2542 HValue* hash,
2543 HIfContinuation* join_continuation);
2544 template <typename CollectionType>
2545 HValue* BuildAllocateOrderedHashTable();
2546 template <typename CollectionType>
2547 void BuildOrderedHashTableClear(HValue* receiver);
2548 template <typename CollectionType>
2549 void BuildJSCollectionDelete(CallRuntime* call,
2550 const Runtime::Function* c_function);
2551 template <typename CollectionType>
2552 void BuildJSCollectionHas(CallRuntime* call,
2553 const Runtime::Function* c_function);
2554 HValue* BuildStringHashLoadIfIsStringAndHashComputed(
2555 HValue* object, HIfContinuation* continuation);
2556
array_function()2557 Handle<JSFunction> array_function() {
2558 return handle(isolate()->native_context()->array_function());
2559 }
2560
2561 bool IsCallArrayInlineable(int argument_count, Handle<AllocationSite> site);
2562 void BuildInlinedCallArray(Expression* expression, int argument_count,
2563 Handle<AllocationSite> site);
2564
2565 void BuildInitializeInobjectProperties(HValue* receiver,
2566 Handle<Map> initial_map);
2567
2568 class PropertyAccessInfo {
2569 public:
PropertyAccessInfo(HOptimizedGraphBuilder * builder,PropertyAccessType access_type,Handle<Map> map,Handle<Name> name)2570 PropertyAccessInfo(HOptimizedGraphBuilder* builder,
2571 PropertyAccessType access_type, Handle<Map> map,
2572 Handle<Name> name)
2573 : builder_(builder),
2574 access_type_(access_type),
2575 map_(map),
2576 name_(isolate()->factory()->InternalizeName(name)),
2577 field_type_(HType::Tagged()),
2578 access_(HObjectAccess::ForMap()),
2579 lookup_type_(NOT_FOUND),
2580 details_(NONE, DATA, Representation::None()) {}
2581
2582 // Checkes whether this PropertyAccessInfo can be handled as a monomorphic
2583 // load named. It additionally fills in the fields necessary to generate the
2584 // lookup code.
2585 bool CanAccessMonomorphic();
2586
2587 // Checks whether all types behave uniform when loading name. If all maps
2588 // behave the same, a single monomorphic load instruction can be emitted,
2589 // guarded by a single map-checks instruction that whether the receiver is
2590 // an instance of any of the types.
2591 // This method skips the first type in types, assuming that this
2592 // PropertyAccessInfo is built for types->first().
2593 bool CanAccessAsMonomorphic(SmallMapList* types);
2594
2595 bool NeedsWrappingFor(Handle<JSFunction> target) const;
2596
2597 Handle<Map> map();
name()2598 Handle<Name> name() const { return name_; }
2599
IsJSObjectFieldAccessor()2600 bool IsJSObjectFieldAccessor() {
2601 int offset; // unused
2602 return Accessors::IsJSObjectFieldAccessor(map_, name_, &offset);
2603 }
2604
GetJSObjectFieldAccess(HObjectAccess * access)2605 bool GetJSObjectFieldAccess(HObjectAccess* access) {
2606 int offset;
2607 if (Accessors::IsJSObjectFieldAccessor(map_, name_, &offset)) {
2608 if (IsStringType()) {
2609 DCHECK(Name::Equals(isolate()->factory()->length_string(), name_));
2610 *access = HObjectAccess::ForStringLength();
2611 } else if (IsArrayType()) {
2612 DCHECK(Name::Equals(isolate()->factory()->length_string(), name_));
2613 *access = HObjectAccess::ForArrayLength(map_->elements_kind());
2614 } else {
2615 *access = HObjectAccess::ForMapAndOffset(map_, offset);
2616 }
2617 return true;
2618 }
2619 return false;
2620 }
2621
has_holder()2622 bool has_holder() { return !holder_.is_null(); }
IsLoad()2623 bool IsLoad() const { return access_type_ == LOAD; }
2624
isolate()2625 Isolate* isolate() const { return builder_->isolate(); }
holder()2626 Handle<JSObject> holder() { return holder_; }
accessor()2627 Handle<Object> accessor() { return accessor_; }
constant()2628 Handle<Object> constant() { return constant_; }
transition()2629 Handle<Map> transition() { return transition_; }
field_maps()2630 SmallMapList* field_maps() { return &field_maps_; }
field_type()2631 HType field_type() const { return field_type_; }
access()2632 HObjectAccess access() { return access_; }
2633
IsFound()2634 bool IsFound() const { return lookup_type_ != NOT_FOUND; }
IsProperty()2635 bool IsProperty() const { return IsFound() && !IsTransition(); }
IsTransition()2636 bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; }
IsData()2637 bool IsData() const {
2638 return lookup_type_ == DESCRIPTOR_TYPE && details_.type() == DATA;
2639 }
IsDataConstant()2640 bool IsDataConstant() const {
2641 return lookup_type_ == DESCRIPTOR_TYPE &&
2642 details_.type() == DATA_CONSTANT;
2643 }
IsAccessorConstant()2644 bool IsAccessorConstant() const {
2645 return !IsTransition() && details_.type() == ACCESSOR_CONSTANT;
2646 }
IsConfigurable()2647 bool IsConfigurable() const { return details_.IsConfigurable(); }
IsReadOnly()2648 bool IsReadOnly() const { return details_.IsReadOnly(); }
2649
IsStringType()2650 bool IsStringType() { return map_->instance_type() < FIRST_NONSTRING_TYPE; }
IsNumberType()2651 bool IsNumberType() { return map_->instance_type() == HEAP_NUMBER_TYPE; }
IsValueWrapped()2652 bool IsValueWrapped() { return IsStringType() || IsNumberType(); }
IsArrayType()2653 bool IsArrayType() { return map_->instance_type() == JS_ARRAY_TYPE; }
2654
2655 private:
GetConstantFromMap(Handle<Map> map)2656 Handle<Object> GetConstantFromMap(Handle<Map> map) const {
2657 DCHECK_EQ(DESCRIPTOR_TYPE, lookup_type_);
2658 DCHECK(number_ < map->NumberOfOwnDescriptors());
2659 return handle(map->instance_descriptors()->GetValue(number_), isolate());
2660 }
GetAccessorsFromMap(Handle<Map> map)2661 Handle<Object> GetAccessorsFromMap(Handle<Map> map) const {
2662 return GetConstantFromMap(map);
2663 }
2664 Handle<FieldType> GetFieldTypeFromMap(Handle<Map> map) const;
GetFieldOwnerFromMap(Handle<Map> map)2665 Handle<Map> GetFieldOwnerFromMap(Handle<Map> map) const {
2666 DCHECK(IsFound());
2667 DCHECK(number_ < map->NumberOfOwnDescriptors());
2668 return handle(map->FindFieldOwner(number_));
2669 }
GetLocalFieldIndexFromMap(Handle<Map> map)2670 int GetLocalFieldIndexFromMap(Handle<Map> map) const {
2671 DCHECK(lookup_type_ == DESCRIPTOR_TYPE ||
2672 lookup_type_ == TRANSITION_TYPE);
2673 DCHECK(number_ < map->NumberOfOwnDescriptors());
2674 int field_index = map->instance_descriptors()->GetFieldIndex(number_);
2675 return field_index - map->GetInObjectProperties();
2676 }
2677
LookupDescriptor(Map * map,Name * name)2678 void LookupDescriptor(Map* map, Name* name) {
2679 DescriptorArray* descriptors = map->instance_descriptors();
2680 int number = descriptors->SearchWithCache(isolate(), name, map);
2681 if (number == DescriptorArray::kNotFound) return NotFound();
2682 lookup_type_ = DESCRIPTOR_TYPE;
2683 details_ = descriptors->GetDetails(number);
2684 number_ = number;
2685 }
LookupTransition(Map * map,Name * name,PropertyAttributes attributes)2686 void LookupTransition(Map* map, Name* name, PropertyAttributes attributes) {
2687 Map* target =
2688 TransitionArray::SearchTransition(map, kData, name, attributes);
2689 if (target == NULL) return NotFound();
2690 lookup_type_ = TRANSITION_TYPE;
2691 transition_ = handle(target);
2692 number_ = transition_->LastAdded();
2693 details_ = transition_->instance_descriptors()->GetDetails(number_);
2694 }
NotFound()2695 void NotFound() {
2696 lookup_type_ = NOT_FOUND;
2697 details_ = PropertyDetails::Empty();
2698 }
representation()2699 Representation representation() const {
2700 DCHECK(IsFound());
2701 return details_.representation();
2702 }
IsTransitionToData()2703 bool IsTransitionToData() const {
2704 return IsTransition() && details_.type() == DATA;
2705 }
2706
zone()2707 Zone* zone() { return builder_->zone(); }
top_info()2708 CompilationInfo* top_info() { return builder_->top_info(); }
current_info()2709 CompilationInfo* current_info() { return builder_->current_info(); }
2710
2711 bool LoadResult(Handle<Map> map);
2712 bool LoadFieldMaps(Handle<Map> map);
2713 bool LookupDescriptor();
2714 bool LookupInPrototypes();
2715 bool IsIntegerIndexedExotic();
2716 bool IsCompatible(PropertyAccessInfo* other);
2717
GeneralizeRepresentation(Representation r)2718 void GeneralizeRepresentation(Representation r) {
2719 access_ = access_.WithRepresentation(
2720 access_.representation().generalize(r));
2721 }
2722
2723 HOptimizedGraphBuilder* builder_;
2724 PropertyAccessType access_type_;
2725 Handle<Map> map_;
2726 Handle<Name> name_;
2727 Handle<JSObject> holder_;
2728 Handle<Object> accessor_;
2729 Handle<JSObject> api_holder_;
2730 Handle<Object> constant_;
2731 SmallMapList field_maps_;
2732 HType field_type_;
2733 HObjectAccess access_;
2734
2735 enum { NOT_FOUND, DESCRIPTOR_TYPE, TRANSITION_TYPE } lookup_type_;
2736 Handle<Map> transition_;
2737 int number_;
2738 PropertyDetails details_;
2739 };
2740
2741 HValue* BuildMonomorphicAccess(PropertyAccessInfo* info, HValue* object,
2742 HValue* checked_object, HValue* value,
2743 BailoutId ast_id, BailoutId return_id,
2744 bool can_inline_accessor = true);
2745
2746 HValue* BuildNamedAccess(PropertyAccessType access, BailoutId ast_id,
2747 BailoutId reutrn_id, Expression* expr,
2748 FeedbackVectorSlot slot, HValue* object,
2749 Handle<Name> name, HValue* value,
2750 bool is_uninitialized = false);
2751
2752 void HandlePolymorphicCallNamed(Call* expr,
2753 HValue* receiver,
2754 SmallMapList* types,
2755 Handle<String> name);
2756 void HandleLiteralCompareTypeof(CompareOperation* expr,
2757 Expression* sub_expr,
2758 Handle<String> check);
2759 void HandleLiteralCompareNil(CompareOperation* expr,
2760 Expression* sub_expr,
2761 NilValue nil);
2762
2763 enum PushBeforeSimulateBehavior {
2764 PUSH_BEFORE_SIMULATE,
2765 NO_PUSH_BEFORE_SIMULATE
2766 };
2767
2768 HControlInstruction* BuildCompareInstruction(
2769 Token::Value op, HValue* left, HValue* right, Type* left_type,
2770 Type* right_type, Type* combined_type, SourcePosition left_position,
2771 SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result,
2772 BailoutId bailout_id);
2773
2774 HInstruction* BuildStringCharCodeAt(HValue* string,
2775 HValue* index);
2776
2777 HValue* BuildBinaryOperation(
2778 BinaryOperation* expr,
2779 HValue* left,
2780 HValue* right,
2781 PushBeforeSimulateBehavior push_sim_result);
2782 HInstruction* BuildIncrement(bool returns_original_input,
2783 CountOperation* expr);
2784 HInstruction* BuildKeyedGeneric(PropertyAccessType access_type,
2785 Expression* expr, FeedbackVectorSlot slot,
2786 HValue* object, HValue* key, HValue* value);
2787
2788 HInstruction* TryBuildConsolidatedElementLoad(HValue* object,
2789 HValue* key,
2790 HValue* val,
2791 SmallMapList* maps);
2792
2793 LoadKeyedHoleMode BuildKeyedHoleMode(Handle<Map> map);
2794
2795 HInstruction* BuildMonomorphicElementAccess(HValue* object,
2796 HValue* key,
2797 HValue* val,
2798 HValue* dependency,
2799 Handle<Map> map,
2800 PropertyAccessType access_type,
2801 KeyedAccessStoreMode store_mode);
2802
2803 HValue* HandlePolymorphicElementAccess(
2804 Expression* expr, FeedbackVectorSlot slot, HValue* object, HValue* key,
2805 HValue* val, SmallMapList* maps, PropertyAccessType access_type,
2806 KeyedAccessStoreMode store_mode, bool* has_side_effects);
2807
2808 HValue* HandleKeyedElementAccess(HValue* obj, HValue* key, HValue* val,
2809 Expression* expr, FeedbackVectorSlot slot,
2810 BailoutId ast_id, BailoutId return_id,
2811 PropertyAccessType access_type,
2812 bool* has_side_effects);
2813
2814 HInstruction* BuildNamedGeneric(PropertyAccessType access, Expression* expr,
2815 FeedbackVectorSlot slot, HValue* object,
2816 Handle<Name> name, HValue* value,
2817 bool is_uninitialized = false);
2818
2819 HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map);
2820
2821 void BuildLoad(Property* property,
2822 BailoutId ast_id);
2823 void PushLoad(Property* property,
2824 HValue* object,
2825 HValue* key);
2826
2827 void BuildStoreForEffect(Expression* expression, Property* prop,
2828 FeedbackVectorSlot slot, BailoutId ast_id,
2829 BailoutId return_id, HValue* object, HValue* key,
2830 HValue* value);
2831
2832 void BuildStore(Expression* expression, Property* prop,
2833 FeedbackVectorSlot slot, BailoutId ast_id,
2834 BailoutId return_id, bool is_uninitialized = false);
2835
2836 HInstruction* BuildLoadNamedField(PropertyAccessInfo* info,
2837 HValue* checked_object);
2838 HInstruction* BuildStoreNamedField(PropertyAccessInfo* info,
2839 HValue* checked_object,
2840 HValue* value);
2841
2842 HValue* BuildContextChainWalk(Variable* var);
2843
2844 HValue* AddThisFunction();
2845 HInstruction* BuildThisFunction();
2846
2847 HInstruction* BuildFastLiteral(Handle<JSObject> boilerplate_object,
2848 AllocationSiteUsageContext* site_context);
2849
2850 void BuildEmitObjectHeader(Handle<JSObject> boilerplate_object,
2851 HInstruction* object);
2852
2853 void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object,
2854 HInstruction* object,
2855 AllocationSiteUsageContext* site_context,
2856 PretenureFlag pretenure_flag);
2857
2858 void BuildEmitElements(Handle<JSObject> boilerplate_object,
2859 Handle<FixedArrayBase> elements,
2860 HValue* object_elements,
2861 AllocationSiteUsageContext* site_context);
2862
2863 void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements,
2864 ElementsKind kind,
2865 HValue* object_elements);
2866
2867 void BuildEmitFixedArray(Handle<FixedArrayBase> elements,
2868 ElementsKind kind,
2869 HValue* object_elements,
2870 AllocationSiteUsageContext* site_context);
2871
2872 void AddCheckPrototypeMaps(Handle<JSObject> holder,
2873 Handle<Map> receiver_map);
2874
2875 void BuildEnsureCallable(HValue* object);
2876
2877 HInstruction* NewCallFunction(HValue* function, int argument_count,
2878 TailCallMode syntactic_tail_call_mode,
2879 ConvertReceiverMode convert_mode,
2880 TailCallMode tail_call_mode);
2881
2882 HInstruction* NewCallFunctionViaIC(HValue* function, int argument_count,
2883 TailCallMode syntactic_tail_call_mode,
2884 ConvertReceiverMode convert_mode,
2885 TailCallMode tail_call_mode,
2886 FeedbackVectorSlot slot);
2887
2888 HInstruction* NewCallConstantFunction(Handle<JSFunction> target,
2889 int argument_count,
2890 TailCallMode syntactic_tail_call_mode,
2891 TailCallMode tail_call_mode);
2892
2893 bool CanBeFunctionApplyArguments(Call* expr);
2894
2895 // The translation state of the currently-being-translated function.
2896 FunctionState* function_state_;
2897
2898 // The base of the function state stack.
2899 FunctionState initial_function_state_;
2900
2901 // Expression context of the currently visited subexpression. NULL when
2902 // visiting statements.
2903 AstContext* ast_context_;
2904
2905 // A stack of breakable statements entered.
2906 BreakAndContinueScope* break_scope_;
2907
2908 int inlined_count_;
2909 ZoneList<Handle<Object> > globals_;
2910
2911 bool inline_bailout_;
2912
2913 HOsrBuilder* osr_;
2914
2915 AstTypeBounds bounds_;
2916
2917 friend class FunctionState; // Pushes and pops the state stack.
2918 friend class AstContext; // Pushes and pops the AST context stack.
2919 friend class KeyedLoadFastElementStub;
2920 friend class HOsrBuilder;
2921
2922 DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder);
2923 };
2924
2925
zone()2926 Zone* AstContext::zone() const { return owner_->zone(); }
2927
2928
2929 class HStatistics final : public Malloced {
2930 public:
HStatistics()2931 HStatistics()
2932 : times_(5),
2933 names_(5),
2934 sizes_(5),
2935 total_size_(0),
2936 source_size_(0) { }
2937
2938 void Initialize(CompilationInfo* info);
2939 void Print();
2940 void SaveTiming(const char* name, base::TimeDelta time, size_t size);
2941
IncrementFullCodeGen(base::TimeDelta full_code_gen)2942 void IncrementFullCodeGen(base::TimeDelta full_code_gen) {
2943 full_code_gen_ += full_code_gen;
2944 }
2945
IncrementCreateGraph(base::TimeDelta delta)2946 void IncrementCreateGraph(base::TimeDelta delta) { create_graph_ += delta; }
2947
IncrementOptimizeGraph(base::TimeDelta delta)2948 void IncrementOptimizeGraph(base::TimeDelta delta) {
2949 optimize_graph_ += delta;
2950 }
2951
IncrementGenerateCode(base::TimeDelta delta)2952 void IncrementGenerateCode(base::TimeDelta delta) { generate_code_ += delta; }
2953
IncrementSubtotals(base::TimeDelta create_graph,base::TimeDelta optimize_graph,base::TimeDelta generate_code)2954 void IncrementSubtotals(base::TimeDelta create_graph,
2955 base::TimeDelta optimize_graph,
2956 base::TimeDelta generate_code) {
2957 IncrementCreateGraph(create_graph);
2958 IncrementOptimizeGraph(optimize_graph);
2959 IncrementGenerateCode(generate_code);
2960 }
2961
2962 private:
2963 List<base::TimeDelta> times_;
2964 List<const char*> names_;
2965 List<size_t> sizes_;
2966 base::TimeDelta create_graph_;
2967 base::TimeDelta optimize_graph_;
2968 base::TimeDelta generate_code_;
2969 size_t total_size_;
2970 base::TimeDelta full_code_gen_;
2971 double source_size_;
2972 };
2973
2974
2975 class HPhase : public CompilationPhase {
2976 public:
HPhase(const char * name,HGraph * graph)2977 HPhase(const char* name, HGraph* graph)
2978 : CompilationPhase(name, graph->info()),
2979 graph_(graph) { }
2980 ~HPhase();
2981
2982 protected:
graph()2983 HGraph* graph() const { return graph_; }
2984
2985 private:
2986 HGraph* graph_;
2987
2988 DISALLOW_COPY_AND_ASSIGN(HPhase);
2989 };
2990
2991
2992 class HTracer final : public Malloced {
2993 public:
HTracer(int isolate_id)2994 explicit HTracer(int isolate_id)
2995 : trace_(&string_allocator_), indent_(0) {
2996 if (FLAG_trace_hydrogen_file == NULL) {
2997 SNPrintF(filename_,
2998 "hydrogen-%d-%d.cfg",
2999 base::OS::GetCurrentProcessId(),
3000 isolate_id);
3001 } else {
3002 StrNCpy(filename_, FLAG_trace_hydrogen_file, filename_.length());
3003 }
3004 WriteChars(filename_.start(), "", 0, false);
3005 }
3006
3007 void TraceCompilation(CompilationInfo* info);
3008 void TraceHydrogen(const char* name, HGraph* graph);
3009 void TraceLithium(const char* name, LChunk* chunk);
3010 void TraceLiveRanges(const char* name, LAllocator* allocator);
3011
3012 private:
3013 class Tag final BASE_EMBEDDED {
3014 public:
Tag(HTracer * tracer,const char * name)3015 Tag(HTracer* tracer, const char* name) {
3016 name_ = name;
3017 tracer_ = tracer;
3018 tracer->PrintIndent();
3019 tracer->trace_.Add("begin_%s\n", name);
3020 tracer->indent_++;
3021 }
3022
~Tag()3023 ~Tag() {
3024 tracer_->indent_--;
3025 tracer_->PrintIndent();
3026 tracer_->trace_.Add("end_%s\n", name_);
3027 DCHECK(tracer_->indent_ >= 0);
3028 tracer_->FlushToFile();
3029 }
3030
3031 private:
3032 HTracer* tracer_;
3033 const char* name_;
3034 };
3035
3036 void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
3037 void Trace(const char* name, HGraph* graph, LChunk* chunk);
3038 void FlushToFile();
3039
PrintEmptyProperty(const char * name)3040 void PrintEmptyProperty(const char* name) {
3041 PrintIndent();
3042 trace_.Add("%s\n", name);
3043 }
3044
PrintStringProperty(const char * name,const char * value)3045 void PrintStringProperty(const char* name, const char* value) {
3046 PrintIndent();
3047 trace_.Add("%s \"%s\"\n", name, value);
3048 }
3049
PrintLongProperty(const char * name,int64_t value)3050 void PrintLongProperty(const char* name, int64_t value) {
3051 PrintIndent();
3052 trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
3053 }
3054
PrintBlockProperty(const char * name,int block_id)3055 void PrintBlockProperty(const char* name, int block_id) {
3056 PrintIndent();
3057 trace_.Add("%s \"B%d\"\n", name, block_id);
3058 }
3059
PrintIntProperty(const char * name,int value)3060 void PrintIntProperty(const char* name, int value) {
3061 PrintIndent();
3062 trace_.Add("%s %d\n", name, value);
3063 }
3064
PrintIndent()3065 void PrintIndent() {
3066 for (int i = 0; i < indent_; i++) {
3067 trace_.Add(" ");
3068 }
3069 }
3070
3071 EmbeddedVector<char, 64> filename_;
3072 HeapStringAllocator string_allocator_;
3073 StringStream trace_;
3074 int indent_;
3075 };
3076
3077
3078 class NoObservableSideEffectsScope final {
3079 public:
NoObservableSideEffectsScope(HGraphBuilder * builder)3080 explicit NoObservableSideEffectsScope(HGraphBuilder* builder) :
3081 builder_(builder) {
3082 builder_->graph()->IncrementInNoSideEffectsScope();
3083 }
~NoObservableSideEffectsScope()3084 ~NoObservableSideEffectsScope() {
3085 builder_->graph()->DecrementInNoSideEffectsScope();
3086 }
3087
3088 private:
3089 HGraphBuilder* builder_;
3090 };
3091
3092 class DoExpressionScope final {
3093 public:
DoExpressionScope(HOptimizedGraphBuilder * builder)3094 explicit DoExpressionScope(HOptimizedGraphBuilder* builder)
3095 : builder_(builder) {
3096 builder_->function_state()->IncrementInDoExpressionScope();
3097 }
~DoExpressionScope()3098 ~DoExpressionScope() {
3099 builder_->function_state()->DecrementInDoExpressionScope();
3100 }
3101
3102 private:
3103 HOptimizedGraphBuilder* builder_;
3104 };
3105
3106 } // namespace internal
3107 } // namespace v8
3108
3109 #endif // V8_CRANKSHAFT_HYDROGEN_H_
3110