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