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 757351 : class HCompilationJob final : public CompilationJob {
40 : public:
41 378686 : 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 1514746 : 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 2362327 : 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 24896441 : 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 6415608 : 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 4493522 : 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 4493524 : first_instruction_index_ = index;
100 : }
101 : int last_instruction_index() const { return last_instruction_index_; }
102 : void set_last_instruction_index(int index) {
103 4493524 : last_instruction_index_ = index;
104 : }
105 3224341 : bool is_osr_entry() { return is_osr_entry_; }
106 2432 : void set_osr_entry() { is_osr_entry_ = true; }
107 :
108 : void AttachLoopInformation();
109 : void DetachLoopInformation();
110 71774137 : bool IsLoopHeader() const { return loop_information() != NULL; }
111 30316007 : 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 356825 : 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 856816 : 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 2832759 : HSimulate* AddNewSimulate(BailoutId ast_id, SourcePosition position,
144 : RemovableSimulate removable = FIXED_SIMULATE) {
145 2832759 : HSimulate* instr = CreateSimulate(ast_id, removable);
146 2832761 : AddInstruction(instr, position);
147 2832762 : 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 4153578 : bool IsInlineReturnTarget() const { return is_inline_return_target_; }
159 : void MarkAsInlineReturnTarget(HBasicBlock* inlined_entry_block) {
160 126831 : is_inline_return_target_ = true;
161 126831 : inlined_entry_block_ = inlined_entry_block;
162 : }
163 : HBasicBlock* inlined_entry_block() { return inlined_entry_block_; }
164 :
165 14100268 : bool IsDeoptimizing() const {
166 28012851 : return end() != NULL && end()->IsDeoptimize();
167 : }
168 :
169 : void MarkUnreachable();
170 8848059 : bool IsUnreachable() const { return !is_reachable_; }
171 72504445 : bool IsReachable() const { return is_reachable_; }
172 :
173 : bool IsLoopSuccessorDominator() const {
174 604489 : return dominates_loop_successors_;
175 : }
176 : void MarkAsLoopSuccessorDominator() {
177 305706 : dominates_loop_successors_ = true;
178 : }
179 :
180 6724179 : bool IsOrdered() const { return is_ordered_; }
181 4503783 : 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 10910666 : : predecessor_list_(block->predecessors()), current_(0) { }
247 :
248 13460428 : bool Done() { return current_ >= predecessor_list_->length(); }
249 10775900 : HBasicBlock* Current() { return predecessor_list_->at(current_); }
250 2549762 : 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 71033841 : explicit HInstructionIterator(HBasicBlock* block)
261 : : instr_(block->first()) {
262 71033841 : 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 441249619 : 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 61068 : HLoopInformation(HBasicBlock* loop_header, Zone* zone)
281 : : back_edges_(4, zone),
282 : loop_header_(loop_header),
283 : blocks_(8, zone),
284 61068 : stack_check_(NULL) {
285 : blocks_.Add(loop_header, zone);
286 61068 : }
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 45458 : 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 1415973 : int GetMaximumValueID() const { return values_.length(); }
377 4604288 : int GetNextBlockID() { return next_block_id_++; }
378 33109997 : int GetNextValueID(HValue* value) {
379 : DCHECK(!disallow_adding_new_values_);
380 : values_.Add(value, zone());
381 33109948 : return values_.length() - 1;
382 : }
383 : HValue* LookupValue(int id) const {
384 80319209 : if (id >= 0 && id < values_.length()) return values_[id];
385 : return NULL;
386 : }
387 : void DisallowAddingNewValues() {
388 283191 : 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 2432 : osr_ = osr;
403 : }
404 :
405 : HOsrBuilder* osr() {
406 : return osr_;
407 : }
408 :
409 : int update_type_change_checksum(int delta) {
410 367182 : type_change_checksum_ += delta;
411 : return type_change_checksum_;
412 : }
413 :
414 : void update_maximum_environment_size(int environment_size) {
415 10432202 : if (environment_size > maximum_environment_size_) {
416 301824 : 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 259782 : void set_allow_code_motion(bool value) { allow_code_motion_ = value; }
423 :
424 : bool use_optimistic_licm() const { return use_optimistic_licm_; }
425 259782 : void set_use_optimistic_licm(bool value) { use_optimistic_licm_ = value; }
426 :
427 9227 : void MarkDependsOnEmptyArrayProtoElements() {
428 : // Add map dependency if not already added.
429 7390 : if (depends_on_empty_array_proto_elements_) return;
430 : info()->dependencies()->AssumePropertyCell(
431 2766 : isolate()->factory()->array_protector());
432 2766 : 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 16503 : void MarkDependsOnStringLengthOverflow() {
440 23666 : if (depends_on_string_length_overflow_) return;
441 : info()->dependencies()->AssumePropertyCell(
442 2335 : isolate()->factory()->string_length_protector());
443 2335 : 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 8605 : void RecordUint32Instruction(HInstruction* instr) {
457 : DCHECK(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
458 3719 : if (uint32_instructions_ == NULL) {
459 1167 : uint32_instructions_ = new(zone()) ZoneList<HInstruction*>(4, zone());
460 : }
461 3719 : uint32_instructions_->Add(instr, zone());
462 3719 : }
463 :
464 766597 : void IncrementInNoSideEffectsScope() { no_side_effects_scope_count_++; }
465 766597 : 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 5094163 : void Run() {
475 2545036 : Phase phase(this);
476 4527414 : phase.Run();
477 5094171 : }
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 57829054 : 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 669483 : HEnvironment* arguments_environment() {
541 669483 : 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 7832473 : void set_ast_id(BailoutId id) { ast_id_ = id; }
560 :
561 : HEnterInlined* entry() const { return entry_; }
562 106730 : void set_entry(HEnterInlined* entry) { entry_ = entry; }
563 :
564 94743807 : int length() const { return values_.length(); }
565 :
566 22155800 : int first_expression_index() const {
567 22155800 : return parameter_count() + specials_count() + local_count();
568 : }
569 :
570 2509090 : int first_local_index() const {
571 2509090 : return parameter_count() + specials_count();
572 : }
573 :
574 26641 : void Bind(Variable* variable, HValue* value) {
575 353 : Bind(IndexFor(variable), value);
576 26641 : }
577 :
578 : void Bind(int index, HValue* value);
579 :
580 769106 : void BindContext(HValue* value) {
581 132644 : Bind(parameter_count(), value);
582 636463 : }
583 :
584 : HValue* Lookup(Variable* variable) const {
585 : return Lookup(IndexFor(variable));
586 : }
587 :
588 : HValue* Lookup(int index) const {
589 37248254 : HValue* result = values_[index];
590 : DCHECK(result != NULL);
591 : return result;
592 : }
593 :
594 15057561 : HValue* context() const {
595 : // Return first special.
596 : return Lookup(parameter_count());
597 : }
598 :
599 10236447 : void Push(HValue* value) {
600 : DCHECK(value != NULL);
601 10236447 : ++push_count_;
602 : values_.Add(value, zone());
603 : }
604 :
605 10968869 : HValue* Pop() {
606 : DCHECK(!ExpressionStackIsEmpty());
607 10968869 : if (push_count_ > 0) {
608 7640805 : --push_count_;
609 : } else {
610 3328064 : ++pop_count_;
611 : }
612 21937639 : 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 4528690 : int index = length() - index_from_top - 1;
623 : DCHECK(HasExpressionAt(index));
624 9053068 : 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 1118007 : HEnvironment* DiscardInlined(bool drop_extra) {
645 3437858 : HEnvironment* outer = outer_;
646 1201844 : while (outer->frame_type() != JS_FUNCTION &&
647 : outer->frame_type() != TAIL_CALLER_FUNCTION) {
648 83837 : outer = outer->outer_;
649 : }
650 1118007 : if (drop_extra) outer->Drop(1);
651 1118007 : if (outer->frame_type() == TAIL_CALLER_FUNCTION) {
652 181 : outer->ClearTailCallerMark();
653 : }
654 1118007 : return outer;
655 : }
656 :
657 : void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
658 :
659 : void ClearHistory() {
660 5833217 : pop_count_ = 0;
661 5833217 : push_count_ = 0;
662 : assigned_variables_.Clear();
663 : }
664 :
665 : void SetValueAt(int index, HValue* value) {
666 : DCHECK(index < length());
667 2778758 : 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 2870593 : int IndexFor(Variable* variable) const {
674 : DCHECK(variable->IsStackAllocated());
675 : int shift = variable->IsParameter()
676 : ? 1
677 2870593 : : parameter_count_ + specials_count_;
678 2870593 : return variable->index() + shift;
679 : }
680 :
681 : bool is_local_index(int i) const {
682 3785246 : return i >= first_local_index() && i < first_expression_index();
683 : }
684 :
685 14075 : bool is_parameter_index(int i) const {
686 28150 : return i >= 0 && i < parameter_count();
687 : }
688 :
689 112697176 : bool is_special_index(int i) const {
690 112697176 : 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 106415 : 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 923364 : : 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 5359101 : : 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 1050593 : 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 1050593 : 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 19395 : void ClearInlinedTestContext() {
896 19395 : delete test_context_;
897 19395 : test_context_ = NULL;
898 19395 : }
899 :
900 : FunctionState* outer() { return outer_; }
901 :
902 : TailCallMode ComputeTailCallMode(TailCallMode tail_call_mode) const {
903 766698 : if (tail_call_mode_ == TailCallMode::kDisallow) return tail_call_mode_;
904 : return tail_call_mode;
905 : }
906 :
907 : HEnterInlined* entry() { return entry_; }
908 107436 : 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 231 : arguments_elements_ = arguments_elements;
918 : }
919 :
920 340 : 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 843 : false_branch_(NULL) {}
976 : HIfContinuation(HBasicBlock* true_branch,
977 : HBasicBlock* false_branch)
978 : : continuation_captured_(true), true_branch_(true_branch),
979 5184 : 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 843 : true_branch_ = true_branch;
986 843 : false_branch_ = false_branch;
987 843 : continuation_captured_ = true;
988 : }
989 :
990 : void Continue(HBasicBlock** true_branch,
991 : HBasicBlock** false_branch) {
992 : DCHECK(continuation_captured_);
993 6027 : *true_branch = true_branch_;
994 6027 : *false_branch = false_branch_;
995 6027 : 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 7708 : : current_site_(current_site), pretenure_flag_(NOT_TENURED) {}
1021 : explicit HAllocationMode(PretenureFlag pretenure_flag)
1022 11710 : : current_site_(NULL), pretenure_flag_(pretenure_flag) {}
1023 : HAllocationMode()
1024 780728 : : 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 3800 : bool CreateAllocationMementos() const WARN_UNUSED_RESULT {
1030 : return current_site() != NULL;
1031 : }
1032 :
1033 : PretenureFlag GetPretenureMode() const WARN_UNUSED_RESULT {
1034 72322 : if (!feedback_site().is_null()) return feedback_site()->GetPretenureMode();
1035 15085 : 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 286915 : scope_(info->scope()),
1055 : position_(SourcePosition::Unknown()),
1056 860745 : track_positions_(track_positions) {}
1057 23483 : virtual ~HGraphBuilder() {}
1058 :
1059 : Scope* scope() const { return scope_; }
1060 899418 : void set_scope(Scope* scope) { scope_ = scope; }
1061 :
1062 : HBasicBlock* current_block() const { return current_block_; }
1063 5282215 : void set_current_block(HBasicBlock* block) { current_block_ = block; }
1064 35658961 : HEnvironment* environment() const {
1065 35764416 : return current_block()->last_environment();
1066 : }
1067 23435080 : Zone* zone() const { return info_->zone(); }
1068 : HGraph* graph() const { return graph_; }
1069 8309981 : Isolate* isolate() const { return graph_->isolate(); }
1070 : CompilationInfo* top_info() { return info_; }
1071 :
1072 : HGraph* CreateGraph();
1073 :
1074 : // Bailout environment manipulation.
1075 14715176 : void Push(HValue* value) { environment()->Push(value); }
1076 5177261 : 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 2795308 : from->Goto(target, source_position(), state, add_simulate);
1090 : }
1091 : void Goto(HBasicBlock* target,
1092 : FunctionState* state = NULL,
1093 632143 : 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 39834 : block->AddLeaveInlined(return_value, state, source_position());
1106 : }
1107 36233 : 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 1306424 : I* New() {
1118 1306424 : 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 1105560 : I* Add() { return AddInstructionTyped(New<I>());}
1126 :
1127 : template<class I, class P1>
1128 657487 : HInstruction* NewUncasted(P1 p1) {
1129 656978 : return I::New(isolate(), zone(), context(), p1);
1130 : }
1131 :
1132 : template <class I, class P1>
1133 14952743 : I* New(P1 p1) {
1134 14952742 : return I::New(isolate(), zone(), context(), p1);
1135 : }
1136 :
1137 : template<class I, class P1>
1138 327980 : HInstruction* AddUncasted(P1 p1) {
1139 327980 : 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 327980 : return result;
1145 : }
1146 :
1147 : template<class I, class P1>
1148 5647720 : I* Add(P1 p1) {
1149 5221015 : 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 5647723 : return result;
1155 : }
1156 :
1157 : template<class I, class P1, class P2>
1158 1559835 : HInstruction* NewUncasted(P1 p1, P2 p2) {
1159 1040256 : return I::New(isolate(), zone(), context(), p1, p2);
1160 : }
1161 :
1162 : template<class I, class P1, class P2>
1163 5894179 : I* New(P1 p1, P2 p2) {
1164 5715210 : return I::New(isolate(), zone(), context(), p1, p2);
1165 : }
1166 :
1167 : template<class I, class P1, class P2>
1168 489802 : HInstruction* AddUncasted(P1 p1, P2 p2) {
1169 489802 : 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 489802 : return result;
1174 : }
1175 :
1176 : template<class I, class P1, class P2>
1177 1955216 : I* Add(P1 p1, P2 p2) {
1178 1955216 : 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 1955215 : return result;
1183 : }
1184 :
1185 : template<class I, class P1, class P2, class P3>
1186 480333 : HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3) {
1187 320222 : return I::New(isolate(), zone(), context(), p1, p2, p3);
1188 : }
1189 :
1190 : template<class I, class P1, class P2, class P3>
1191 2645744 : I* New(P1 p1, P2 p2, P3 p3) {
1192 2646170 : return I::New(isolate(), zone(), context(), p1, p2, p3);
1193 : }
1194 :
1195 : template<class I, class P1, class P2, class P3>
1196 158361 : HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3) {
1197 158361 : return AddInstruction(NewUncasted<I>(p1, p2, p3));
1198 : }
1199 :
1200 : template<class I, class P1, class P2, class P3>
1201 812726 : I* Add(P1 p1, P2 p2, P3 p3) {
1202 1625452 : 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 657836 : I* New(P1 p1, P2 p2, P3 p3, P4 p4) {
1212 657836 : 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 127312 : I* Add(P1 p1, P2 p2, P3 p3, P4 p4) {
1222 254624 : 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 80643 : HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1227 53762 : 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 2099876 : I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1232 2099876 : 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 26881 : HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1237 26881 : 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 33792 : I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1242 67584 : 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 896 : HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1247 896 : 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 188982 : I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1252 188982 : 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 448 : HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1257 448 : 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 86583 : I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1262 173166 : 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 214872 : I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) {
1318 107436 : return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8,
1319 214872 : 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 107436 : I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) {
1332 214872 : 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 1088 : HValue* BuildDecodeField(HValue* encoded_field) {
1349 1088 : HValue* mask_value = Add<HConstant>(static_cast<int>(BitFieldClass::kMask));
1350 : HValue* masked_field =
1351 1088 : AddUncasted<HBitwise>(Token::BIT_AND, encoded_field, mask_value);
1352 : return AddUncasted<HShr>(masked_field,
1353 1088 : 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 : void BuildTransitionElementsKind(HValue* object,
1383 : HValue* map,
1384 : ElementsKind from_kind,
1385 : ElementsKind to_kind,
1386 : bool is_jsarray);
1387 :
1388 : HValue* BuildNumberToString(HValue* object, AstType* type);
1389 : HValue* BuildToNumber(HValue* input);
1390 : HValue* BuildToObject(HValue* receiver);
1391 :
1392 : HValue* BuildUncheckedDictionaryElementLoad(HValue* receiver,
1393 : HValue* elements, HValue* key,
1394 : HValue* hash);
1395 :
1396 : // ES6 section 7.4.7 CreateIterResultObject ( value, done )
1397 : HValue* BuildCreateIterResultObject(HValue* value, HValue* done);
1398 :
1399 : // Allocates a new object according with the given allocation properties.
1400 : HAllocate* BuildAllocate(HValue* object_size,
1401 : HType type,
1402 : InstanceType instance_type,
1403 : HAllocationMode allocation_mode);
1404 : // Computes the sum of two string lengths, taking care of overflow handling.
1405 : HValue* BuildAddStringLengths(HValue* left_length, HValue* right_length);
1406 : // Creates a cons string using the two input strings.
1407 : HValue* BuildCreateConsString(HValue* length,
1408 : HValue* left,
1409 : HValue* right,
1410 : HAllocationMode allocation_mode);
1411 : // Copies characters from one sequential string to another.
1412 : void BuildCopySeqStringChars(HValue* src,
1413 : HValue* src_offset,
1414 : String::Encoding src_encoding,
1415 : HValue* dst,
1416 : HValue* dst_offset,
1417 : String::Encoding dst_encoding,
1418 : HValue* length);
1419 :
1420 : // Align an object size to object alignment boundary
1421 : HValue* BuildObjectSizeAlignment(HValue* unaligned_size, int header_size);
1422 :
1423 : // Both operands are non-empty strings.
1424 : HValue* BuildUncheckedStringAdd(HValue* left,
1425 : HValue* right,
1426 : HAllocationMode allocation_mode);
1427 : // Add two strings using allocation mode, validating type feedback.
1428 : HValue* BuildStringAdd(HValue* left,
1429 : HValue* right,
1430 : HAllocationMode allocation_mode);
1431 :
1432 : HInstruction* BuildUncheckedMonomorphicElementAccess(
1433 : HValue* checked_object,
1434 : HValue* key,
1435 : HValue* val,
1436 : bool is_js_array,
1437 : ElementsKind elements_kind,
1438 : PropertyAccessType access_type,
1439 : LoadKeyedHoleMode load_mode,
1440 : KeyedAccessStoreMode store_mode);
1441 :
1442 : HInstruction* AddElementAccess(
1443 : HValue* elements, HValue* checked_key, HValue* val, HValue* dependency,
1444 : HValue* backing_store_owner, ElementsKind elements_kind,
1445 : PropertyAccessType access_type,
1446 : LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE);
1447 :
1448 : HInstruction* AddLoadStringInstanceType(HValue* string);
1449 : HInstruction* AddLoadStringLength(HValue* string);
1450 : HInstruction* BuildLoadStringLength(HValue* string);
1451 14465 : HStoreNamedField* AddStoreMapConstant(HValue* object, Handle<Map> map) {
1452 : return Add<HStoreNamedField>(object, HObjectAccess::ForMap(),
1453 14465 : Add<HConstant>(map));
1454 : }
1455 : HLoadNamedField* AddLoadMap(HValue* object,
1456 : HValue* dependency = NULL);
1457 : HLoadNamedField* AddLoadElements(HValue* object,
1458 : HValue* dependency = NULL);
1459 :
1460 : bool MatchRotateRight(HValue* left,
1461 : HValue* right,
1462 : HValue** operand,
1463 : HValue** shift_amount);
1464 :
1465 : HValue* BuildBinaryOperation(Token::Value op, HValue* left, HValue* right,
1466 : AstType* left_type, AstType* right_type,
1467 : AstType* result_type, Maybe<int> fixed_right_arg,
1468 : HAllocationMode allocation_mode,
1469 : BailoutId opt_id = BailoutId::None());
1470 :
1471 : HLoadNamedField* AddLoadFixedArrayLength(HValue *object,
1472 : HValue *dependency = NULL);
1473 :
1474 : HLoadNamedField* AddLoadArrayLength(HValue *object,
1475 : ElementsKind kind,
1476 : HValue *dependency = NULL);
1477 :
1478 : HValue* AddLoadJSBuiltin(int context_index);
1479 :
1480 : HValue* EnforceNumberType(HValue* number, AstType* expected);
1481 : HValue* TruncateToNumber(HValue* value, AstType** expected);
1482 :
1483 : void FinishExitWithHardDeoptimization(DeoptimizeReason reason);
1484 :
1485 : void AddIncrementCounter(StatsCounter* counter);
1486 :
1487 : class IfBuilder final {
1488 : public:
1489 : // If using this constructor, Initialize() must be called explicitly!
1490 : IfBuilder();
1491 :
1492 : explicit IfBuilder(HGraphBuilder* builder);
1493 : IfBuilder(HGraphBuilder* builder,
1494 : HIfContinuation* continuation);
1495 :
1496 : ~IfBuilder() {
1497 99375 : if (!finished_) End();
1498 : }
1499 :
1500 : void Initialize(HGraphBuilder* builder);
1501 :
1502 : template<class Condition>
1503 7351 : Condition* If(HValue *p) {
1504 7351 : Condition* compare = builder()->New<Condition>(p);
1505 7351 : AddCompare(compare);
1506 7351 : return compare;
1507 : }
1508 :
1509 : template<class Condition, class P2>
1510 26986 : Condition* If(HValue* p1, P2 p2) {
1511 26986 : Condition* compare = builder()->New<Condition>(p1, p2);
1512 26986 : AddCompare(compare);
1513 26986 : return compare;
1514 : }
1515 :
1516 : template<class Condition, class P2, class P3>
1517 93631 : Condition* If(HValue* p1, P2 p2, P3 p3) {
1518 93631 : Condition* compare = builder()->New<Condition>(p1, p2, p3);
1519 93631 : AddCompare(compare);
1520 93631 : return compare;
1521 : }
1522 :
1523 : template<class Condition>
1524 : Condition* IfNot(HValue* p) {
1525 1390 : Condition* compare = If<Condition>(p);
1526 1390 : compare->Not();
1527 : return compare;
1528 : }
1529 :
1530 : template<class Condition, class P2>
1531 : Condition* IfNot(HValue* p1, P2 p2) {
1532 271 : Condition* compare = If<Condition>(p1, p2);
1533 271 : compare->Not();
1534 : return compare;
1535 : }
1536 :
1537 : template<class Condition, class P2, class P3>
1538 : Condition* IfNot(HValue* p1, P2 p2, P3 p3) {
1539 133 : Condition* compare = If<Condition>(p1, p2, p3);
1540 133 : compare->Not();
1541 : return compare;
1542 : }
1543 :
1544 : template<class Condition>
1545 : Condition* OrIf(HValue *p) {
1546 : Or();
1547 : return If<Condition>(p);
1548 : }
1549 :
1550 : template<class Condition, class P2>
1551 : Condition* OrIf(HValue* p1, P2 p2) {
1552 170 : Or();
1553 170 : return If<Condition>(p1, p2);
1554 : }
1555 :
1556 : template<class Condition, class P2, class P3>
1557 : Condition* OrIf(HValue* p1, P2 p2, P3 p3) {
1558 : Or();
1559 : return If<Condition>(p1, p2, p3);
1560 : }
1561 :
1562 : template<class Condition>
1563 : Condition* AndIf(HValue *p) {
1564 : And();
1565 : return If<Condition>(p);
1566 : }
1567 :
1568 : template<class Condition, class P2>
1569 : Condition* AndIf(HValue* p1, P2 p2) {
1570 103 : And();
1571 103 : return If<Condition>(p1, p2);
1572 : }
1573 :
1574 : template<class Condition, class P2, class P3>
1575 : Condition* AndIf(HValue* p1, P2 p2, P3 p3) {
1576 85 : And();
1577 85 : return If<Condition>(p1, p2, p3);
1578 : }
1579 :
1580 : void Or();
1581 : void And();
1582 :
1583 : // Captures the current state of this IfBuilder in the specified
1584 : // continuation and ends this IfBuilder.
1585 : void CaptureContinuation(HIfContinuation* continuation);
1586 :
1587 : // Joins the specified continuation from this IfBuilder and ends this
1588 : // IfBuilder. This appends a Goto instruction from the true branch of
1589 : // this IfBuilder to the true branch of the continuation unless the
1590 : // true branch of this IfBuilder is already finished. And vice versa
1591 : // for the false branch.
1592 : //
1593 : // The basic idea is as follows: You have several nested IfBuilder's
1594 : // that you want to join based on two possible outcomes (i.e. success
1595 : // and failure, or whatever). You can do this easily using this method
1596 : // now, for example:
1597 : //
1598 : // HIfContinuation cont(graph()->CreateBasicBlock(),
1599 : // graph()->CreateBasicBlock());
1600 : // ...
1601 : // IfBuilder if_whatever(this);
1602 : // if_whatever.If<Condition>(arg);
1603 : // if_whatever.Then();
1604 : // ...
1605 : // if_whatever.Else();
1606 : // ...
1607 : // if_whatever.JoinContinuation(&cont);
1608 : // ...
1609 : // IfBuilder if_something(this);
1610 : // if_something.If<Condition>(arg1, arg2);
1611 : // if_something.Then();
1612 : // ...
1613 : // if_something.Else();
1614 : // ...
1615 : // if_something.JoinContinuation(&cont);
1616 : // ...
1617 : // IfBuilder if_finally(this, &cont);
1618 : // if_finally.Then();
1619 : // // continues after then code of if_whatever or if_something.
1620 : // ...
1621 : // if_finally.Else();
1622 : // // continues after else code of if_whatever or if_something.
1623 : // ...
1624 : // if_finally.End();
1625 : void JoinContinuation(HIfContinuation* continuation);
1626 :
1627 : void Then();
1628 : void Else();
1629 : void End();
1630 : void EndUnreachable();
1631 :
1632 : void Deopt(DeoptimizeReason reason);
1633 : void ThenDeopt(DeoptimizeReason reason) {
1634 1675 : Then();
1635 1675 : Deopt(reason);
1636 : }
1637 496 : void ElseDeopt(DeoptimizeReason reason) {
1638 0 : Else();
1639 496 : Deopt(reason);
1640 496 : }
1641 :
1642 : void Return(HValue* value);
1643 :
1644 : private:
1645 : void InitializeDontCreateBlocks(HGraphBuilder* builder);
1646 :
1647 : HControlInstruction* AddCompare(HControlInstruction* compare);
1648 :
1649 : HGraphBuilder* builder() const {
1650 : DCHECK(builder_ != NULL); // Have you called "Initialize"?
1651 : return builder_;
1652 : }
1653 :
1654 : void AddMergeAtJoinBlock(bool deopt);
1655 :
1656 : void Finish();
1657 : void Finish(HBasicBlock** then_continuation,
1658 : HBasicBlock** else_continuation);
1659 :
1660 : class MergeAtJoinBlock : public ZoneObject {
1661 : public:
1662 : MergeAtJoinBlock(HBasicBlock* block,
1663 : bool deopt,
1664 : MergeAtJoinBlock* next)
1665 : : block_(block),
1666 : deopt_(deopt),
1667 216314 : next_(next) {}
1668 : HBasicBlock* block_;
1669 : bool deopt_;
1670 : MergeAtJoinBlock* next_;
1671 : };
1672 :
1673 : HGraphBuilder* builder_;
1674 : bool finished_ : 1;
1675 : bool did_then_ : 1;
1676 : bool did_else_ : 1;
1677 : bool did_else_if_ : 1;
1678 : bool did_and_ : 1;
1679 : bool did_or_ : 1;
1680 : bool captured_ : 1;
1681 : bool needs_compare_ : 1;
1682 : bool pending_merge_block_ : 1;
1683 : HBasicBlock* first_true_block_;
1684 : HBasicBlock* first_false_block_;
1685 : HBasicBlock* split_edge_merge_block_;
1686 : MergeAtJoinBlock* merge_at_join_blocks_;
1687 : int normal_merge_at_join_block_count_;
1688 : int deopt_merge_at_join_block_count_;
1689 : };
1690 :
1691 : class LoopBuilder final {
1692 : public:
1693 : enum Direction {
1694 : kPreIncrement,
1695 : kPostIncrement,
1696 : kPreDecrement,
1697 : kPostDecrement,
1698 : kWhileTrue
1699 : };
1700 :
1701 : explicit LoopBuilder(HGraphBuilder* builder); // while (true) {...}
1702 : LoopBuilder(HGraphBuilder* builder,
1703 : HValue* context,
1704 : Direction direction);
1705 : LoopBuilder(HGraphBuilder* builder,
1706 : HValue* context,
1707 : Direction direction,
1708 : HValue* increment_amount);
1709 :
1710 : ~LoopBuilder() {
1711 : DCHECK(finished_);
1712 : }
1713 :
1714 : HValue* BeginBody(
1715 : HValue* initial,
1716 : HValue* terminating,
1717 : Token::Value token);
1718 :
1719 : void BeginBody(int drop_count);
1720 :
1721 : void Break();
1722 :
1723 : void EndBody();
1724 :
1725 : private:
1726 : void Initialize(HGraphBuilder* builder, HValue* context,
1727 : Direction direction, HValue* increment_amount);
1728 15546 : Zone* zone() { return builder_->zone(); }
1729 :
1730 : HGraphBuilder* builder_;
1731 : HValue* context_;
1732 : HValue* increment_amount_;
1733 : HInstruction* increment_;
1734 : HPhi* phi_;
1735 : HBasicBlock* header_block_;
1736 : HBasicBlock* body_block_;
1737 : HBasicBlock* exit_block_;
1738 : HBasicBlock* exit_trampoline_block_;
1739 : Direction direction_;
1740 : bool finished_;
1741 : };
1742 :
1743 : HValue* BuildNewElementsCapacity(HValue* old_capacity);
1744 :
1745 : HValue* BuildCalculateElementsSize(ElementsKind kind,
1746 : HValue* capacity);
1747 : HAllocate* AllocateJSArrayObject(AllocationSiteMode mode);
1748 : HConstant* EstablishElementsAllocationSize(ElementsKind kind, int capacity);
1749 :
1750 : HAllocate* BuildAllocateElements(ElementsKind kind, HValue* size_in_bytes);
1751 :
1752 : void BuildInitializeElementsHeader(HValue* elements,
1753 : ElementsKind kind,
1754 : HValue* capacity);
1755 :
1756 : // Build allocation and header initialization code for respective successor
1757 : // of FixedArrayBase.
1758 : HValue* BuildAllocateAndInitializeArray(ElementsKind kind, HValue* capacity);
1759 :
1760 : // |array| must have been allocated with enough room for
1761 : // 1) the JSArray and 2) an AllocationMemento if mode requires it.
1762 : // If the |elements| value provided is NULL then the array elements storage
1763 : // is initialized with empty array.
1764 : void BuildJSArrayHeader(HValue* array,
1765 : HValue* array_map,
1766 : HValue* elements,
1767 : AllocationSiteMode mode,
1768 : ElementsKind elements_kind,
1769 : HValue* allocation_site_payload,
1770 : HValue* length_field);
1771 :
1772 : HValue* BuildGrowElementsCapacity(HValue* object,
1773 : HValue* elements,
1774 : ElementsKind kind,
1775 : ElementsKind new_kind,
1776 : HValue* length,
1777 : HValue* new_capacity);
1778 :
1779 : void BuildFillElementsWithValue(HValue* elements,
1780 : ElementsKind elements_kind,
1781 : HValue* from,
1782 : HValue* to,
1783 : HValue* value);
1784 :
1785 : void BuildFillElementsWithHole(HValue* elements,
1786 : ElementsKind elements_kind,
1787 : HValue* from,
1788 : HValue* to);
1789 :
1790 : void BuildCopyProperties(HValue* from_properties, HValue* to_properties,
1791 : HValue* length, HValue* capacity);
1792 :
1793 : void BuildCopyElements(HValue* from_elements,
1794 : ElementsKind from_elements_kind,
1795 : HValue* to_elements,
1796 : ElementsKind to_elements_kind,
1797 : HValue* length,
1798 : HValue* capacity);
1799 :
1800 : HValue* BuildElementIndexHash(HValue* index);
1801 :
1802 : void BuildCreateAllocationMemento(HValue* previous_object,
1803 : HValue* previous_object_size,
1804 : HValue* payload);
1805 :
1806 : HInstruction* BuildConstantMapCheck(Handle<JSObject> constant,
1807 : bool ensure_no_elements = false);
1808 : HInstruction* BuildCheckPrototypeMaps(Handle<JSObject> prototype,
1809 : Handle<JSObject> holder,
1810 : bool ensure_no_elements = false);
1811 :
1812 : HInstruction* BuildGetNativeContext(HValue* closure);
1813 : HInstruction* BuildGetNativeContext();
1814 :
1815 : // Builds a loop version if |depth| is specified or unrolls the loop to
1816 : // |depth_value| iterations otherwise.
1817 : HValue* BuildGetParentContext(HValue* depth, int depth_value);
1818 :
1819 : HInstruction* BuildGetArrayFunction();
1820 : HValue* BuildArrayBufferViewFieldAccessor(HValue* object,
1821 : HValue* checked_object,
1822 : FieldIndex index);
1823 :
1824 :
1825 : protected:
1826 : void SetSourcePosition(int position) {
1827 1710844 : if (position != kNoSourcePosition) {
1828 : position_.SetScriptOffset(position);
1829 : }
1830 : // Otherwise position remains unknown.
1831 : }
1832 :
1833 : void EnterInlinedSource(int inlining_id) {
1834 125 : if (is_tracking_positions()) {
1835 : position_.SetInliningId(inlining_id);
1836 : }
1837 : }
1838 :
1839 : // Convert the given absolute offset from the start of the script to
1840 : // the SourcePosition assuming that this position corresponds to the
1841 : // same function as position_.
1842 : SourcePosition ScriptPositionToSourcePosition(int position) {
1843 863354 : if (position == kNoSourcePosition) {
1844 : return SourcePosition::Unknown();
1845 : }
1846 : return SourcePosition(position, position_.InliningId());
1847 : }
1848 :
1849 : SourcePosition source_position() { return position_; }
1850 1841 : void set_source_position(SourcePosition position) { position_ = position; }
1851 :
1852 : bool is_tracking_positions() { return track_positions_; }
1853 :
1854 : HValue* BuildAllocateEmptyArrayBuffer(HValue* byte_length);
1855 : template <typename ViewClass>
1856 : void BuildArrayBufferViewInitialization(HValue* obj,
1857 : HValue* buffer,
1858 : HValue* byte_offset,
1859 : HValue* byte_length);
1860 :
1861 : private:
1862 : HGraphBuilder();
1863 :
1864 : template <class I>
1865 : I* AddInstructionTyped(I* instr) {
1866 9323562 : return I::cast(AddInstruction(instr));
1867 : }
1868 :
1869 : CompilationInfo* info_;
1870 : CallInterfaceDescriptor descriptor_;
1871 : HGraph* graph_;
1872 : HBasicBlock* current_block_;
1873 : Scope* scope_;
1874 : SourcePosition position_;
1875 : bool track_positions_;
1876 : };
1877 :
1878 : template <>
1879 641932 : inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>(
1880 1170110 : DeoptimizeReason reason, Deoptimizer::BailoutType type) {
1881 641932 : if (type == Deoptimizer::SOFT) {
1882 624483 : isolate()->counters()->soft_deopts_requested()->Increment();
1883 624483 : if (FLAG_always_opt) return NULL;
1884 : }
1885 187692 : if (current_block()->IsDeoptimizing()) return NULL;
1886 : HBasicBlock* after_deopt_block = CreateBasicBlock(
1887 187692 : current_block()->last_environment());
1888 187692 : HDeoptimize* instr = New<HDeoptimize>(reason, type, after_deopt_block);
1889 187692 : if (type == Deoptimizer::SOFT) {
1890 170243 : isolate()->counters()->soft_deopts_inserted()->Increment();
1891 : }
1892 187692 : FinishCurrentBlock(instr);
1893 : set_current_block(after_deopt_block);
1894 187692 : return instr;
1895 : }
1896 :
1897 : template <>
1898 : inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>(
1899 : DeoptimizeReason reason, Deoptimizer::BailoutType type) {
1900 : return Add<HDeoptimize>(reason, type);
1901 : }
1902 :
1903 :
1904 : template<>
1905 2122285 : inline HSimulate* HGraphBuilder::Add<HSimulate>(
1906 : BailoutId id,
1907 2122285 : RemovableSimulate removable) {
1908 2122285 : HSimulate* instr = current_block()->CreateSimulate(id, removable);
1909 2122286 : AddInstruction(instr);
1910 2122286 : return instr;
1911 : }
1912 :
1913 :
1914 : template<>
1915 : inline HSimulate* HGraphBuilder::Add<HSimulate>(
1916 : BailoutId id) {
1917 475767 : return Add<HSimulate>(id, FIXED_SIMULATE);
1918 : }
1919 :
1920 :
1921 : template<>
1922 : inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(BailoutId id) {
1923 : return Add<HSimulate>(id, FIXED_SIMULATE);
1924 : }
1925 :
1926 :
1927 : template<>
1928 327980 : inline HReturn* HGraphBuilder::Add<HReturn>(HValue* value) {
1929 327980 : int num_parameters = graph()->info()->num_parameters();
1930 327980 : HValue* params = AddUncasted<HConstant>(num_parameters);
1931 327980 : HReturn* return_instruction = New<HReturn>(value, params);
1932 327980 : FinishExitCurrentBlock(return_instruction);
1933 327980 : return return_instruction;
1934 : }
1935 :
1936 :
1937 : template<>
1938 : inline HReturn* HGraphBuilder::Add<HReturn>(HConstant* value) {
1939 44081 : return Add<HReturn>(static_cast<HValue*>(value));
1940 : }
1941 :
1942 : template<>
1943 : inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HValue* value) {
1944 : return Add<HReturn>(value);
1945 : }
1946 :
1947 :
1948 : template<>
1949 : inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HConstant* value) {
1950 : return Add<HReturn>(value);
1951 : }
1952 :
1953 :
1954 : template<>
1955 57332 : inline HCallRuntime* HGraphBuilder::Add<HCallRuntime>(
1956 : const Runtime::Function* c_function,
1957 57332 : int argument_count) {
1958 57332 : HCallRuntime* instr = New<HCallRuntime>(c_function, argument_count);
1959 57332 : if (graph()->info()->IsStub()) {
1960 : // When compiling code stubs, we don't want to save all double registers
1961 : // upon entry to the stub, but instead have the call runtime instruction
1962 : // save the double registers only on-demand (in the fallback case).
1963 : instr->set_save_doubles(kSaveFPRegs);
1964 : }
1965 57332 : AddInstruction(instr);
1966 57332 : return instr;
1967 : }
1968 :
1969 :
1970 : template<>
1971 : inline HInstruction* HGraphBuilder::AddUncasted<HCallRuntime>(
1972 : Handle<String> name,
1973 : const Runtime::Function* c_function,
1974 : int argument_count) {
1975 : return Add<HCallRuntime>(c_function, argument_count);
1976 : }
1977 :
1978 :
1979 : template <>
1980 426705 : inline HParameter* HGraphBuilder::New<HParameter>(unsigned index) {
1981 426705 : return HParameter::New(isolate(), zone(), nullptr, index);
1982 : }
1983 :
1984 :
1985 : template <>
1986 : inline HParameter* HGraphBuilder::New<HParameter>(
1987 : unsigned index, HParameter::ParameterKind kind) {
1988 : return HParameter::New(isolate(), zone(), nullptr, index, kind);
1989 : }
1990 :
1991 :
1992 : template <>
1993 : inline HParameter* HGraphBuilder::New<HParameter>(
1994 : unsigned index, HParameter::ParameterKind kind, Representation r) {
1995 : return HParameter::New(isolate(), zone(), nullptr, index, kind, r);
1996 : }
1997 :
1998 :
1999 : template <>
2000 263433 : inline HPrologue* HGraphBuilder::New<HPrologue>() {
2001 263433 : return HPrologue::New(zone());
2002 : }
2003 :
2004 :
2005 : template <>
2006 289347 : inline HContext* HGraphBuilder::New<HContext>() {
2007 289347 : return HContext::New(zone());
2008 : }
2009 :
2010 : // This AstVistor is not final, and provides the AstVisitor methods as virtual
2011 : // methods so they can be specialized by subclasses.
2012 0 : class HOptimizedGraphBuilder : public HGraphBuilder,
2013 : public AstVisitor<HOptimizedGraphBuilder> {
2014 : public:
2015 : // A class encapsulating (lazily-allocated) break and continue blocks for
2016 : // a breakable statement. Separated from BreakAndContinueScope so that it
2017 : // can have a separate lifetime.
2018 : class BreakAndContinueInfo final BASE_EMBEDDED {
2019 : public:
2020 : explicit BreakAndContinueInfo(BreakableStatement* target,
2021 : Scope* scope,
2022 : int drop_extra = 0)
2023 : : target_(target),
2024 : break_block_(NULL),
2025 : continue_block_(NULL),
2026 : scope_(scope),
2027 735644 : drop_extra_(drop_extra) {
2028 : }
2029 :
2030 : BreakableStatement* target() { return target_; }
2031 : HBasicBlock* break_block() { return break_block_; }
2032 3762 : void set_break_block(HBasicBlock* block) { break_block_ = block; }
2033 : HBasicBlock* continue_block() { return continue_block_; }
2034 1527 : void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
2035 : Scope* scope() { return scope_; }
2036 : int drop_extra() { return drop_extra_; }
2037 :
2038 : private:
2039 : BreakableStatement* target_;
2040 : HBasicBlock* break_block_;
2041 : HBasicBlock* continue_block_;
2042 : Scope* scope_;
2043 : int drop_extra_;
2044 : };
2045 :
2046 : // A helper class to maintain a stack of current BreakAndContinueInfo
2047 : // structures mirroring BreakableStatement nesting.
2048 : class BreakAndContinueScope final BASE_EMBEDDED {
2049 : public:
2050 : BreakAndContinueScope(BreakAndContinueInfo* info,
2051 735644 : HOptimizedGraphBuilder* owner)
2052 1471288 : : info_(info), owner_(owner), next_(owner->break_scope()) {
2053 : owner->set_break_scope(this);
2054 : }
2055 :
2056 735644 : ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
2057 :
2058 : BreakAndContinueInfo* info() { return info_; }
2059 : HOptimizedGraphBuilder* owner() { return owner_; }
2060 : BreakAndContinueScope* next() { return next_; }
2061 :
2062 : // Search the break stack for a break or continue target.
2063 : enum BreakType { BREAK, CONTINUE };
2064 : HBasicBlock* Get(BreakableStatement* stmt, BreakType type,
2065 : Scope** scope, int* drop_extra);
2066 :
2067 : private:
2068 : BreakAndContinueInfo* info_;
2069 : HOptimizedGraphBuilder* owner_;
2070 : BreakAndContinueScope* next_;
2071 : };
2072 :
2073 : explicit HOptimizedGraphBuilder(CompilationInfo* info, bool track_positions);
2074 :
2075 : bool BuildGraph() override;
2076 :
2077 : // Simple accessors.
2078 : BreakAndContinueScope* break_scope() const { return break_scope_; }
2079 1471288 : void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
2080 :
2081 28750048 : HValue* context() override { return environment()->context(); }
2082 :
2083 : HOsrBuilder* osr() const { return osr_; }
2084 :
2085 : void Bailout(BailoutReason reason);
2086 :
2087 : HBasicBlock* CreateJoin(HBasicBlock* first,
2088 : HBasicBlock* second,
2089 : BailoutId join_id);
2090 :
2091 : FunctionState* function_state() const { return function_state_; }
2092 :
2093 : void VisitDeclarations(Declaration::List* declarations);
2094 :
2095 : AstTypeBounds* bounds() { return &bounds_; }
2096 :
2097 263433 : void* operator new(size_t size, Zone* zone) { return zone->New(size); }
2098 : void operator delete(void* pointer, Zone* zone) { }
2099 : void operator delete(void* pointer) { }
2100 :
2101 43065520 : DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
2102 :
2103 : protected:
2104 : // Forward declarations for inner scope classes.
2105 : class SubgraphScope;
2106 :
2107 : static const int kMaxCallPolymorphism = 4;
2108 : static const int kMaxLoadPolymorphism = 4;
2109 : static const int kMaxStorePolymorphism = 4;
2110 :
2111 : // Even in the 'unlimited' case we have to have some limit in order not to
2112 : // overflow the stack.
2113 : static const int kUnlimitedMaxInlinedSourceSize = 100000;
2114 : static const int kUnlimitedMaxInlinedNodes = 10000;
2115 : static const int kUnlimitedMaxInlinedNodesCumulative = 10000;
2116 :
2117 : // Maximum depth and total number of elements and properties for literal
2118 : // graphs to be considered for fast deep-copying. The limit is chosen to
2119 : // match the maximum number of inobject properties, to ensure that the
2120 : // performance of using object literals is not worse than using constructor
2121 : // functions, see crbug.com/v8/6211 for details.
2122 : static const int kMaxFastLiteralDepth = 3;
2123 : static const int kMaxFastLiteralProperties =
2124 : (JSObject::kMaxInstanceSize - JSObject::kHeaderSize) >> kPointerSizeLog2;
2125 :
2126 : // Simple accessors.
2127 478304 : void set_function_state(FunctionState* state) { function_state_ = state; }
2128 :
2129 : AstContext* ast_context() const { return ast_context_; }
2130 14627323 : void set_ast_context(AstContext* context) { ast_context_ = context; }
2131 :
2132 : // Accessors forwarded to the function state.
2133 3955703 : CompilationInfo* current_info() const {
2134 3955725 : return function_state()->compilation_info();
2135 : }
2136 7071 : AstContext* call_context() const {
2137 614809 : return function_state()->call_context();
2138 : }
2139 94355 : HBasicBlock* function_return() const {
2140 239102 : return function_state()->function_return();
2141 : }
2142 107548 : TestContext* inlined_test_context() const {
2143 107562 : return function_state()->test_context();
2144 : }
2145 : Handle<JSFunction> current_closure() const {
2146 : return current_info()->closure();
2147 : }
2148 : Handle<SharedFunctionInfo> current_shared_info() const {
2149 : return current_info()->shared_info();
2150 : }
2151 : FeedbackVector* current_feedback_vector() const {
2152 : return current_closure()->feedback_vector();
2153 : }
2154 : void ClearInlinedTestContext() {
2155 19395 : function_state()->ClearInlinedTestContext();
2156 : }
2157 82545 : LanguageMode function_language_mode() {
2158 82545 : return function_state()->compilation_info()->parse_info()->language_mode();
2159 : }
2160 :
2161 : #define FOR_EACH_HYDROGEN_INTRINSIC(F) \
2162 : F(IsSmi) \
2163 : F(IsArray) \
2164 : F(IsTypedArray) \
2165 : F(IsJSProxy) \
2166 : F(Call) \
2167 : F(ToInteger) \
2168 : F(ToObject) \
2169 : F(ToString) \
2170 : F(ToLength) \
2171 : F(ToNumber) \
2172 : F(IsJSReceiver) \
2173 : F(DebugBreakInOptimizedCode) \
2174 : F(StringCharCodeAt) \
2175 : F(SubString) \
2176 : F(DebugIsActive) \
2177 : /* Typed Arrays */ \
2178 : F(MaxSmi) \
2179 : F(TypedArrayMaxSizeInHeap) \
2180 : F(ArrayBufferViewGetByteLength) \
2181 : F(ArrayBufferViewGetByteOffset) \
2182 : F(ArrayBufferViewWasNeutered) \
2183 : F(TypedArrayGetLength) \
2184 : /* ArrayBuffer */ \
2185 : F(ArrayBufferGetByteLength) \
2186 : /* ES6 Collections */ \
2187 : F(MapClear) \
2188 : F(MapInitialize) \
2189 : F(SetClear) \
2190 : F(SetInitialize) \
2191 : F(FixedArrayGet) \
2192 : F(FixedArraySet) \
2193 : F(JSCollectionGetTable) \
2194 : F(StringGetRawHashField) \
2195 : F(TheHole) \
2196 : /* ES6 Iterators */ \
2197 : F(CreateIterResultObject) \
2198 : /* Arrays */ \
2199 : F(HasFastPackedElements)
2200 :
2201 : #define GENERATOR_DECLARATION(Name) void Generate##Name(CallRuntime* call);
2202 : FOR_EACH_HYDROGEN_INTRINSIC(GENERATOR_DECLARATION)
2203 : #undef GENERATOR_DECLARATION
2204 :
2205 : void VisitDelete(UnaryOperation* expr);
2206 : void VisitVoid(UnaryOperation* expr);
2207 : void VisitTypeof(UnaryOperation* expr);
2208 : void VisitNot(UnaryOperation* expr);
2209 :
2210 : void VisitComma(BinaryOperation* expr);
2211 : void VisitLogicalExpression(BinaryOperation* expr);
2212 : void VisitArithmeticExpression(BinaryOperation* expr);
2213 :
2214 : void VisitLoopBody(IterationStatement* stmt, BailoutId stack_check_id,
2215 : HBasicBlock* loop_entry);
2216 :
2217 : void BuildForInBody(ForInStatement* stmt, Variable* each_var,
2218 : HValue* enumerable);
2219 :
2220 : // Create a back edge in the flow graph. body_exit is the predecessor
2221 : // block and loop_entry is the successor block. loop_successor is the
2222 : // block where control flow exits the loop normally (e.g., via failure of
2223 : // the condition) and break_block is the block where control flow breaks
2224 : // from the loop. All blocks except loop_entry can be NULL. The return
2225 : // value is the new successor block which is the join of loop_successor
2226 : // and break_block, or NULL.
2227 : HBasicBlock* CreateLoop(IterationStatement* statement,
2228 : HBasicBlock* loop_entry,
2229 : HBasicBlock* body_exit,
2230 : HBasicBlock* loop_successor,
2231 : HBasicBlock* break_block);
2232 :
2233 : // Build a loop entry
2234 : HBasicBlock* BuildLoopEntry();
2235 :
2236 : // Builds a loop entry respectful of OSR requirements
2237 : HBasicBlock* BuildLoopEntry(IterationStatement* statement);
2238 :
2239 : HBasicBlock* JoinContinue(IterationStatement* statement,
2240 : BailoutId continue_id, HBasicBlock* exit_block,
2241 : HBasicBlock* continue_block);
2242 :
2243 : HValue* Top() const { return environment()->Top(); }
2244 : void Drop(int n) { environment()->Drop(n); }
2245 1078 : void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
2246 : bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var,
2247 : int index,
2248 : HEnvironment* env) {
2249 2618106 : if (!FLAG_analyze_environment_liveness) return false;
2250 : // Zapping parameters isn't safe because function.arguments can inspect them
2251 : // at any time.
2252 : return env->is_local_index(index);
2253 : }
2254 537628 : void BindIfLive(Variable* var, HValue* value) {
2255 : HEnvironment* env = environment();
2256 : int index = env->IndexFor(var);
2257 : env->Bind(index, value);
2258 537628 : if (IsEligibleForEnvironmentLivenessAnalysis(var, index, env)) {
2259 : HEnvironmentMarker* bind =
2260 506800 : Add<HEnvironmentMarker>(HEnvironmentMarker::BIND, index);
2261 : USE(bind);
2262 : #ifdef DEBUG
2263 : bind->set_closure(env->closure());
2264 : #endif
2265 : }
2266 537628 : }
2267 2080478 : HValue* LookupAndMakeLive(Variable* var) {
2268 : HEnvironment* env = environment();
2269 : int index = env->IndexFor(var);
2270 2080478 : if (IsEligibleForEnvironmentLivenessAnalysis(var, index, env)) {
2271 : HEnvironmentMarker* lookup =
2272 779732 : Add<HEnvironmentMarker>(HEnvironmentMarker::LOOKUP, index);
2273 : USE(lookup);
2274 : #ifdef DEBUG
2275 : lookup->set_closure(env->closure());
2276 : #endif
2277 : }
2278 2080477 : return env->Lookup(index);
2279 : }
2280 :
2281 : // The value of the arguments object is allowed in some but not most value
2282 : // contexts. (It's allowed in all effect contexts and disallowed in all
2283 : // test contexts.)
2284 : void VisitForValue(Expression* expr,
2285 : ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
2286 : void VisitForTypeOf(Expression* expr);
2287 : void VisitForEffect(Expression* expr);
2288 : void VisitForControl(Expression* expr,
2289 : HBasicBlock* true_block,
2290 : HBasicBlock* false_block);
2291 :
2292 : // Visit a list of expressions from left to right, each in a value context.
2293 : void VisitExpressions(ZoneList<Expression*>* exprs);
2294 : void VisitExpressions(ZoneList<Expression*>* exprs,
2295 : ArgumentsAllowedFlag flag);
2296 :
2297 : // Remove the arguments from the bailout environment and emit instructions
2298 : // to push them as outgoing parameters.
2299 : template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
2300 : void PushArgumentsFromEnvironment(int count);
2301 :
2302 : void SetUpScope(DeclarationScope* scope);
2303 : void VisitStatements(ZoneList<Statement*>* statements);
2304 :
2305 : #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
2306 : AST_NODE_LIST(DECLARE_VISIT)
2307 : #undef DECLARE_VISIT
2308 :
2309 : private:
2310 : bool CanInlineGlobalPropertyAccess(Variable* var, LookupIterator* it,
2311 : PropertyAccessType access_type);
2312 :
2313 : bool CanInlineGlobalPropertyAccess(LookupIterator* it,
2314 : PropertyAccessType access_type);
2315 :
2316 : void InlineGlobalPropertyLoad(LookupIterator* it, BailoutId ast_id);
2317 : HInstruction* InlineGlobalPropertyStore(LookupIterator* it, HValue* value,
2318 : BailoutId ast_id);
2319 :
2320 : void EnsureArgumentsArePushedForAccess();
2321 : bool TryArgumentsAccess(Property* expr);
2322 :
2323 : // Shared code for .call and .apply optimizations.
2324 : void HandleIndirectCall(Call* expr, HValue* function, int arguments_count);
2325 : // Try to optimize indirect calls such as fun.apply(receiver, arguments)
2326 : // or fun.call(...).
2327 : bool TryIndirectCall(Call* expr);
2328 : void BuildFunctionApply(Call* expr);
2329 : void BuildFunctionCall(Call* expr);
2330 :
2331 : template <class T>
2332 : bool TryHandleArrayCall(T* expr, HValue* function);
2333 :
2334 : enum ArrayIndexOfMode { kFirstIndexOf, kLastIndexOf };
2335 : HValue* BuildArrayIndexOf(HValue* receiver,
2336 : HValue* search_element,
2337 : ElementsKind kind,
2338 : ArrayIndexOfMode mode);
2339 :
2340 : HValue* ImplicitReceiverFor(HValue* function,
2341 : Handle<JSFunction> target);
2342 :
2343 : int InliningAstSize(Handle<JSFunction> target);
2344 : bool TryInline(Handle<JSFunction> target, int arguments_count,
2345 : HValue* implicit_return_value, BailoutId ast_id,
2346 : BailoutId return_id, InliningKind inlining_kind,
2347 : TailCallMode syntactic_tail_call_mode);
2348 :
2349 : bool TryInlineCall(Call* expr);
2350 : bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value);
2351 : bool TryInlineGetter(Handle<Object> getter, Handle<Map> receiver_map,
2352 : BailoutId ast_id, BailoutId return_id);
2353 : bool TryInlineSetter(Handle<Object> setter, Handle<Map> receiver_map,
2354 : BailoutId id, BailoutId assignment_id,
2355 : HValue* implicit_return_value);
2356 : bool TryInlineIndirectCall(Handle<JSFunction> function, Call* expr,
2357 : int arguments_count);
2358 : bool TryInlineBuiltinGetterCall(Handle<JSFunction> function,
2359 : Handle<Map> receiver_map, BailoutId ast_id);
2360 : bool TryInlineBuiltinMethodCall(Handle<JSFunction> function,
2361 : Handle<Map> receiver_map, BailoutId ast_id,
2362 : int args_count_no_receiver);
2363 : bool TryInlineBuiltinFunctionCall(Call* expr);
2364 : enum ApiCallType {
2365 : kCallApiFunction,
2366 : kCallApiMethod,
2367 : kCallApiGetter,
2368 : kCallApiSetter
2369 : };
2370 : bool TryInlineApiMethodCall(Call* expr,
2371 : HValue* receiver,
2372 : SmallMapList* receiver_types);
2373 : bool TryInlineApiFunctionCall(Call* expr, HValue* receiver);
2374 : bool TryInlineApiGetter(Handle<Object> function, Handle<Map> receiver_map,
2375 : BailoutId ast_id);
2376 : bool TryInlineApiSetter(Handle<Object> function, Handle<Map> receiver_map,
2377 : BailoutId ast_id);
2378 : bool TryInlineApiCall(Handle<Object> function, HValue* receiver,
2379 : SmallMapList* receiver_maps, int argc, BailoutId ast_id,
2380 : ApiCallType call_type,
2381 : TailCallMode syntactic_tail_call_mode);
2382 : static bool IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map);
2383 : static bool CanInlineArrayResizeOperation(Handle<Map> receiver_map);
2384 : static bool NoElementsInPrototypeChain(Handle<Map> receiver_map);
2385 :
2386 : // If --trace-inlining, print a line of the inlining trace. Inlining
2387 : // succeeded if the reason string is NULL and failed if there is a
2388 : // non-NULL reason string.
2389 : void TraceInline(Handle<JSFunction> target, Handle<JSFunction> caller,
2390 : const char* failure_reason,
2391 : TailCallMode tail_call_mode = TailCallMode::kDisallow);
2392 :
2393 : void HandleGlobalVariableAssignment(Variable* var, HValue* value,
2394 : FeedbackSlot slot, BailoutId ast_id);
2395 :
2396 : void HandlePropertyAssignment(Assignment* expr);
2397 : void HandleCompoundAssignment(Assignment* expr);
2398 : void HandlePolymorphicNamedFieldAccess(PropertyAccessType access_type,
2399 : Expression* expr, FeedbackSlot slot,
2400 : BailoutId ast_id, BailoutId return_id,
2401 : HValue* object, HValue* value,
2402 : SmallMapList* types,
2403 : Handle<Name> name);
2404 :
2405 : HValue* BuildAllocateExternalElements(
2406 : ExternalArrayType array_type,
2407 : bool is_zero_byte_offset,
2408 : HValue* buffer, HValue* byte_offset, HValue* length);
2409 : HValue* BuildAllocateFixedTypedArray(ExternalArrayType array_type,
2410 : size_t element_size,
2411 : ElementsKind fixed_elements_kind,
2412 : HValue* byte_length, HValue* length,
2413 : bool initialize);
2414 :
2415 : // TODO(adamk): Move all OrderedHashTable functions to their own class.
2416 : HValue* BuildOrderedHashTableHashToBucket(HValue* hash, HValue* num_buckets);
2417 : template <typename CollectionType>
2418 : HValue* BuildOrderedHashTableHashToEntry(HValue* table, HValue* hash,
2419 : HValue* num_buckets);
2420 : template <typename CollectionType>
2421 : HValue* BuildOrderedHashTableEntryToIndex(HValue* entry, HValue* num_buckets);
2422 : template <typename CollectionType>
2423 : HValue* BuildOrderedHashTableFindEntry(HValue* table, HValue* key,
2424 : HValue* hash);
2425 : template <typename CollectionType>
2426 : HValue* BuildOrderedHashTableAddEntry(HValue* table, HValue* key,
2427 : HValue* hash,
2428 : HIfContinuation* join_continuation);
2429 : template <typename CollectionType>
2430 : HValue* BuildAllocateOrderedHashTable();
2431 : template <typename CollectionType>
2432 : void BuildOrderedHashTableClear(HValue* receiver);
2433 : template <typename CollectionType>
2434 : void BuildJSCollectionDelete(CallRuntime* call,
2435 : const Runtime::Function* c_function);
2436 : template <typename CollectionType>
2437 : void BuildJSCollectionHas(CallRuntime* call,
2438 : const Runtime::Function* c_function);
2439 : HValue* BuildStringHashLoadIfIsStringAndHashComputed(
2440 : HValue* object, HIfContinuation* continuation);
2441 :
2442 209503 : Handle<JSFunction> array_function() {
2443 628509 : return handle(isolate()->native_context()->array_function());
2444 : }
2445 :
2446 : bool TryInlineArrayCall(Expression* expression, int argument_count,
2447 : Handle<AllocationSite> site);
2448 :
2449 : void BuildInitializeInobjectProperties(HValue* receiver,
2450 : Handle<Map> initial_map);
2451 :
2452 : class PropertyAccessInfo {
2453 : public:
2454 348175 : PropertyAccessInfo(HOptimizedGraphBuilder* builder,
2455 : PropertyAccessType access_type, Handle<Map> map,
2456 : Handle<Name> name)
2457 : : builder_(builder),
2458 : access_type_(access_type),
2459 : map_(map),
2460 : name_(isolate()->factory()->InternalizeName(name)),
2461 : field_type_(HType::Tagged()),
2462 : access_(HObjectAccess::ForMap()),
2463 : lookup_type_(NOT_FOUND),
2464 : details_(PropertyDetails::Empty()),
2465 1392700 : store_mode_(STORE_TO_INITIALIZED_ENTRY) {}
2466 :
2467 : // Ensure the full store is performed.
2468 : void MarkAsInitializingStore() {
2469 : DCHECK_EQ(STORE, access_type_);
2470 22666 : store_mode_ = INITIALIZING_STORE;
2471 : }
2472 :
2473 : StoreFieldOrKeyedMode StoreMode() {
2474 : DCHECK_EQ(STORE, access_type_);
2475 : return store_mode_;
2476 : }
2477 :
2478 : // Checkes whether this PropertyAccessInfo can be handled as a monomorphic
2479 : // load named. It additionally fills in the fields necessary to generate the
2480 : // lookup code.
2481 : bool CanAccessMonomorphic();
2482 :
2483 : // Checks whether all types behave uniform when loading name. If all maps
2484 : // behave the same, a single monomorphic load instruction can be emitted,
2485 : // guarded by a single map-checks instruction that whether the receiver is
2486 : // an instance of any of the types.
2487 : // This method skips the first type in types, assuming that this
2488 : // PropertyAccessInfo is built for types->first().
2489 : bool CanAccessAsMonomorphic(SmallMapList* types);
2490 :
2491 : bool NeedsWrappingFor(Handle<JSFunction> target) const;
2492 :
2493 : Handle<Map> map();
2494 : Handle<Name> name() const { return name_; }
2495 :
2496 : bool IsJSObjectFieldAccessor() {
2497 : int offset; // unused
2498 328744 : return Accessors::IsJSObjectFieldAccessor(map_, name_, &offset);
2499 : }
2500 :
2501 482976 : bool GetJSObjectFieldAccess(HObjectAccess* access) {
2502 : int offset;
2503 482976 : if (Accessors::IsJSObjectFieldAccessor(map_, name_, &offset)) {
2504 35418 : if (IsStringType()) {
2505 : DCHECK(Name::Equals(isolate()->factory()->length_string(), name_));
2506 10180 : *access = HObjectAccess::ForStringLength();
2507 25238 : } else if (IsArrayType()) {
2508 : DCHECK(Name::Equals(isolate()->factory()->length_string(), name_));
2509 25238 : *access = HObjectAccess::ForArrayLength(map_->elements_kind());
2510 : } else {
2511 0 : *access = HObjectAccess::ForMapAndOffset(map_, offset);
2512 : }
2513 : return true;
2514 : }
2515 : return false;
2516 : }
2517 :
2518 : bool has_holder() { return !holder_.is_null(); }
2519 24248 : bool IsLoad() const { return access_type_ == LOAD; }
2520 :
2521 1106257 : Isolate* isolate() const { return builder_->isolate(); }
2522 : Handle<JSObject> holder() { return holder_; }
2523 : Handle<Object> accessor() { return accessor_; }
2524 : Handle<Object> constant() { return constant_; }
2525 : Handle<Map> transition() { return transition_; }
2526 : SmallMapList* field_maps() { return &field_maps_; }
2527 : HType field_type() const { return field_type_; }
2528 : HObjectAccess access() { return access_; }
2529 :
2530 : bool IsFound() const { return lookup_type_ != NOT_FOUND; }
2531 34687 : bool IsProperty() const { return IsFound() && !IsTransition(); }
2532 21285 : bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; }
2533 : // TODO(ishell): rename to IsDataConstant() once constant field tracking
2534 : // is done.
2535 : bool IsDataConstantField() const {
2536 : return lookup_type_ == DESCRIPTOR_TYPE && details_.kind() == kData &&
2537 : details_.location() == kField && details_.constness() == kConst;
2538 : }
2539 : bool IsData() const {
2540 1462541 : return lookup_type_ == DESCRIPTOR_TYPE && details_.kind() == kData &&
2541 : details_.location() == kField;
2542 : }
2543 : bool IsDataConstant() const {
2544 682504 : return lookup_type_ == DESCRIPTOR_TYPE && details_.kind() == kData &&
2545 : details_.location() == kDescriptor;
2546 : }
2547 16976 : bool IsAccessorConstant() const {
2548 819594 : return !IsTransition() && details_.kind() == kAccessor &&
2549 : details_.location() == kDescriptor;
2550 : }
2551 : bool IsConfigurable() const { return details_.IsConfigurable(); }
2552 : bool IsReadOnly() const { return details_.IsReadOnly(); }
2553 :
2554 114296 : bool IsStringType() { return map_->instance_type() < FIRST_NONSTRING_TYPE; }
2555 : bool IsNumberType() { return map_->instance_type() == HEAP_NUMBER_TYPE; }
2556 31580 : bool IsValueWrapped() { return IsStringType() || IsNumberType(); }
2557 : bool IsArrayType() { return map_->instance_type() == JS_ARRAY_TYPE; }
2558 :
2559 : private:
2560 200703 : Handle<Object> GetConstantFromMap(Handle<Map> map) const {
2561 : DCHECK_EQ(DESCRIPTOR_TYPE, lookup_type_);
2562 : DCHECK(number_ < map->NumberOfOwnDescriptors());
2563 401406 : return handle(map->instance_descriptors()->GetValue(number_), isolate());
2564 : }
2565 : Handle<Object> GetAccessorsFromMap(Handle<Map> map) const {
2566 7922 : return GetConstantFromMap(map);
2567 : }
2568 : Handle<FieldType> GetFieldTypeFromMap(Handle<Map> map) const;
2569 11950 : Handle<Map> GetFieldOwnerFromMap(Handle<Map> map) const {
2570 : DCHECK(IsFound());
2571 : DCHECK(number_ < map->NumberOfOwnDescriptors());
2572 35850 : return handle(map->FindFieldOwner(number_));
2573 : }
2574 91509 : int GetLocalFieldIndexFromMap(Handle<Map> map) const {
2575 : DCHECK(lookup_type_ == DESCRIPTOR_TYPE ||
2576 : lookup_type_ == TRANSITION_TYPE);
2577 : DCHECK(number_ < map->NumberOfOwnDescriptors());
2578 91509 : int field_index = map->instance_descriptors()->GetFieldIndex(number_);
2579 91509 : return field_index - map->GetInObjectProperties();
2580 : }
2581 :
2582 844490 : void LookupDescriptor(Map* map, Name* name) {
2583 : DescriptorArray* descriptors = map->instance_descriptors();
2584 : int number = descriptors->SearchWithCache(isolate(), name, map);
2585 844490 : if (number == DescriptorArray::kNotFound) return NotFound();
2586 292260 : lookup_type_ = DESCRIPTOR_TYPE;
2587 292260 : details_ = descriptors->GetDetails(number);
2588 292260 : number_ = number;
2589 : }
2590 16838 : void LookupTransition(Map* map, Name* name, PropertyAttributes attributes) {
2591 : Map* target =
2592 16838 : TransitionArray::SearchTransition(map, kData, name, attributes);
2593 33676 : if (target == NULL) return NotFound();
2594 16532 : lookup_type_ = TRANSITION_TYPE;
2595 16532 : transition_ = handle(target);
2596 16532 : number_ = transition_->LastAdded();
2597 16532 : details_ = transition_->instance_descriptors()->GetDetails(number_);
2598 : MarkAsInitializingStore();
2599 : }
2600 : void NotFound() {
2601 148968 : lookup_type_ = NOT_FOUND;
2602 148968 : details_ = PropertyDetails::Empty();
2603 : }
2604 : Representation representation() const {
2605 : DCHECK(IsFound());
2606 : return details_.representation();
2607 : }
2608 16838 : bool IsTransitionToData() const {
2609 49902 : return IsTransition() && details_.kind() == kData &&
2610 : details_.location() == kField;
2611 : }
2612 :
2613 23989 : Zone* zone() { return builder_->zone(); }
2614 11950 : CompilationInfo* top_info() { return builder_->top_info(); }
2615 : CompilationInfo* current_info() { return builder_->current_info(); }
2616 :
2617 : bool LoadResult(Handle<Map> map);
2618 : bool LoadFieldMaps(Handle<Map> map);
2619 : bool LookupDescriptor();
2620 : bool LookupInPrototypes();
2621 : bool IsIntegerIndexedExotic();
2622 : bool IsCompatible(PropertyAccessInfo* other);
2623 :
2624 3204 : void GeneralizeRepresentation(Representation r) {
2625 : access_ = access_.WithRepresentation(
2626 6408 : access_.representation().generalize(r));
2627 3204 : }
2628 :
2629 : HOptimizedGraphBuilder* builder_;
2630 : PropertyAccessType access_type_;
2631 : Handle<Map> map_;
2632 : Handle<Name> name_;
2633 : Handle<JSObject> holder_;
2634 : Handle<Object> accessor_;
2635 : Handle<JSObject> api_holder_;
2636 : Handle<Object> constant_;
2637 : SmallMapList field_maps_;
2638 : HType field_type_;
2639 : HObjectAccess access_;
2640 :
2641 : enum { NOT_FOUND, DESCRIPTOR_TYPE, TRANSITION_TYPE } lookup_type_;
2642 : Handle<Map> transition_;
2643 : int number_;
2644 : PropertyDetails details_;
2645 : StoreFieldOrKeyedMode store_mode_;
2646 : };
2647 :
2648 : HValue* BuildMonomorphicAccess(PropertyAccessInfo* info, HValue* object,
2649 : HValue* checked_object, HValue* value,
2650 : BailoutId ast_id, BailoutId return_id,
2651 : bool can_inline_accessor = true);
2652 :
2653 : HValue* BuildNamedAccess(PropertyAccessType access, BailoutId ast_id,
2654 : BailoutId reutrn_id, Expression* expr,
2655 : FeedbackSlot slot, HValue* object, Handle<Name> name,
2656 : HValue* value, bool is_uninitialized = false);
2657 :
2658 : void HandlePolymorphicCallNamed(Call* expr,
2659 : HValue* receiver,
2660 : SmallMapList* types,
2661 : Handle<String> name);
2662 : void HandleLiteralCompareTypeof(CompareOperation* expr,
2663 : Expression* sub_expr,
2664 : Handle<String> check);
2665 : void HandleLiteralCompareNil(CompareOperation* expr,
2666 : Expression* sub_expr,
2667 : NilValue nil);
2668 :
2669 : enum PushBeforeSimulateBehavior {
2670 : PUSH_BEFORE_SIMULATE,
2671 : NO_PUSH_BEFORE_SIMULATE
2672 : };
2673 :
2674 : HControlInstruction* BuildCompareInstruction(
2675 : Token::Value op, HValue* left, HValue* right, AstType* left_type,
2676 : AstType* right_type, AstType* combined_type, SourcePosition left_position,
2677 : SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result,
2678 : BailoutId bailout_id);
2679 :
2680 : HInstruction* BuildStringCharCodeAt(HValue* string,
2681 : HValue* index);
2682 :
2683 : HValue* BuildBinaryOperation(
2684 : BinaryOperation* expr,
2685 : HValue* left,
2686 : HValue* right,
2687 : PushBeforeSimulateBehavior push_sim_result);
2688 : HInstruction* BuildIncrement(CountOperation* expr);
2689 : HInstruction* BuildKeyedGeneric(PropertyAccessType access_type,
2690 : Expression* expr, FeedbackSlot slot,
2691 : HValue* object, HValue* key, HValue* value);
2692 :
2693 : HInstruction* TryBuildConsolidatedElementLoad(HValue* object,
2694 : HValue* key,
2695 : HValue* val,
2696 : SmallMapList* maps);
2697 :
2698 : LoadKeyedHoleMode BuildKeyedHoleMode(Handle<Map> map);
2699 :
2700 : HInstruction* BuildMonomorphicElementAccess(HValue* object,
2701 : HValue* key,
2702 : HValue* val,
2703 : HValue* dependency,
2704 : Handle<Map> map,
2705 : PropertyAccessType access_type,
2706 : KeyedAccessStoreMode store_mode);
2707 :
2708 : HValue* HandlePolymorphicElementAccess(Expression* expr, FeedbackSlot slot,
2709 : HValue* object, HValue* key,
2710 : HValue* val, SmallMapList* maps,
2711 : PropertyAccessType access_type,
2712 : KeyedAccessStoreMode store_mode,
2713 : bool* has_side_effects);
2714 :
2715 : HValue* HandleKeyedElementAccess(HValue* obj, HValue* key, HValue* val,
2716 : Expression* expr, FeedbackSlot slot,
2717 : BailoutId ast_id, BailoutId return_id,
2718 : PropertyAccessType access_type,
2719 : bool* has_side_effects);
2720 :
2721 : HInstruction* BuildNamedGeneric(PropertyAccessType access, Expression* expr,
2722 : FeedbackSlot slot, HValue* object,
2723 : Handle<Name> name, HValue* value,
2724 : bool is_uninitialized = false);
2725 :
2726 : HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map);
2727 :
2728 : void BuildLoad(Property* property,
2729 : BailoutId ast_id);
2730 : void PushLoad(Property* property,
2731 : HValue* object,
2732 : HValue* key);
2733 :
2734 : void BuildStoreForEffect(Expression* expression, Property* prop,
2735 : FeedbackSlot slot, BailoutId ast_id,
2736 : BailoutId return_id, HValue* object, HValue* key,
2737 : HValue* value);
2738 :
2739 : void BuildStore(Expression* expression, Property* prop, FeedbackSlot slot,
2740 : BailoutId ast_id, BailoutId return_id,
2741 : bool is_uninitialized = false);
2742 :
2743 : HInstruction* BuildLoadNamedField(PropertyAccessInfo* info,
2744 : HValue* checked_object);
2745 : HValue* BuildStoreNamedField(PropertyAccessInfo* info, HValue* checked_object,
2746 : HValue* value);
2747 :
2748 : HValue* BuildContextChainWalk(Variable* var);
2749 :
2750 : HValue* AddThisFunction();
2751 : HInstruction* BuildThisFunction();
2752 :
2753 : HInstruction* BuildFastLiteral(Handle<JSObject> boilerplate_object,
2754 : AllocationSiteUsageContext* site_context);
2755 :
2756 : void BuildEmitObjectHeader(Handle<JSObject> boilerplate_object,
2757 : HInstruction* object);
2758 :
2759 : void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object,
2760 : HInstruction* object,
2761 : AllocationSiteUsageContext* site_context,
2762 : PretenureFlag pretenure_flag);
2763 :
2764 : void BuildEmitElements(Handle<JSObject> boilerplate_object,
2765 : Handle<FixedArrayBase> elements,
2766 : HValue* object_elements,
2767 : AllocationSiteUsageContext* site_context);
2768 :
2769 : void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements,
2770 : ElementsKind kind,
2771 : HValue* object_elements);
2772 :
2773 : void BuildEmitFixedArray(Handle<FixedArrayBase> elements,
2774 : ElementsKind kind,
2775 : HValue* object_elements,
2776 : AllocationSiteUsageContext* site_context);
2777 :
2778 : void AddCheckPrototypeMaps(Handle<JSObject> holder,
2779 : Handle<Map> receiver_map);
2780 :
2781 : void BuildEnsureCallable(HValue* object);
2782 :
2783 : HInstruction* NewCallFunction(HValue* function, int argument_count,
2784 : TailCallMode syntactic_tail_call_mode,
2785 : ConvertReceiverMode convert_mode,
2786 : TailCallMode tail_call_mode);
2787 :
2788 : HInstruction* NewCallFunctionViaIC(HValue* function, int argument_count,
2789 : TailCallMode syntactic_tail_call_mode,
2790 : ConvertReceiverMode convert_mode,
2791 : TailCallMode tail_call_mode,
2792 : FeedbackSlot slot);
2793 :
2794 : HInstruction* NewCallConstantFunction(Handle<JSFunction> target,
2795 : int argument_count,
2796 : TailCallMode syntactic_tail_call_mode,
2797 : TailCallMode tail_call_mode);
2798 :
2799 : bool CanBeFunctionApplyArguments(Call* expr);
2800 :
2801 : bool IsAnyParameterContextAllocated();
2802 :
2803 : // The translation state of the currently-being-translated function.
2804 : FunctionState* function_state_;
2805 :
2806 : // The base of the function state stack.
2807 : FunctionState initial_function_state_;
2808 :
2809 : // Expression context of the currently visited subexpression. NULL when
2810 : // visiting statements.
2811 : AstContext* ast_context_;
2812 :
2813 : // A stack of breakable statements entered.
2814 : BreakAndContinueScope* break_scope_;
2815 :
2816 : int inlined_count_;
2817 : ZoneList<Handle<Object> > globals_;
2818 :
2819 : bool inline_bailout_;
2820 :
2821 : HOsrBuilder* osr_;
2822 :
2823 : AstTypeBounds bounds_;
2824 :
2825 : friend class FunctionState; // Pushes and pops the state stack.
2826 : friend class AstContext; // Pushes and pops the AST context stack.
2827 : friend class HOsrBuilder;
2828 :
2829 : DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder);
2830 : };
2831 :
2832 :
2833 : Zone* AstContext::zone() const { return owner_->zone(); }
2834 :
2835 :
2836 0 : class HStatistics final : public Malloced {
2837 : public:
2838 0 : HStatistics()
2839 : : times_(5),
2840 : names_(5),
2841 : sizes_(5),
2842 : total_size_(0),
2843 0 : source_size_(0) { }
2844 :
2845 : void Initialize(CompilationInfo* info);
2846 : void Print();
2847 : void SaveTiming(const char* name, base::TimeDelta time, size_t size);
2848 :
2849 : void IncrementFullCodeGen(base::TimeDelta full_code_gen) {
2850 : full_code_gen_ += full_code_gen;
2851 : }
2852 :
2853 : void IncrementCreateGraph(base::TimeDelta delta) { create_graph_ += delta; }
2854 :
2855 : void IncrementOptimizeGraph(base::TimeDelta delta) {
2856 : optimize_graph_ += delta;
2857 : }
2858 :
2859 : void IncrementGenerateCode(base::TimeDelta delta) { generate_code_ += delta; }
2860 :
2861 : void IncrementSubtotals(base::TimeDelta create_graph,
2862 : base::TimeDelta optimize_graph,
2863 : base::TimeDelta generate_code) {
2864 : IncrementCreateGraph(create_graph);
2865 : IncrementOptimizeGraph(optimize_graph);
2866 : IncrementGenerateCode(generate_code);
2867 : }
2868 :
2869 : private:
2870 : List<base::TimeDelta> times_;
2871 : List<const char*> names_;
2872 : List<size_t> sizes_;
2873 : base::TimeDelta create_graph_;
2874 : base::TimeDelta optimize_graph_;
2875 : base::TimeDelta generate_code_;
2876 : size_t total_size_;
2877 : base::TimeDelta full_code_gen_;
2878 : double source_size_;
2879 : };
2880 :
2881 :
2882 : class HPhase : public CompilationPhase {
2883 : public:
2884 5943791 : HPhase(const char* name, HGraph* graph)
2885 : : CompilationPhase(name, graph->info()),
2886 5943791 : graph_(graph) { }
2887 : ~HPhase();
2888 :
2889 : protected:
2890 : HGraph* graph() const { return graph_; }
2891 :
2892 : private:
2893 : HGraph* graph_;
2894 :
2895 : DISALLOW_COPY_AND_ASSIGN(HPhase);
2896 : };
2897 :
2898 :
2899 : class HTracer final : public Malloced {
2900 : public:
2901 0 : explicit HTracer(int isolate_id)
2902 0 : : trace_(&string_allocator_), indent_(0) {
2903 0 : if (FLAG_trace_hydrogen_file == NULL) {
2904 : SNPrintF(filename_,
2905 : "hydrogen-%d-%d.cfg",
2906 : base::OS::GetCurrentProcessId(),
2907 0 : isolate_id);
2908 : } else {
2909 0 : StrNCpy(filename_, FLAG_trace_hydrogen_file, filename_.length());
2910 : }
2911 0 : WriteChars(filename_.start(), "", 0, false);
2912 0 : }
2913 :
2914 : void TraceCompilation(CompilationInfo* info);
2915 : void TraceHydrogen(const char* name, HGraph* graph);
2916 : void TraceLithium(const char* name, LChunk* chunk);
2917 : void TraceLiveRanges(const char* name, LAllocator* allocator);
2918 :
2919 : private:
2920 : class Tag final BASE_EMBEDDED {
2921 : public:
2922 0 : Tag(HTracer* tracer, const char* name) {
2923 0 : name_ = name;
2924 0 : tracer_ = tracer;
2925 : tracer->PrintIndent();
2926 0 : tracer->trace_.Add("begin_%s\n", name);
2927 0 : tracer->indent_++;
2928 0 : }
2929 :
2930 0 : ~Tag() {
2931 0 : tracer_->indent_--;
2932 : tracer_->PrintIndent();
2933 0 : tracer_->trace_.Add("end_%s\n", name_);
2934 : DCHECK(tracer_->indent_ >= 0);
2935 0 : tracer_->FlushToFile();
2936 0 : }
2937 :
2938 : private:
2939 : HTracer* tracer_;
2940 : const char* name_;
2941 : };
2942 :
2943 : void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
2944 : void Trace(const char* name, HGraph* graph, LChunk* chunk);
2945 : void FlushToFile();
2946 :
2947 0 : void PrintEmptyProperty(const char* name) {
2948 : PrintIndent();
2949 0 : trace_.Add("%s\n", name);
2950 0 : }
2951 :
2952 0 : void PrintStringProperty(const char* name, const char* value) {
2953 : PrintIndent();
2954 0 : trace_.Add("%s \"%s\"\n", name, value);
2955 0 : }
2956 :
2957 0 : void PrintLongProperty(const char* name, int64_t value) {
2958 : PrintIndent();
2959 0 : trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
2960 0 : }
2961 :
2962 0 : void PrintBlockProperty(const char* name, int block_id) {
2963 : PrintIndent();
2964 0 : trace_.Add("%s \"B%d\"\n", name, block_id);
2965 0 : }
2966 :
2967 0 : void PrintIntProperty(const char* name, int value) {
2968 : PrintIndent();
2969 0 : trace_.Add("%s %d\n", name, value);
2970 0 : }
2971 :
2972 : void PrintIndent() {
2973 0 : for (int i = 0; i < indent_; i++) {
2974 0 : trace_.Add(" ");
2975 : }
2976 : }
2977 :
2978 : EmbeddedVector<char, 64> filename_;
2979 : HeapStringAllocator string_allocator_;
2980 : StringStream trace_;
2981 : int indent_;
2982 : };
2983 :
2984 :
2985 : class NoObservableSideEffectsScope final {
2986 : public:
2987 : explicit NoObservableSideEffectsScope(HGraphBuilder* builder) :
2988 : builder_(builder) {
2989 766597 : builder_->graph()->IncrementInNoSideEffectsScope();
2990 : }
2991 : ~NoObservableSideEffectsScope() {
2992 766597 : builder_->graph()->DecrementInNoSideEffectsScope();
2993 : }
2994 :
2995 : private:
2996 : HGraphBuilder* builder_;
2997 : };
2998 :
2999 : class DoExpressionScope final {
3000 : public:
3001 : explicit DoExpressionScope(HOptimizedGraphBuilder* builder)
3002 : : builder_(builder) {
3003 62 : builder_->function_state()->IncrementInDoExpressionScope();
3004 : }
3005 : ~DoExpressionScope() {
3006 62 : builder_->function_state()->DecrementInDoExpressionScope();
3007 : }
3008 :
3009 : private:
3010 : HOptimizedGraphBuilder* builder_;
3011 : };
3012 :
3013 : } // namespace internal
3014 : } // namespace v8
3015 :
3016 : #endif // V8_CRANKSHAFT_HYDROGEN_H_
|