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