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