Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(387)

Side by Side Diff: src/hydrogen.h

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

Powered by Google App Engine
This is Rietveld 408576698