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.
8 #include "src/accessors.h"
9 #include "src/allocation.h"
11 #include "src/bailout-reason.h"
12 #include "src/compiler.h"
13 #include "src/hydrogen-instructions.h"
14 #include "src/scopes.h"
20 // Forward declarations.
25 class HLoopInformation;
33 class HBasicBlock final : public ZoneObject {
35 explicit HBasicBlock(HGraph* graph);
39 int block_id() const { return block_id_; }
40 void set_block_id(int id) { block_id_ = id; }
41 HGraph* graph() const { return graph_; }
42 Isolate* isolate() const;
43 const ZoneList<HPhi*>* phis() const { return &phis_; }
44 HInstruction* first() const { return first_; }
45 HInstruction* last() const { return last_; }
46 void set_last(HInstruction* instr) { last_ = instr; }
47 HControlInstruction* end() const { return end_; }
48 HLoopInformation* loop_information() const { return loop_information_; }
49 HLoopInformation* current_loop() const {
50 return IsLoopHeader() ? loop_information()
51 : (parent_loop_header() != NULL
52 ? parent_loop_header()->loop_information() : NULL);
54 const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; }
55 bool HasPredecessor() const { return predecessors_.length() > 0; }
56 const ZoneList<HBasicBlock*>* dominated_blocks() const {
57 return &dominated_blocks_;
59 const ZoneList<int>* deleted_phis() const {
60 return &deleted_phis_;
62 void RecordDeletedPhi(int merge_index) {
63 deleted_phis_.Add(merge_index, zone());
65 HBasicBlock* dominator() const { return dominator_; }
66 HEnvironment* last_environment() const { return last_environment_; }
67 int argument_count() const { return argument_count_; }
68 void set_argument_count(int count) { argument_count_ = count; }
69 int first_instruction_index() const { return first_instruction_index_; }
70 void set_first_instruction_index(int index) {
71 first_instruction_index_ = index;
73 int last_instruction_index() const { return last_instruction_index_; }
74 void set_last_instruction_index(int index) {
75 last_instruction_index_ = index;
77 bool is_osr_entry() { return is_osr_entry_; }
78 void set_osr_entry() { is_osr_entry_ = true; }
80 void AttachLoopInformation();
81 void DetachLoopInformation();
82 bool IsLoopHeader() const { return loop_information() != NULL; }
83 bool IsStartBlock() const { return block_id() == 0; }
84 void PostProcessLoopHeader(IterationStatement* stmt);
86 bool IsFinished() const { return end_ != NULL; }
87 void AddPhi(HPhi* phi);
88 void RemovePhi(HPhi* phi);
89 void AddInstruction(HInstruction* instr, SourcePosition position);
90 bool Dominates(HBasicBlock* other) const;
91 bool EqualToOrDominates(HBasicBlock* other) const;
92 int LoopNestingDepth() const;
94 void SetInitialEnvironment(HEnvironment* env);
95 void ClearEnvironment() {
97 DCHECK(end()->SuccessorCount() == 0);
98 last_environment_ = NULL;
100 bool HasEnvironment() const { return last_environment_ != NULL; }
101 void UpdateEnvironment(HEnvironment* env);
102 HBasicBlock* parent_loop_header() const { return parent_loop_header_; }
104 void set_parent_loop_header(HBasicBlock* block) {
105 DCHECK(parent_loop_header_ == NULL);
106 parent_loop_header_ = block;
109 bool HasParentLoopHeader() const { return parent_loop_header_ != NULL; }
111 void SetJoinId(BailoutId ast_id);
113 int PredecessorIndexOf(HBasicBlock* predecessor) const;
114 HPhi* AddNewPhi(int merged_index);
115 HSimulate* AddNewSimulate(BailoutId ast_id, SourcePosition position,
116 RemovableSimulate removable = FIXED_SIMULATE) {
117 HSimulate* instr = CreateSimulate(ast_id, removable);
118 AddInstruction(instr, position);
121 void AssignCommonDominator(HBasicBlock* other);
122 void AssignLoopSuccessorDominators();
124 // If a target block is tagged as an inline function return, all
125 // predecessors should contain the inlined exit sequence:
128 // Simulate (caller's environment)
129 // Goto (target block)
130 bool IsInlineReturnTarget() const { return is_inline_return_target_; }
131 void MarkAsInlineReturnTarget(HBasicBlock* inlined_entry_block) {
132 is_inline_return_target_ = true;
133 inlined_entry_block_ = inlined_entry_block;
135 HBasicBlock* inlined_entry_block() { return inlined_entry_block_; }
137 bool IsDeoptimizing() const {
138 return end() != NULL && end()->IsDeoptimize();
141 void MarkUnreachable();
142 bool IsUnreachable() const { return !is_reachable_; }
143 bool IsReachable() const { return is_reachable_; }
145 bool IsLoopSuccessorDominator() const {
146 return dominates_loop_successors_;
148 void MarkAsLoopSuccessorDominator() {
149 dominates_loop_successors_ = true;
152 bool IsOrdered() const { return is_ordered_; }
153 void MarkAsOrdered() { is_ordered_ = true; }
155 void MarkSuccEdgeUnreachable(int succ);
157 inline Zone* zone() const;
164 friend class HGraphBuilder;
166 HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable);
167 void Finish(HControlInstruction* last, SourcePosition position);
168 void FinishExit(HControlInstruction* instruction, SourcePosition position);
169 void Goto(HBasicBlock* block, SourcePosition position,
170 FunctionState* state = NULL, bool add_simulate = true);
171 void GotoNoSimulate(HBasicBlock* block, SourcePosition position) {
172 Goto(block, position, NULL, false);
175 // Add the inlined function exit sequence, adding an HLeaveInlined
176 // instruction and updating the bailout environment.
177 void AddLeaveInlined(HValue* return_value, FunctionState* state,
178 SourcePosition position);
181 void RegisterPredecessor(HBasicBlock* pred);
182 void AddDominatedBlock(HBasicBlock* block);
186 ZoneList<HPhi*> phis_;
187 HInstruction* first_;
189 HControlInstruction* end_;
190 HLoopInformation* loop_information_;
191 ZoneList<HBasicBlock*> predecessors_;
192 HBasicBlock* dominator_;
193 ZoneList<HBasicBlock*> dominated_blocks_;
194 HEnvironment* last_environment_;
195 // Outgoing parameter count at block exit, set during lithium translation.
197 // Instruction indices into the lithium code stream.
198 int first_instruction_index_;
199 int last_instruction_index_;
200 ZoneList<int> deleted_phis_;
201 HBasicBlock* parent_loop_header_;
202 // For blocks marked as inline return target: the block with HEnterInlined.
203 HBasicBlock* inlined_entry_block_;
204 bool is_inline_return_target_ : 1;
205 bool is_reachable_ : 1;
206 bool dominates_loop_successors_ : 1;
207 bool is_osr_entry_ : 1;
208 bool is_ordered_ : 1;
212 std::ostream& operator<<(std::ostream& os, const HBasicBlock& b);
215 class HPredecessorIterator final BASE_EMBEDDED {
217 explicit HPredecessorIterator(HBasicBlock* block)
218 : predecessor_list_(block->predecessors()), current_(0) { }
220 bool Done() { return current_ >= predecessor_list_->length(); }
221 HBasicBlock* Current() { return predecessor_list_->at(current_); }
222 void Advance() { current_++; }
225 const ZoneList<HBasicBlock*>* predecessor_list_;
230 class HInstructionIterator final BASE_EMBEDDED {
232 explicit HInstructionIterator(HBasicBlock* block)
233 : instr_(block->first()) {
234 next_ = Done() ? NULL : instr_->next();
237 inline bool Done() const { return instr_ == NULL; }
238 inline HInstruction* Current() { return instr_; }
239 inline void Advance() {
241 next_ = Done() ? NULL : instr_->next();
245 HInstruction* instr_;
250 class HLoopInformation final : public ZoneObject {
252 HLoopInformation(HBasicBlock* loop_header, Zone* zone)
253 : back_edges_(4, zone),
254 loop_header_(loop_header),
257 blocks_.Add(loop_header, zone);
259 ~HLoopInformation() {}
261 const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; }
262 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
263 HBasicBlock* loop_header() const { return loop_header_; }
264 HBasicBlock* GetLastBackEdge() const;
265 void RegisterBackEdge(HBasicBlock* block);
267 HStackCheck* stack_check() const { return stack_check_; }
268 void set_stack_check(HStackCheck* stack_check) {
269 stack_check_ = stack_check;
272 bool IsNestedInThisLoop(HLoopInformation* other) {
273 while (other != NULL) {
277 other = other->parent_loop();
281 HLoopInformation* parent_loop() {
282 HBasicBlock* parent_header = loop_header()->parent_loop_header();
283 return parent_header != NULL ? parent_header->loop_information() : NULL;
287 void AddBlock(HBasicBlock* block);
289 ZoneList<HBasicBlock*> back_edges_;
290 HBasicBlock* loop_header_;
291 ZoneList<HBasicBlock*> blocks_;
292 HStackCheck* stack_check_;
296 class BoundsCheckTable;
297 class InductionVariableBlocksTable;
298 class HGraph final : public ZoneObject {
300 explicit HGraph(CompilationInfo* info);
302 Isolate* isolate() const { return isolate_; }
303 Zone* zone() const { return zone_; }
304 CompilationInfo* info() const { return info_; }
306 const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
307 const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
308 HBasicBlock* entry_block() const { return entry_block_; }
309 HEnvironment* start_environment() const { return start_environment_; }
311 void FinalizeUniqueness();
313 void AssignDominators();
314 void RestoreActualValues();
316 // Returns false if there are phi-uses of the arguments-object
317 // which are not supported by the optimizing compiler.
318 bool CheckArgumentsPhiUses();
320 // Returns false if there are phi-uses of an uninitialized const
321 // which are not supported by the optimizing compiler.
322 bool CheckConstPhiUses();
326 HConstant* GetConstantUndefined();
327 HConstant* GetConstant0();
328 HConstant* GetConstant1();
329 HConstant* GetConstantMinus1();
330 HConstant* GetConstantTrue();
331 HConstant* GetConstantFalse();
332 HConstant* GetConstantBool(bool value);
333 HConstant* GetConstantHole();
334 HConstant* GetConstantNull();
335 HConstant* GetInvalidContext();
337 bool IsConstantUndefined(HConstant* constant);
338 bool IsConstant0(HConstant* constant);
339 bool IsConstant1(HConstant* constant);
340 bool IsConstantMinus1(HConstant* constant);
341 bool IsConstantTrue(HConstant* constant);
342 bool IsConstantFalse(HConstant* constant);
343 bool IsConstantHole(HConstant* constant);
344 bool IsConstantNull(HConstant* constant);
345 bool IsStandardConstant(HConstant* constant);
347 HBasicBlock* CreateBasicBlock();
348 HArgumentsObject* GetArgumentsObject() const {
349 return arguments_object_.get();
352 void SetArgumentsObject(HArgumentsObject* object) {
353 arguments_object_.set(object);
356 int GetMaximumValueID() const { return values_.length(); }
357 int GetNextBlockID() { return next_block_id_++; }
358 int GetNextValueID(HValue* value) {
359 DCHECK(!disallow_adding_new_values_);
360 values_.Add(value, zone());
361 return values_.length() - 1;
363 HValue* LookupValue(int id) const {
364 if (id >= 0 && id < values_.length()) return values_[id];
367 void DisallowAddingNewValues() {
368 disallow_adding_new_values_ = true;
371 bool Optimize(BailoutReason* bailout_reason);
374 void Verify(bool do_full_verify) const;
381 void set_osr(HOsrBuilder* osr) {
389 int update_type_change_checksum(int delta) {
390 type_change_checksum_ += delta;
391 return type_change_checksum_;
394 void update_maximum_environment_size(int environment_size) {
395 if (environment_size > maximum_environment_size_) {
396 maximum_environment_size_ = environment_size;
399 int maximum_environment_size() { return maximum_environment_size_; }
401 bool use_optimistic_licm() {
402 return use_optimistic_licm_;
405 void set_use_optimistic_licm(bool value) {
406 use_optimistic_licm_ = value;
409 void MarkRecursive() { is_recursive_ = true; }
410 bool is_recursive() const { return is_recursive_; }
412 void MarkDependsOnEmptyArrayProtoElements() {
413 // Add map dependency if not already added.
414 if (depends_on_empty_array_proto_elements_) return;
415 info()->dependencies()->AssumePropertyCell(
416 isolate()->factory()->array_protector());
417 depends_on_empty_array_proto_elements_ = true;
420 bool depends_on_empty_array_proto_elements() {
421 return depends_on_empty_array_proto_elements_;
424 bool has_uint32_instructions() {
425 DCHECK(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
426 return uint32_instructions_ != NULL;
429 ZoneList<HInstruction*>* uint32_instructions() {
430 DCHECK(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
431 return uint32_instructions_;
434 void RecordUint32Instruction(HInstruction* instr) {
435 DCHECK(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
436 if (uint32_instructions_ == NULL) {
437 uint32_instructions_ = new(zone()) ZoneList<HInstruction*>(4, zone());
439 uint32_instructions_->Add(instr, zone());
442 void IncrementInNoSideEffectsScope() { no_side_effects_scope_count_++; }
443 void DecrementInNoSideEffectsScope() { no_side_effects_scope_count_--; }
444 bool IsInsideNoSideEffectsScope() { return no_side_effects_scope_count_ > 0; }
446 // If we are tracking source positions then this function assigns a unique
447 // identifier to each inlining and dumps function source if it was inlined
448 // for the first time during the current optimization.
449 int TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
450 SourcePosition position);
452 // Converts given SourcePosition to the absolute offset from the start of
453 // the corresponding script.
454 int SourcePositionToScriptPosition(SourcePosition position);
457 HConstant* ReinsertConstantIfNecessary(HConstant* constant);
458 HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
459 int32_t integer_value);
461 template<class Phase>
469 HBasicBlock* entry_block_;
470 HEnvironment* start_environment_;
471 ZoneList<HBasicBlock*> blocks_;
472 ZoneList<HValue*> values_;
473 ZoneList<HPhi*>* phi_list_;
474 ZoneList<HInstruction*>* uint32_instructions_;
475 SetOncePointer<HConstant> constant_undefined_;
476 SetOncePointer<HConstant> constant_0_;
477 SetOncePointer<HConstant> constant_1_;
478 SetOncePointer<HConstant> constant_minus1_;
479 SetOncePointer<HConstant> constant_true_;
480 SetOncePointer<HConstant> constant_false_;
481 SetOncePointer<HConstant> constant_the_hole_;
482 SetOncePointer<HConstant> constant_null_;
483 SetOncePointer<HConstant> constant_invalid_context_;
484 SetOncePointer<HArgumentsObject> arguments_object_;
488 CompilationInfo* info_;
492 bool use_optimistic_licm_;
493 bool depends_on_empty_array_proto_elements_;
494 int type_change_checksum_;
495 int maximum_environment_size_;
496 int no_side_effects_scope_count_;
497 bool disallow_adding_new_values_;
499 DISALLOW_COPY_AND_ASSIGN(HGraph);
503 Zone* HBasicBlock::zone() const { return graph_->zone(); }
506 // Type of stack frame an environment might refer to.
517 class HEnvironment final : public ZoneObject {
519 HEnvironment(HEnvironment* outer,
521 Handle<JSFunction> closure,
524 HEnvironment(Zone* zone, int parameter_count);
526 HEnvironment* arguments_environment() {
527 return outer()->frame_type() == ARGUMENTS_ADAPTOR ? outer() : this;
531 Handle<JSFunction> closure() const { return closure_; }
532 const ZoneList<HValue*>* values() const { return &values_; }
533 const GrowableBitVector* assigned_variables() const {
534 return &assigned_variables_;
536 FrameType frame_type() const { return frame_type_; }
537 int parameter_count() const { return parameter_count_; }
538 int specials_count() const { return specials_count_; }
539 int local_count() const { return local_count_; }
540 HEnvironment* outer() const { return outer_; }
541 int pop_count() const { return pop_count_; }
542 int push_count() const { return push_count_; }
544 BailoutId ast_id() const { return ast_id_; }
545 void set_ast_id(BailoutId id) { ast_id_ = id; }
547 HEnterInlined* entry() const { return entry_; }
548 void set_entry(HEnterInlined* entry) { entry_ = entry; }
550 int length() const { return values_.length(); }
552 int first_expression_index() const {
553 return parameter_count() + specials_count() + local_count();
556 int first_local_index() const {
557 return parameter_count() + specials_count();
560 void Bind(Variable* variable, HValue* value) {
561 Bind(IndexFor(variable), value);
564 void Bind(int index, HValue* value);
566 void BindContext(HValue* value) {
567 Bind(parameter_count(), value);
570 HValue* Lookup(Variable* variable) const {
571 return Lookup(IndexFor(variable));
574 HValue* Lookup(int index) const {
575 HValue* result = values_[index];
576 DCHECK(result != NULL);
580 HValue* context() const {
581 // Return first special.
582 return Lookup(parameter_count());
585 void Push(HValue* value) {
586 DCHECK(value != NULL);
588 values_.Add(value, zone());
592 DCHECK(!ExpressionStackIsEmpty());
593 if (push_count_ > 0) {
598 return values_.RemoveLast();
601 void Drop(int count);
603 HValue* Top() const { return ExpressionStackAt(0); }
605 bool ExpressionStackIsEmpty() const;
607 HValue* ExpressionStackAt(int index_from_top) const {
608 int index = length() - index_from_top - 1;
609 DCHECK(HasExpressionAt(index));
610 return values_[index];
613 void SetExpressionStackAt(int index_from_top, HValue* value);
614 HValue* RemoveExpressionStackAt(int index_from_top);
616 HEnvironment* Copy() const;
617 HEnvironment* CopyWithoutHistory() const;
618 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const;
620 // Create an "inlined version" of this environment, where the original
621 // environment is the outer environment but the top expression stack
622 // elements are moved to an inner environment as parameters.
623 HEnvironment* CopyForInlining(Handle<JSFunction> target,
625 FunctionLiteral* function,
626 HConstant* undefined,
627 InliningKind inlining_kind) const;
629 HEnvironment* DiscardInlined(bool drop_extra) {
630 HEnvironment* outer = outer_;
631 while (outer->frame_type() != JS_FUNCTION) outer = outer->outer_;
632 if (drop_extra) outer->Drop(1);
636 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
638 void ClearHistory() {
641 assigned_variables_.Clear();
644 void SetValueAt(int index, HValue* value) {
645 DCHECK(index < length());
646 values_[index] = value;
649 // Map a variable to an environment index. Parameter indices are shifted
650 // by 1 (receiver is parameter index -1 but environment index 0).
651 // Stack-allocated local indices are shifted by the number of parameters.
652 int IndexFor(Variable* variable) const {
653 DCHECK(variable->IsStackAllocated());
654 int shift = variable->IsParameter()
656 : parameter_count_ + specials_count_;
657 return variable->index() + shift;
660 bool is_local_index(int i) const {
661 return i >= first_local_index() && i < first_expression_index();
664 bool is_parameter_index(int i) const {
665 return i >= 0 && i < parameter_count();
668 bool is_special_index(int i) const {
669 return i >= parameter_count() && i < parameter_count() + specials_count();
672 Zone* zone() const { return zone_; }
675 HEnvironment(const HEnvironment* other, Zone* zone);
677 HEnvironment(HEnvironment* outer,
678 Handle<JSFunction> closure,
679 FrameType frame_type,
683 // Create an artificial stub environment (e.g. for argument adaptor or
684 // constructor stub).
685 HEnvironment* CreateStubEnvironment(HEnvironment* outer,
686 Handle<JSFunction> target,
687 FrameType frame_type,
688 int arguments) const;
690 // True if index is included in the expression stack part of the environment.
691 bool HasExpressionAt(int index) const;
693 void Initialize(int parameter_count, int local_count, int stack_height);
694 void Initialize(const HEnvironment* other);
696 Handle<JSFunction> closure_;
697 // Value array [parameters] [specials] [locals] [temporaries].
698 ZoneList<HValue*> values_;
699 GrowableBitVector assigned_variables_;
700 FrameType frame_type_;
701 int parameter_count_;
704 HEnvironment* outer_;
705 HEnterInlined* entry_;
713 std::ostream& operator<<(std::ostream& os, const HEnvironment& env);
716 class HOptimizedGraphBuilder;
718 enum ArgumentsAllowedFlag {
719 ARGUMENTS_NOT_ALLOWED,
725 class HIfContinuation;
727 // This class is not BASE_EMBEDDED because our inlining implementation uses
731 bool IsEffect() const { return kind_ == Expression::kEffect; }
732 bool IsValue() const { return kind_ == Expression::kValue; }
733 bool IsTest() const { return kind_ == Expression::kTest; }
735 // 'Fill' this context with a hydrogen value. The value is assumed to
736 // have already been inserted in the instruction stream (or not need to
737 // be, e.g., HPhi). Call this function in tail position in the Visit
738 // functions for expressions.
739 virtual void ReturnValue(HValue* value) = 0;
741 // Add a hydrogen instruction to the instruction stream (recording an
742 // environment simulation if necessary) and then fill this context with
743 // the instruction as value.
744 virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id) = 0;
746 // Finishes the current basic block and materialize a boolean for
747 // value context, nothing for effect, generate a branch for test context.
748 // Call this function in tail position in the Visit functions for
750 virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id) = 0;
752 // Finishes the current basic block and materialize a boolean for
753 // value context, nothing for effect, generate a branch for test context.
754 // Call this function in tail position in the Visit functions for
755 // expressions that use an IfBuilder.
756 virtual void ReturnContinuation(HIfContinuation* continuation,
757 BailoutId ast_id) = 0;
759 void set_typeof_mode(TypeofMode typeof_mode) { typeof_mode_ = typeof_mode; }
760 TypeofMode typeof_mode() { return typeof_mode_; }
763 AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind);
764 virtual ~AstContext();
766 HOptimizedGraphBuilder* owner() const { return owner_; }
768 inline Zone* zone() const;
770 // We want to be able to assert, in a context-specific way, that the stack
771 // height makes sense when the context is filled.
773 int original_length_;
777 HOptimizedGraphBuilder* owner_;
778 Expression::Context kind_;
780 TypeofMode typeof_mode_;
784 class EffectContext final : public AstContext {
786 explicit EffectContext(HOptimizedGraphBuilder* owner)
787 : AstContext(owner, Expression::kEffect) {
789 virtual ~EffectContext();
791 void ReturnValue(HValue* value) override;
792 virtual void ReturnInstruction(HInstruction* instr,
793 BailoutId ast_id) override;
794 virtual void ReturnControl(HControlInstruction* instr,
795 BailoutId ast_id) override;
796 virtual void ReturnContinuation(HIfContinuation* continuation,
797 BailoutId ast_id) override;
801 class ValueContext final : public AstContext {
803 ValueContext(HOptimizedGraphBuilder* owner, ArgumentsAllowedFlag flag)
804 : AstContext(owner, Expression::kValue), flag_(flag) {
806 virtual ~ValueContext();
808 void ReturnValue(HValue* value) override;
809 virtual void ReturnInstruction(HInstruction* instr,
810 BailoutId ast_id) override;
811 virtual void ReturnControl(HControlInstruction* instr,
812 BailoutId ast_id) override;
813 virtual void ReturnContinuation(HIfContinuation* continuation,
814 BailoutId ast_id) override;
816 bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
819 ArgumentsAllowedFlag flag_;
823 class TestContext final : public AstContext {
825 TestContext(HOptimizedGraphBuilder* owner,
826 Expression* condition,
827 HBasicBlock* if_true,
828 HBasicBlock* if_false)
829 : AstContext(owner, Expression::kTest),
830 condition_(condition),
832 if_false_(if_false) {
835 void ReturnValue(HValue* value) override;
836 virtual void ReturnInstruction(HInstruction* instr,
837 BailoutId ast_id) override;
838 virtual void ReturnControl(HControlInstruction* instr,
839 BailoutId ast_id) override;
840 virtual void ReturnContinuation(HIfContinuation* continuation,
841 BailoutId ast_id) override;
843 static TestContext* cast(AstContext* context) {
844 DCHECK(context->IsTest());
845 return reinterpret_cast<TestContext*>(context);
848 Expression* condition() const { return condition_; }
849 HBasicBlock* if_true() const { return if_true_; }
850 HBasicBlock* if_false() const { return if_false_; }
853 // Build the shared core part of the translation unpacking a value into
855 void BuildBranch(HValue* value);
857 Expression* condition_;
858 HBasicBlock* if_true_;
859 HBasicBlock* if_false_;
863 class FunctionState final {
865 FunctionState(HOptimizedGraphBuilder* owner,
866 CompilationInfo* info,
867 InliningKind inlining_kind,
871 CompilationInfo* compilation_info() { return compilation_info_; }
872 AstContext* call_context() { return call_context_; }
873 InliningKind inlining_kind() const { return inlining_kind_; }
874 HBasicBlock* function_return() { return function_return_; }
875 TestContext* test_context() { return test_context_; }
876 void ClearInlinedTestContext() {
877 delete test_context_;
878 test_context_ = NULL;
881 FunctionState* outer() { return outer_; }
883 HEnterInlined* entry() { return entry_; }
884 void set_entry(HEnterInlined* entry) { entry_ = entry; }
886 HArgumentsObject* arguments_object() { return arguments_object_; }
887 void set_arguments_object(HArgumentsObject* arguments_object) {
888 arguments_object_ = arguments_object;
891 HArgumentsElements* arguments_elements() { return arguments_elements_; }
892 void set_arguments_elements(HArgumentsElements* arguments_elements) {
893 arguments_elements_ = arguments_elements;
896 bool arguments_pushed() { return arguments_elements() != NULL; }
898 int inlining_id() const { return inlining_id_; }
901 HOptimizedGraphBuilder* owner_;
903 CompilationInfo* compilation_info_;
905 // During function inlining, expression context of the call being
906 // inlined. NULL when not inlining.
907 AstContext* call_context_;
909 // The kind of call which is currently being inlined.
910 InliningKind inlining_kind_;
912 // When inlining in an effect or value context, this is the return block.
913 // It is NULL otherwise. When inlining in a test context, there are a
914 // pair of return blocks in the context. When not inlining, there is no
915 // local return point.
916 HBasicBlock* function_return_;
918 // When inlining a call in a test context, a context containing a pair of
919 // return blocks. NULL in all other cases.
920 TestContext* test_context_;
922 // When inlining HEnterInlined instruction corresponding to the function
924 HEnterInlined* entry_;
926 HArgumentsObject* arguments_object_;
927 HArgumentsElements* arguments_elements_;
930 SourcePosition outer_source_position_;
932 FunctionState* outer_;
936 class HIfContinuation final {
939 : continuation_captured_(false),
941 false_branch_(NULL) {}
942 HIfContinuation(HBasicBlock* true_branch,
943 HBasicBlock* false_branch)
944 : continuation_captured_(true), true_branch_(true_branch),
945 false_branch_(false_branch) {}
946 ~HIfContinuation() { DCHECK(!continuation_captured_); }
948 void Capture(HBasicBlock* true_branch,
949 HBasicBlock* false_branch) {
950 DCHECK(!continuation_captured_);
951 true_branch_ = true_branch;
952 false_branch_ = false_branch;
953 continuation_captured_ = true;
956 void Continue(HBasicBlock** true_branch,
957 HBasicBlock** false_branch) {
958 DCHECK(continuation_captured_);
959 *true_branch = true_branch_;
960 *false_branch = false_branch_;
961 continuation_captured_ = false;
964 bool IsTrueReachable() { return true_branch_ != NULL; }
965 bool IsFalseReachable() { return false_branch_ != NULL; }
966 bool TrueAndFalseReachable() {
967 return IsTrueReachable() || IsFalseReachable();
970 HBasicBlock* true_branch() const { return true_branch_; }
971 HBasicBlock* false_branch() const { return false_branch_; }
974 bool continuation_captured_;
975 HBasicBlock* true_branch_;
976 HBasicBlock* false_branch_;
980 class HAllocationMode final BASE_EMBEDDED {
982 explicit HAllocationMode(Handle<AllocationSite> feedback_site)
983 : current_site_(NULL), feedback_site_(feedback_site),
984 pretenure_flag_(NOT_TENURED) {}
985 explicit HAllocationMode(HValue* current_site)
986 : current_site_(current_site), pretenure_flag_(NOT_TENURED) {}
987 explicit HAllocationMode(PretenureFlag pretenure_flag)
988 : current_site_(NULL), pretenure_flag_(pretenure_flag) {}
990 : current_site_(NULL), pretenure_flag_(NOT_TENURED) {}
992 HValue* current_site() const { return current_site_; }
993 Handle<AllocationSite> feedback_site() const { return feedback_site_; }
995 bool CreateAllocationMementos() const WARN_UNUSED_RESULT {
996 return current_site() != NULL;
999 PretenureFlag GetPretenureMode() const WARN_UNUSED_RESULT {
1000 if (!feedback_site().is_null()) return feedback_site()->GetPretenureMode();
1001 return pretenure_flag_;
1005 HValue* current_site_;
1006 Handle<AllocationSite> feedback_site_;
1007 PretenureFlag pretenure_flag_;
1011 class HGraphBuilder {
1013 explicit HGraphBuilder(CompilationInfo* info)
1016 current_block_(NULL),
1017 scope_(info->scope()),
1018 position_(SourcePosition::Unknown()),
1019 start_position_(0) {}
1020 virtual ~HGraphBuilder() {}
1022 Scope* scope() const { return scope_; }
1023 void set_scope(Scope* scope) { scope_ = scope; }
1025 HBasicBlock* current_block() const { return current_block_; }
1026 void set_current_block(HBasicBlock* block) { current_block_ = block; }
1027 HEnvironment* environment() const {
1028 return current_block()->last_environment();
1030 Zone* zone() const { return info_->zone(); }
1031 HGraph* graph() const { return graph_; }
1032 Isolate* isolate() const { return graph_->isolate(); }
1033 CompilationInfo* top_info() { return info_; }
1035 HGraph* CreateGraph();
1037 // Bailout environment manipulation.
1038 void Push(HValue* value) { environment()->Push(value); }
1039 HValue* Pop() { return environment()->Pop(); }
1041 virtual HValue* context() = 0;
1043 // Adding instructions.
1044 HInstruction* AddInstruction(HInstruction* instr);
1045 void FinishCurrentBlock(HControlInstruction* last);
1046 void FinishExitCurrentBlock(HControlInstruction* instruction);
1048 void Goto(HBasicBlock* from,
1049 HBasicBlock* target,
1050 FunctionState* state = NULL,
1051 bool add_simulate = true) {
1052 from->Goto(target, source_position(), state, add_simulate);
1054 void Goto(HBasicBlock* target,
1055 FunctionState* state = NULL,
1056 bool add_simulate = true) {
1057 Goto(current_block(), target, state, add_simulate);
1059 void GotoNoSimulate(HBasicBlock* from, HBasicBlock* target) {
1060 Goto(from, target, NULL, false);
1062 void GotoNoSimulate(HBasicBlock* target) {
1063 Goto(target, NULL, false);
1065 void AddLeaveInlined(HBasicBlock* block,
1066 HValue* return_value,
1067 FunctionState* state) {
1068 block->AddLeaveInlined(return_value, state, source_position());
1070 void AddLeaveInlined(HValue* return_value, FunctionState* state) {
1071 return AddLeaveInlined(current_block(), return_value, state);
1075 HInstruction* NewUncasted() {
1076 return I::New(isolate(), zone(), context());
1081 return I::New(isolate(), zone(), context());
1085 HInstruction* AddUncasted() { return AddInstruction(NewUncasted<I>());}
1088 I* Add() { return AddInstructionTyped(New<I>());}
1090 template<class I, class P1>
1091 HInstruction* NewUncasted(P1 p1) {
1092 return I::New(isolate(), zone(), context(), p1);
1095 template <class I, class P1>
1097 return I::New(isolate(), zone(), context(), p1);
1100 template<class I, class P1>
1101 HInstruction* AddUncasted(P1 p1) {
1102 HInstruction* result = AddInstruction(NewUncasted<I>(p1));
1103 // Specializations must have their parameters properly casted
1104 // to avoid landing here.
1105 DCHECK(!result->IsReturn() && !result->IsSimulate() &&
1106 !result->IsDeoptimize());
1110 template<class I, class P1>
1112 I* result = AddInstructionTyped(New<I>(p1));
1113 // Specializations must have their parameters properly casted
1114 // to avoid landing here.
1115 DCHECK(!result->IsReturn() && !result->IsSimulate() &&
1116 !result->IsDeoptimize());
1120 template<class I, class P1, class P2>
1121 HInstruction* NewUncasted(P1 p1, P2 p2) {
1122 return I::New(isolate(), zone(), context(), p1, p2);
1125 template<class I, class P1, class P2>
1126 I* New(P1 p1, P2 p2) {
1127 return I::New(isolate(), zone(), context(), p1, p2);
1130 template<class I, class P1, class P2>
1131 HInstruction* AddUncasted(P1 p1, P2 p2) {
1132 HInstruction* result = AddInstruction(NewUncasted<I>(p1, p2));
1133 // Specializations must have their parameters properly casted
1134 // to avoid landing here.
1135 DCHECK(!result->IsSimulate());
1139 template<class I, class P1, class P2>
1140 I* Add(P1 p1, P2 p2) {
1141 I* result = AddInstructionTyped(New<I>(p1, p2));
1142 // Specializations must have their parameters properly casted
1143 // to avoid landing here.
1144 DCHECK(!result->IsSimulate());
1148 template<class I, class P1, class P2, class P3>
1149 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3) {
1150 return I::New(isolate(), zone(), context(), p1, p2, p3);
1153 template<class I, class P1, class P2, class P3>
1154 I* New(P1 p1, P2 p2, P3 p3) {
1155 return I::New(isolate(), zone(), context(), p1, p2, p3);
1158 template<class I, class P1, class P2, class P3>
1159 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3) {
1160 return AddInstruction(NewUncasted<I>(p1, p2, p3));
1163 template<class I, class P1, class P2, class P3>
1164 I* Add(P1 p1, P2 p2, P3 p3) {
1165 return AddInstructionTyped(New<I>(p1, p2, p3));
1168 template<class I, class P1, class P2, class P3, class P4>
1169 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
1170 return I::New(isolate(), zone(), context(), p1, p2, p3, p4);
1173 template<class I, class P1, class P2, class P3, class P4>
1174 I* New(P1 p1, P2 p2, P3 p3, P4 p4) {
1175 return I::New(isolate(), zone(), context(), p1, p2, p3, p4);
1178 template<class I, class P1, class P2, class P3, class P4>
1179 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
1180 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4));
1183 template<class I, class P1, class P2, class P3, class P4>
1184 I* Add(P1 p1, P2 p2, P3 p3, P4 p4) {
1185 return AddInstructionTyped(New<I>(p1, p2, p3, p4));
1188 template<class I, class P1, class P2, class P3, class P4, class P5>
1189 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1190 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5);
1193 template<class I, class P1, class P2, class P3, class P4, class P5>
1194 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1195 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5);
1198 template<class I, class P1, class P2, class P3, class P4, class P5>
1199 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1200 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5));
1203 template<class I, class P1, class P2, class P3, class P4, class P5>
1204 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1205 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5));
1208 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1209 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1210 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6);
1213 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1214 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1215 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6);
1218 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1219 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1220 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6));
1223 template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1224 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1225 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6));
1228 template<class I, class P1, class P2, class P3, class P4,
1229 class P5, class P6, class P7>
1230 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1231 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7);
1234 template<class I, class P1, class P2, class P3, class P4,
1235 class P5, class P6, class P7>
1236 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1237 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7);
1240 template<class I, class P1, class P2, class P3,
1241 class P4, class P5, class P6, class P7>
1242 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1243 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7));
1246 template<class I, class P1, class P2, class P3,
1247 class P4, class P5, class P6, class P7>
1248 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1249 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7));
1252 template<class I, class P1, class P2, class P3, class P4,
1253 class P5, class P6, class P7, class P8>
1254 HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
1255 P5 p5, P6 p6, P7 p7, P8 p8) {
1256 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8);
1259 template<class I, class P1, class P2, class P3, class P4,
1260 class P5, class P6, class P7, class P8>
1261 I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
1262 return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8);
1265 template<class I, class P1, class P2, class P3, class P4,
1266 class P5, class P6, class P7, class P8>
1267 HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
1268 P5 p5, P6 p6, P7 p7, P8 p8) {
1269 return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8));
1272 template<class I, class P1, class P2, class P3, class P4,
1273 class P5, class P6, class P7, class P8>
1274 I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
1275 return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7, p8));
1278 void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE);
1280 // When initializing arrays, we'll unfold the loop if the number of elements
1281 // is known at compile time and is <= kElementLoopUnrollThreshold.
1282 static const int kElementLoopUnrollThreshold = 8;
1285 virtual bool BuildGraph() = 0;
1287 HBasicBlock* CreateBasicBlock(HEnvironment* env);
1288 HBasicBlock* CreateLoopHeaderBlock();
1290 template <class BitFieldClass>
1291 HValue* BuildDecodeField(HValue* encoded_field) {
1292 HValue* mask_value = Add<HConstant>(static_cast<int>(BitFieldClass::kMask));
1293 HValue* masked_field =
1294 AddUncasted<HBitwise>(Token::BIT_AND, encoded_field, mask_value);
1295 return AddUncasted<HShr>(masked_field,
1296 Add<HConstant>(static_cast<int>(BitFieldClass::kShift)));
1299 HValue* BuildGetElementsKind(HValue* object);
1301 HValue* BuildCheckHeapObject(HValue* object);
1302 HValue* BuildCheckString(HValue* string);
1303 HValue* BuildWrapReceiver(HValue* object, HValue* function);
1305 // Building common constructs
1306 HValue* BuildCheckForCapacityGrow(HValue* object,
1312 PropertyAccessType access_type);
1314 HValue* BuildCheckAndGrowElementsCapacity(HValue* object, HValue* elements,
1315 ElementsKind kind, HValue* length,
1316 HValue* capacity, HValue* key);
1318 HValue* BuildCopyElementsOnWrite(HValue* object,
1323 void BuildTransitionElementsKind(HValue* object,
1325 ElementsKind from_kind,
1326 ElementsKind to_kind,
1329 HValue* BuildNumberToString(HValue* object, Type* type);
1330 HValue* BuildToObject(HValue* receiver);
1332 void BuildJSObjectCheck(HValue* receiver,
1333 int bit_field_mask);
1335 // Checks a key value that's being used for a keyed element access context. If
1336 // the key is a index, i.e. a smi or a number in a unique string with a cached
1337 // numeric value, the "true" of the continuation is joined. Otherwise,
1338 // if the key is a name or a unique string, the "false" of the continuation is
1339 // joined. Otherwise, a deoptimization is triggered. In both paths of the
1340 // continuation, the key is pushed on the top of the environment.
1341 void BuildKeyedIndexCheck(HValue* key,
1342 HIfContinuation* join_continuation);
1344 // Checks the properties of an object if they are in dictionary case, in which
1345 // case "true" of continuation is taken, otherwise the "false"
1346 void BuildTestForDictionaryProperties(HValue* object,
1347 HIfContinuation* continuation);
1349 void BuildNonGlobalObjectCheck(HValue* receiver);
1351 HValue* BuildKeyedLookupCacheHash(HValue* object,
1354 HValue* BuildUncheckedDictionaryElementLoad(HValue* receiver,
1355 HValue* elements, HValue* key,
1357 LanguageMode language_mode);
1359 HValue* BuildRegExpConstructResult(HValue* length,
1363 // Allocates a new object according with the given allocation properties.
1364 HAllocate* BuildAllocate(HValue* object_size,
1366 InstanceType instance_type,
1367 HAllocationMode allocation_mode);
1368 // Computes the sum of two string lengths, taking care of overflow handling.
1369 HValue* BuildAddStringLengths(HValue* left_length, HValue* right_length);
1370 // Creates a cons string using the two input strings.
1371 HValue* BuildCreateConsString(HValue* length,
1374 HAllocationMode allocation_mode);
1375 // Copies characters from one sequential string to another.
1376 void BuildCopySeqStringChars(HValue* src,
1378 String::Encoding src_encoding,
1381 String::Encoding dst_encoding,
1384 // Align an object size to object alignment boundary
1385 HValue* BuildObjectSizeAlignment(HValue* unaligned_size, int header_size);
1387 // Both operands are non-empty strings.
1388 HValue* BuildUncheckedStringAdd(HValue* left,
1390 HAllocationMode allocation_mode);
1391 // Add two strings using allocation mode, validating type feedback.
1392 HValue* BuildStringAdd(HValue* left,
1394 HAllocationMode allocation_mode);
1396 HInstruction* BuildUncheckedMonomorphicElementAccess(
1397 HValue* checked_object,
1401 ElementsKind elements_kind,
1402 PropertyAccessType access_type,
1403 LoadKeyedHoleMode load_mode,
1404 KeyedAccessStoreMode store_mode);
1406 HInstruction* AddElementAccess(
1408 HValue* checked_key,
1411 ElementsKind elements_kind,
1412 PropertyAccessType access_type,
1413 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE);
1415 HInstruction* AddLoadStringInstanceType(HValue* string);
1416 HInstruction* AddLoadStringLength(HValue* string);
1417 HInstruction* BuildLoadStringLength(HValue* string);
1418 HStoreNamedField* AddStoreMapConstant(HValue* object, Handle<Map> map) {
1419 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(),
1420 Add<HConstant>(map));
1422 HLoadNamedField* AddLoadMap(HValue* object,
1423 HValue* dependency = NULL);
1424 HLoadNamedField* AddLoadElements(HValue* object,
1425 HValue* dependency = NULL);
1427 bool MatchRotateRight(HValue* left,
1430 HValue** shift_amount);
1432 HValue* BuildBinaryOperation(Token::Value op, HValue* left, HValue* right,
1433 Type* left_type, Type* right_type,
1434 Type* result_type, Maybe<int> fixed_right_arg,
1435 HAllocationMode allocation_mode,
1437 BailoutId opt_id = BailoutId::None());
1439 HLoadNamedField* AddLoadFixedArrayLength(HValue *object,
1440 HValue *dependency = NULL);
1442 HLoadNamedField* AddLoadArrayLength(HValue *object,
1444 HValue *dependency = NULL);
1446 HValue* AddLoadJSBuiltin(Builtins::JavaScript builtin);
1448 HValue* EnforceNumberType(HValue* number, Type* expected);
1449 HValue* TruncateToNumber(HValue* value, Type** expected);
1451 void FinishExitWithHardDeoptimization(Deoptimizer::DeoptReason reason);
1453 void AddIncrementCounter(StatsCounter* counter);
1455 class IfBuilder final {
1457 // If using this constructor, Initialize() must be called explicitly!
1460 explicit IfBuilder(HGraphBuilder* builder);
1461 IfBuilder(HGraphBuilder* builder,
1462 HIfContinuation* continuation);
1465 if (!finished_) End();
1468 void Initialize(HGraphBuilder* builder);
1470 template<class Condition>
1471 Condition* If(HValue *p) {
1472 Condition* compare = builder()->New<Condition>(p);
1473 AddCompare(compare);
1477 template<class Condition, class P2>
1478 Condition* If(HValue* p1, P2 p2) {
1479 Condition* compare = builder()->New<Condition>(p1, p2);
1480 AddCompare(compare);
1484 template<class Condition, class P2, class P3>
1485 Condition* If(HValue* p1, P2 p2, P3 p3) {
1486 Condition* compare = builder()->New<Condition>(p1, p2, p3);
1487 AddCompare(compare);
1491 template<class Condition>
1492 Condition* IfNot(HValue* p) {
1493 Condition* compare = If<Condition>(p);
1498 template<class Condition, class P2>
1499 Condition* IfNot(HValue* p1, P2 p2) {
1500 Condition* compare = If<Condition>(p1, p2);
1505 template<class Condition, class P2, class P3>
1506 Condition* IfNot(HValue* p1, P2 p2, P3 p3) {
1507 Condition* compare = If<Condition>(p1, p2, p3);
1512 template<class Condition>
1513 Condition* OrIf(HValue *p) {
1515 return If<Condition>(p);
1518 template<class Condition, class P2>
1519 Condition* OrIf(HValue* p1, P2 p2) {
1521 return If<Condition>(p1, p2);
1524 template<class Condition, class P2, class P3>
1525 Condition* OrIf(HValue* p1, P2 p2, P3 p3) {
1527 return If<Condition>(p1, p2, p3);
1530 template<class Condition>
1531 Condition* AndIf(HValue *p) {
1533 return If<Condition>(p);
1536 template<class Condition, class P2>
1537 Condition* AndIf(HValue* p1, P2 p2) {
1539 return If<Condition>(p1, p2);
1542 template<class Condition, class P2, class P3>
1543 Condition* AndIf(HValue* p1, P2 p2, P3 p3) {
1545 return If<Condition>(p1, p2, p3);
1551 // Captures the current state of this IfBuilder in the specified
1552 // continuation and ends this IfBuilder.
1553 void CaptureContinuation(HIfContinuation* continuation);
1555 // Joins the specified continuation from this IfBuilder and ends this
1556 // IfBuilder. This appends a Goto instruction from the true branch of
1557 // this IfBuilder to the true branch of the continuation unless the
1558 // true branch of this IfBuilder is already finished. And vice versa
1559 // for the false branch.
1561 // The basic idea is as follows: You have several nested IfBuilder's
1562 // that you want to join based on two possible outcomes (i.e. success
1563 // and failure, or whatever). You can do this easily using this method
1564 // now, for example:
1566 // HIfContinuation cont(graph()->CreateBasicBlock(),
1567 // graph()->CreateBasicBlock());
1569 // IfBuilder if_whatever(this);
1570 // if_whatever.If<Condition>(arg);
1571 // if_whatever.Then();
1573 // if_whatever.Else();
1575 // if_whatever.JoinContinuation(&cont);
1577 // IfBuilder if_something(this);
1578 // if_something.If<Condition>(arg1, arg2);
1579 // if_something.Then();
1581 // if_something.Else();
1583 // if_something.JoinContinuation(&cont);
1585 // IfBuilder if_finally(this, &cont);
1586 // if_finally.Then();
1587 // // continues after then code of if_whatever or if_something.
1589 // if_finally.Else();
1590 // // continues after else code of if_whatever or if_something.
1592 // if_finally.End();
1593 void JoinContinuation(HIfContinuation* continuation);
1598 void EndUnreachable();
1600 void Deopt(Deoptimizer::DeoptReason reason);
1601 void ThenDeopt(Deoptimizer::DeoptReason reason) {
1605 void ElseDeopt(Deoptimizer::DeoptReason reason) {
1610 void Return(HValue* value);
1613 void InitializeDontCreateBlocks(HGraphBuilder* builder);
1615 HControlInstruction* AddCompare(HControlInstruction* compare);
1617 HGraphBuilder* builder() const {
1618 DCHECK(builder_ != NULL); // Have you called "Initialize"?
1622 void AddMergeAtJoinBlock(bool deopt);
1625 void Finish(HBasicBlock** then_continuation,
1626 HBasicBlock** else_continuation);
1628 class MergeAtJoinBlock : public ZoneObject {
1630 MergeAtJoinBlock(HBasicBlock* block,
1632 MergeAtJoinBlock* next)
1636 HBasicBlock* block_;
1638 MergeAtJoinBlock* next_;
1641 HGraphBuilder* builder_;
1645 bool did_else_if_ : 1;
1649 bool needs_compare_ : 1;
1650 bool pending_merge_block_ : 1;
1651 HBasicBlock* first_true_block_;
1652 HBasicBlock* first_false_block_;
1653 HBasicBlock* split_edge_merge_block_;
1654 MergeAtJoinBlock* merge_at_join_blocks_;
1655 int normal_merge_at_join_block_count_;
1656 int deopt_merge_at_join_block_count_;
1659 class LoopBuilder final {
1669 explicit LoopBuilder(HGraphBuilder* builder); // while (true) {...}
1670 LoopBuilder(HGraphBuilder* builder,
1672 Direction direction);
1673 LoopBuilder(HGraphBuilder* builder,
1675 Direction direction,
1676 HValue* increment_amount);
1684 HValue* terminating,
1685 Token::Value token);
1687 void BeginBody(int drop_count);
1694 void Initialize(HGraphBuilder* builder, HValue* context,
1695 Direction direction, HValue* increment_amount);
1696 Zone* zone() { return builder_->zone(); }
1698 HGraphBuilder* builder_;
1700 HValue* increment_amount_;
1701 HInstruction* increment_;
1703 HBasicBlock* header_block_;
1704 HBasicBlock* body_block_;
1705 HBasicBlock* exit_block_;
1706 HBasicBlock* exit_trampoline_block_;
1707 Direction direction_;
1711 HValue* BuildNewElementsCapacity(HValue* old_capacity);
1713 class JSArrayBuilder final {
1715 JSArrayBuilder(HGraphBuilder* builder,
1717 HValue* allocation_site_payload,
1718 HValue* constructor_function,
1719 AllocationSiteOverrideMode override_mode);
1721 JSArrayBuilder(HGraphBuilder* builder,
1723 HValue* constructor_function = NULL);
1726 DONT_FILL_WITH_HOLE,
1730 ElementsKind kind() { return kind_; }
1731 HAllocate* elements_location() { return elements_location_; }
1733 HAllocate* AllocateEmptyArray();
1734 HAllocate* AllocateArray(HValue* capacity,
1735 HValue* length_field,
1736 FillMode fill_mode = FILL_WITH_HOLE);
1737 // Use these allocators when capacity could be unknown at compile time
1738 // but its limit is known. For constant |capacity| the value of
1739 // |capacity_upper_bound| is ignored and the actual |capacity|
1740 // value is used as an upper bound.
1741 HAllocate* AllocateArray(HValue* capacity,
1742 int capacity_upper_bound,
1743 HValue* length_field,
1744 FillMode fill_mode = FILL_WITH_HOLE);
1745 HAllocate* AllocateArray(HValue* capacity,
1746 HConstant* capacity_upper_bound,
1747 HValue* length_field,
1748 FillMode fill_mode = FILL_WITH_HOLE);
1749 HValue* GetElementsLocation() { return elements_location_; }
1750 HValue* EmitMapCode();
1753 Zone* zone() const { return builder_->zone(); }
1754 int elements_size() const {
1755 return IsFastDoubleElementsKind(kind_) ? kDoubleSize : kPointerSize;
1757 HGraphBuilder* builder() { return builder_; }
1758 HGraph* graph() { return builder_->graph(); }
1759 int initial_capacity() {
1760 STATIC_ASSERT(JSArray::kPreallocatedArrayElements > 0);
1761 return JSArray::kPreallocatedArrayElements;
1764 HValue* EmitInternalMapCode();
1766 HGraphBuilder* builder_;
1768 AllocationSiteMode mode_;
1769 HValue* allocation_site_payload_;
1770 HValue* constructor_function_;
1771 HAllocate* elements_location_;
1774 HValue* BuildAllocateArrayFromLength(JSArrayBuilder* array_builder,
1775 HValue* length_argument);
1776 HValue* BuildCalculateElementsSize(ElementsKind kind,
1778 HAllocate* AllocateJSArrayObject(AllocationSiteMode mode);
1779 HConstant* EstablishElementsAllocationSize(ElementsKind kind, int capacity);
1781 HAllocate* BuildAllocateElements(ElementsKind kind, HValue* size_in_bytes);
1783 void BuildInitializeElementsHeader(HValue* elements,
1787 // Build allocation and header initialization code for respective successor
1788 // of FixedArrayBase.
1789 HValue* BuildAllocateAndInitializeArray(ElementsKind kind, HValue* capacity);
1791 // |array| must have been allocated with enough room for
1792 // 1) the JSArray and 2) an AllocationMemento if mode requires it.
1793 // If the |elements| value provided is NULL then the array elements storage
1794 // is initialized with empty array.
1795 void BuildJSArrayHeader(HValue* array,
1798 AllocationSiteMode mode,
1799 ElementsKind elements_kind,
1800 HValue* allocation_site_payload,
1801 HValue* length_field);
1803 HValue* BuildGrowElementsCapacity(HValue* object,
1806 ElementsKind new_kind,
1808 HValue* new_capacity);
1810 void BuildFillElementsWithValue(HValue* elements,
1811 ElementsKind elements_kind,
1816 void BuildFillElementsWithHole(HValue* elements,
1817 ElementsKind elements_kind,
1821 void BuildCopyProperties(HValue* from_properties, HValue* to_properties,
1822 HValue* length, HValue* capacity);
1824 void BuildCopyElements(HValue* from_elements,
1825 ElementsKind from_elements_kind,
1826 HValue* to_elements,
1827 ElementsKind to_elements_kind,
1831 HValue* BuildCloneShallowArrayCow(HValue* boilerplate,
1832 HValue* allocation_site,
1833 AllocationSiteMode mode,
1836 HValue* BuildCloneShallowArrayEmpty(HValue* boilerplate,
1837 HValue* allocation_site,
1838 AllocationSiteMode mode);
1840 HValue* BuildCloneShallowArrayNonEmpty(HValue* boilerplate,
1841 HValue* allocation_site,
1842 AllocationSiteMode mode,
1845 HValue* BuildElementIndexHash(HValue* index);
1847 enum MapEmbedding { kEmbedMapsDirectly, kEmbedMapsViaWeakCells };
1849 void BuildCompareNil(HValue* value, Type* type, HIfContinuation* continuation,
1850 MapEmbedding map_embedding = kEmbedMapsDirectly);
1852 void BuildCreateAllocationMemento(HValue* previous_object,
1853 HValue* previous_object_size,
1856 HInstruction* BuildConstantMapCheck(Handle<JSObject> constant);
1857 HInstruction* BuildCheckPrototypeMaps(Handle<JSObject> prototype,
1858 Handle<JSObject> holder);
1860 HInstruction* BuildGetNativeContext(HValue* closure);
1861 HInstruction* BuildGetNativeContext();
1862 HInstruction* BuildGetScriptContext(int context_index);
1863 // Builds a loop version if |depth| is specified or unrolls the loop to
1864 // |depth_value| iterations otherwise.
1865 HValue* BuildGetParentContext(HValue* depth, int depth_value);
1867 HInstruction* BuildGetArrayFunction();
1868 HValue* BuildArrayBufferViewFieldAccessor(HValue* object,
1869 HValue* checked_object,
1874 void SetSourcePosition(int position) {
1875 if (position != RelocInfo::kNoPosition) {
1876 position_.set_position(position - start_position_);
1878 // Otherwise position remains unknown.
1881 void EnterInlinedSource(int start_position, int id) {
1882 if (top_info()->is_tracking_positions()) {
1883 start_position_ = start_position;
1884 position_.set_inlining_id(id);
1888 // Convert the given absolute offset from the start of the script to
1889 // the SourcePosition assuming that this position corresponds to the
1890 // same function as current position_.
1891 SourcePosition ScriptPositionToSourcePosition(int position) {
1892 SourcePosition pos = position_;
1893 pos.set_position(position - start_position_);
1897 SourcePosition source_position() { return position_; }
1898 void set_source_position(SourcePosition position) { position_ = position; }
1900 HValue* BuildAllocateEmptyArrayBuffer(HValue* byte_length);
1901 template <typename ViewClass>
1902 void BuildArrayBufferViewInitialization(HValue* obj,
1904 HValue* byte_offset,
1905 HValue* byte_length);
1911 I* AddInstructionTyped(I* instr) {
1912 return I::cast(AddInstruction(instr));
1915 CompilationInfo* info_;
1917 HBasicBlock* current_block_;
1919 SourcePosition position_;
1920 int start_position_;
1925 inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>(
1926 Deoptimizer::DeoptReason reason, Deoptimizer::BailoutType type) {
1927 if (type == Deoptimizer::SOFT) {
1928 isolate()->counters()->soft_deopts_requested()->Increment();
1929 if (FLAG_always_opt) return NULL;
1931 if (current_block()->IsDeoptimizing()) return NULL;
1932 HBasicBlock* after_deopt_block = CreateBasicBlock(
1933 current_block()->last_environment());
1934 HDeoptimize* instr = New<HDeoptimize>(reason, type, after_deopt_block);
1935 if (type == Deoptimizer::SOFT) {
1936 isolate()->counters()->soft_deopts_inserted()->Increment();
1938 FinishCurrentBlock(instr);
1939 set_current_block(after_deopt_block);
1945 inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>(
1946 Deoptimizer::DeoptReason reason, Deoptimizer::BailoutType type) {
1947 return Add<HDeoptimize>(reason, type);
1952 inline HSimulate* HGraphBuilder::Add<HSimulate>(
1954 RemovableSimulate removable) {
1955 HSimulate* instr = current_block()->CreateSimulate(id, removable);
1956 AddInstruction(instr);
1962 inline HSimulate* HGraphBuilder::Add<HSimulate>(
1964 return Add<HSimulate>(id, FIXED_SIMULATE);
1969 inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(BailoutId id) {
1970 return Add<HSimulate>(id, FIXED_SIMULATE);
1975 inline HReturn* HGraphBuilder::Add<HReturn>(HValue* value) {
1976 int num_parameters = graph()->info()->num_parameters();
1977 HValue* params = AddUncasted<HConstant>(num_parameters);
1978 HReturn* return_instruction = New<HReturn>(value, params);
1979 FinishExitCurrentBlock(return_instruction);
1980 return return_instruction;
1985 inline HReturn* HGraphBuilder::Add<HReturn>(HConstant* value) {
1986 return Add<HReturn>(static_cast<HValue*>(value));
1990 inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HValue* value) {
1991 return Add<HReturn>(value);
1996 inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HConstant* value) {
1997 return Add<HReturn>(value);
2002 inline HCallRuntime* HGraphBuilder::Add<HCallRuntime>(
2003 Handle<String> name,
2004 const Runtime::Function* c_function,
2005 int argument_count) {
2006 HCallRuntime* instr = New<HCallRuntime>(name, c_function, argument_count);
2007 if (graph()->info()->IsStub()) {
2008 // When compiling code stubs, we don't want to save all double registers
2009 // upon entry to the stub, but instead have the call runtime instruction
2010 // save the double registers only on-demand (in the fallback case).
2011 instr->set_save_doubles(kSaveFPRegs);
2013 AddInstruction(instr);
2019 inline HInstruction* HGraphBuilder::AddUncasted<HCallRuntime>(
2020 Handle<String> name,
2021 const Runtime::Function* c_function,
2022 int argument_count) {
2023 return Add<HCallRuntime>(name, c_function, argument_count);
2028 inline HContext* HGraphBuilder::New<HContext>() {
2029 return HContext::New(zone());
2034 inline HInstruction* HGraphBuilder::NewUncasted<HContext>() {
2035 return New<HContext>();
2038 class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
2040 // A class encapsulating (lazily-allocated) break and continue blocks for
2041 // a breakable statement. Separated from BreakAndContinueScope so that it
2042 // can have a separate lifetime.
2043 class BreakAndContinueInfo final BASE_EMBEDDED {
2045 explicit BreakAndContinueInfo(BreakableStatement* target,
2050 continue_block_(NULL),
2052 drop_extra_(drop_extra) {
2055 BreakableStatement* target() { return target_; }
2056 HBasicBlock* break_block() { return break_block_; }
2057 void set_break_block(HBasicBlock* block) { break_block_ = block; }
2058 HBasicBlock* continue_block() { return continue_block_; }
2059 void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
2060 Scope* scope() { return scope_; }
2061 int drop_extra() { return drop_extra_; }
2064 BreakableStatement* target_;
2065 HBasicBlock* break_block_;
2066 HBasicBlock* continue_block_;
2071 // A helper class to maintain a stack of current BreakAndContinueInfo
2072 // structures mirroring BreakableStatement nesting.
2073 class BreakAndContinueScope final BASE_EMBEDDED {
2075 BreakAndContinueScope(BreakAndContinueInfo* info,
2076 HOptimizedGraphBuilder* owner)
2077 : info_(info), owner_(owner), next_(owner->break_scope()) {
2078 owner->set_break_scope(this);
2081 ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
2083 BreakAndContinueInfo* info() { return info_; }
2084 HOptimizedGraphBuilder* owner() { return owner_; }
2085 BreakAndContinueScope* next() { return next_; }
2087 // Search the break stack for a break or continue target.
2088 enum BreakType { BREAK, CONTINUE };
2089 HBasicBlock* Get(BreakableStatement* stmt, BreakType type,
2090 Scope** scope, int* drop_extra);
2093 BreakAndContinueInfo* info_;
2094 HOptimizedGraphBuilder* owner_;
2095 BreakAndContinueScope* next_;
2098 explicit HOptimizedGraphBuilder(CompilationInfo* info);
2100 bool BuildGraph() override;
2102 // Simple accessors.
2103 BreakAndContinueScope* break_scope() const { return break_scope_; }
2104 void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
2106 HValue* context() override { return environment()->context(); }
2108 HOsrBuilder* osr() const { return osr_; }
2110 void Bailout(BailoutReason reason);
2112 HBasicBlock* CreateJoin(HBasicBlock* first,
2113 HBasicBlock* second,
2116 FunctionState* function_state() const { return function_state_; }
2118 void VisitDeclarations(ZoneList<Declaration*>* declarations) override;
2120 void* operator new(size_t size, Zone* zone) { return zone->New(size); }
2121 void operator delete(void* pointer, Zone* zone) { }
2122 void operator delete(void* pointer) { }
2124 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
2127 // Forward declarations for inner scope classes.
2128 class SubgraphScope;
2130 static const int kMaxCallPolymorphism = 4;
2131 static const int kMaxLoadPolymorphism = 4;
2132 static const int kMaxStorePolymorphism = 4;
2134 // Even in the 'unlimited' case we have to have some limit in order not to
2135 // overflow the stack.
2136 static const int kUnlimitedMaxInlinedSourceSize = 100000;
2137 static const int kUnlimitedMaxInlinedNodes = 10000;
2138 static const int kUnlimitedMaxInlinedNodesCumulative = 10000;
2140 // Maximum depth and total number of elements and properties for literal
2141 // graphs to be considered for fast deep-copying.
2142 static const int kMaxFastLiteralDepth = 3;
2143 static const int kMaxFastLiteralProperties = 8;
2145 // Simple accessors.
2146 void set_function_state(FunctionState* state) { function_state_ = state; }
2148 AstContext* ast_context() const { return ast_context_; }
2149 void set_ast_context(AstContext* context) { ast_context_ = context; }
2151 // Accessors forwarded to the function state.
2152 CompilationInfo* current_info() const {
2153 return function_state()->compilation_info();
2155 AstContext* call_context() const {
2156 return function_state()->call_context();
2158 HBasicBlock* function_return() const {
2159 return function_state()->function_return();
2161 TestContext* inlined_test_context() const {
2162 return function_state()->test_context();
2164 Handle<SharedFunctionInfo> current_shared_info() const {
2165 return current_info()->shared_info();
2167 TypeFeedbackVector* current_feedback_vector() const {
2168 return current_shared_info()->feedback_vector();
2170 void ClearInlinedTestContext() {
2171 function_state()->ClearInlinedTestContext();
2173 LanguageMode function_language_mode() {
2174 return function_state()->compilation_info()->language_mode();
2177 #define FOR_EACH_HYDROGEN_INTRINSIC(F) \
2183 F(IsConstructCall) \
2185 F(ArgumentsLength) \
2191 F(ThrowNotDateError) \
2192 F(StringCharFromCode) \
2194 F(OneByteSeqStringSetChar) \
2195 F(TwoByteSeqStringSetChar) \
2200 F(IsUndetectableObject) \
2204 F(HasCachedArrayIndex) \
2205 F(GetCachedArrayIndex) \
2206 F(FastOneByteArrayJoin) \
2207 F(DebugBreakInOptimizedCode) \
2208 F(StringCharCodeAt) \
2213 F(RegExpConstructResult) \
2218 /* Typed Arrays */ \
2219 F(TypedArrayInitialize) \
2220 F(DataViewInitialize) \
2222 F(TypedArrayMaxSizeInHeap) \
2223 F(ArrayBufferViewGetByteLength) \
2224 F(ArrayBufferViewGetByteOffset) \
2225 F(TypedArrayGetLength) \
2227 F(ArrayBufferGetByteLength) \
2229 F(ConstructDouble) \
2236 /* ES6 Collections */ \
2243 F(JSCollectionGetTable) \
2244 F(StringGetRawHashField) \
2247 F(HasFastPackedElements) \
2250 F(StringGetLength) \
2254 #define GENERATOR_DECLARATION(Name) void Generate##Name(CallRuntime* call);
2255 FOR_EACH_HYDROGEN_INTRINSIC(GENERATOR_DECLARATION)
2256 #undef GENERATOR_DECLARATION
2258 void VisitDelete(UnaryOperation* expr);
2259 void VisitVoid(UnaryOperation* expr);
2260 void VisitTypeof(UnaryOperation* expr);
2261 void VisitNot(UnaryOperation* expr);
2263 void VisitComma(BinaryOperation* expr);
2264 void VisitLogicalExpression(BinaryOperation* expr);
2265 void VisitArithmeticExpression(BinaryOperation* expr);
2267 void VisitLoopBody(IterationStatement* stmt,
2268 HBasicBlock* loop_entry);
2270 void BuildForInBody(ForInStatement* stmt, Variable* each_var,
2271 HValue* enumerable);
2273 // Create a back edge in the flow graph. body_exit is the predecessor
2274 // block and loop_entry is the successor block. loop_successor is the
2275 // block where control flow exits the loop normally (e.g., via failure of
2276 // the condition) and break_block is the block where control flow breaks
2277 // from the loop. All blocks except loop_entry can be NULL. The return
2278 // value is the new successor block which is the join of loop_successor
2279 // and break_block, or NULL.
2280 HBasicBlock* CreateLoop(IterationStatement* statement,
2281 HBasicBlock* loop_entry,
2282 HBasicBlock* body_exit,
2283 HBasicBlock* loop_successor,
2284 HBasicBlock* break_block);
2286 // Build a loop entry
2287 HBasicBlock* BuildLoopEntry();
2289 // Builds a loop entry respectful of OSR requirements
2290 HBasicBlock* BuildLoopEntry(IterationStatement* statement);
2292 HBasicBlock* JoinContinue(IterationStatement* statement,
2293 HBasicBlock* exit_block,
2294 HBasicBlock* continue_block);
2296 HValue* Top() const { return environment()->Top(); }
2297 void Drop(int n) { environment()->Drop(n); }
2298 void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
2299 bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var,
2302 HEnvironment* env) {
2303 if (!FLAG_analyze_environment_liveness) return false;
2304 // |this| and |arguments| are always live; zapping parameters isn't
2305 // safe because function.arguments can inspect them at any time.
2306 return !var->is_this() &&
2307 !var->is_arguments() &&
2308 !value->IsArgumentsObject() &&
2309 env->is_local_index(index);
2311 void BindIfLive(Variable* var, HValue* value) {
2312 HEnvironment* env = environment();
2313 int index = env->IndexFor(var);
2314 env->Bind(index, value);
2315 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
2316 HEnvironmentMarker* bind =
2317 Add<HEnvironmentMarker>(HEnvironmentMarker::BIND, index);
2320 bind->set_closure(env->closure());
2324 HValue* LookupAndMakeLive(Variable* var) {
2325 HEnvironment* env = environment();
2326 int index = env->IndexFor(var);
2327 HValue* value = env->Lookup(index);
2328 if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
2329 HEnvironmentMarker* lookup =
2330 Add<HEnvironmentMarker>(HEnvironmentMarker::LOOKUP, index);
2333 lookup->set_closure(env->closure());
2339 // The value of the arguments object is allowed in some but not most value
2340 // contexts. (It's allowed in all effect contexts and disallowed in all
2342 void VisitForValue(Expression* expr,
2343 ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
2344 void VisitForTypeOf(Expression* expr);
2345 void VisitForEffect(Expression* expr);
2346 void VisitForControl(Expression* expr,
2347 HBasicBlock* true_block,
2348 HBasicBlock* false_block);
2350 // Visit a list of expressions from left to right, each in a value context.
2351 void VisitExpressions(ZoneList<Expression*>* exprs) override;
2352 void VisitExpressions(ZoneList<Expression*>* exprs,
2353 ArgumentsAllowedFlag flag);
2355 // Remove the arguments from the bailout environment and emit instructions
2356 // to push them as outgoing parameters.
2357 template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
2358 void PushArgumentsFromEnvironment(int count);
2360 void SetUpScope(Scope* scope);
2361 void VisitStatements(ZoneList<Statement*>* statements) override;
2363 #define DECLARE_VISIT(type) virtual void Visit##type(type* node) override;
2364 AST_NODE_LIST(DECLARE_VISIT)
2365 #undef DECLARE_VISIT
2368 // Helpers for flow graph construction.
2369 enum GlobalPropertyAccess {
2373 GlobalPropertyAccess LookupGlobalProperty(Variable* var, LookupIterator* it,
2374 PropertyAccessType access_type);
2376 void EnsureArgumentsArePushedForAccess();
2377 bool TryArgumentsAccess(Property* expr);
2379 // Shared code for .call and .apply optimizations.
2380 void HandleIndirectCall(Call* expr, HValue* function, int arguments_count);
2381 // Try to optimize indirect calls such as fun.apply(receiver, arguments)
2382 // or fun.call(...).
2383 bool TryIndirectCall(Call* expr);
2384 void BuildFunctionApply(Call* expr);
2385 void BuildFunctionCall(Call* expr);
2387 bool TryHandleArrayCall(Call* expr, HValue* function);
2388 bool TryHandleArrayCallNew(CallNew* expr, HValue* function);
2389 void BuildArrayCall(Expression* expr, int arguments_count, HValue* function,
2390 Handle<AllocationSite> cell);
2392 enum ArrayIndexOfMode { kFirstIndexOf, kLastIndexOf };
2393 HValue* BuildArrayIndexOf(HValue* receiver,
2394 HValue* search_element,
2396 ArrayIndexOfMode mode);
2398 HValue* ImplicitReceiverFor(HValue* function,
2399 Handle<JSFunction> target);
2401 int InliningAstSize(Handle<JSFunction> target);
2402 bool TryInline(Handle<JSFunction> target, int arguments_count,
2403 HValue* implicit_return_value, BailoutId ast_id,
2404 BailoutId return_id, InliningKind inlining_kind);
2406 bool TryInlineCall(Call* expr);
2407 bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value);
2408 bool TryInlineGetter(Handle<JSFunction> getter,
2409 Handle<Map> receiver_map,
2411 BailoutId return_id);
2412 bool TryInlineSetter(Handle<JSFunction> setter,
2413 Handle<Map> receiver_map,
2415 BailoutId assignment_id,
2416 HValue* implicit_return_value);
2417 bool TryInlineIndirectCall(Handle<JSFunction> function, Call* expr,
2418 int arguments_count);
2419 bool TryInlineBuiltinMethodCall(Call* expr, Handle<JSFunction> function,
2420 Handle<Map> receiver_map,
2421 int args_count_no_receiver);
2422 bool TryInlineBuiltinFunctionCall(Call* expr);
2429 bool TryInlineApiMethodCall(Call* expr,
2431 SmallMapList* receiver_types);
2432 bool TryInlineApiFunctionCall(Call* expr, HValue* receiver);
2433 bool TryInlineApiGetter(Handle<JSFunction> function,
2434 Handle<Map> receiver_map,
2436 bool TryInlineApiSetter(Handle<JSFunction> function,
2437 Handle<Map> receiver_map,
2439 bool TryInlineApiCall(Handle<JSFunction> function,
2441 SmallMapList* receiver_maps,
2444 ApiCallType call_type);
2445 static bool IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map);
2446 static bool CanInlineArrayResizeOperation(Handle<Map> receiver_map);
2448 // If --trace-inlining, print a line of the inlining trace. Inlining
2449 // succeeded if the reason string is NULL and failed if there is a
2450 // non-NULL reason string.
2451 void TraceInline(Handle<JSFunction> target,
2452 Handle<JSFunction> caller,
2453 const char* failure_reason);
2455 void HandleGlobalVariableAssignment(Variable* var, HValue* value,
2456 FeedbackVectorICSlot ic_slot,
2459 void HandlePropertyAssignment(Assignment* expr);
2460 void HandleCompoundAssignment(Assignment* expr);
2461 void HandlePolymorphicNamedFieldAccess(
2462 PropertyAccessType access_type, Expression* expr,
2463 FeedbackVectorICSlot slot, BailoutId ast_id, BailoutId return_id,
2464 HValue* object, HValue* value, SmallMapList* types, Handle<String> name);
2466 HValue* BuildAllocateExternalElements(
2467 ExternalArrayType array_type,
2468 bool is_zero_byte_offset,
2469 HValue* buffer, HValue* byte_offset, HValue* length);
2470 HValue* BuildAllocateFixedTypedArray(ExternalArrayType array_type,
2471 size_t element_size,
2472 ElementsKind fixed_elements_kind,
2473 HValue* byte_length, HValue* length,
2476 // TODO(adamk): Move all OrderedHashTable functions to their own class.
2477 HValue* BuildOrderedHashTableHashToBucket(HValue* hash, HValue* num_buckets);
2478 template <typename CollectionType>
2479 HValue* BuildOrderedHashTableHashToEntry(HValue* table, HValue* hash,
2480 HValue* num_buckets);
2481 template <typename CollectionType>
2482 HValue* BuildOrderedHashTableEntryToIndex(HValue* entry, HValue* num_buckets);
2483 template <typename CollectionType>
2484 HValue* BuildOrderedHashTableFindEntry(HValue* table, HValue* key,
2486 template <typename CollectionType>
2487 HValue* BuildOrderedHashTableAddEntry(HValue* table, HValue* key,
2489 HIfContinuation* join_continuation);
2490 template <typename CollectionType>
2491 HValue* BuildAllocateOrderedHashTable();
2492 template <typename CollectionType>
2493 void BuildOrderedHashTableClear(HValue* receiver);
2494 template <typename CollectionType>
2495 void BuildJSCollectionDelete(CallRuntime* call,
2496 const Runtime::Function* c_function);
2497 template <typename CollectionType>
2498 void BuildJSCollectionHas(CallRuntime* call,
2499 const Runtime::Function* c_function);
2500 HValue* BuildStringHashLoadIfIsStringAndHashComputed(
2501 HValue* object, HIfContinuation* continuation);
2503 Handle<JSFunction> array_function() {
2504 return handle(isolate()->native_context()->array_function());
2507 bool IsCallArrayInlineable(int argument_count, Handle<AllocationSite> site);
2508 void BuildInlinedCallArray(Expression* expression, int argument_count,
2509 Handle<AllocationSite> site);
2511 void BuildInitializeInobjectProperties(HValue* receiver,
2512 Handle<Map> initial_map);
2514 class PropertyAccessInfo {
2516 PropertyAccessInfo(HOptimizedGraphBuilder* builder,
2517 PropertyAccessType access_type, Handle<Map> map,
2518 Handle<String> name)
2519 : builder_(builder),
2520 access_type_(access_type),
2523 field_type_(HType::Tagged()),
2524 access_(HObjectAccess::ForMap()),
2525 lookup_type_(NOT_FOUND),
2526 details_(NONE, DATA, Representation::None()) {}
2528 // Checkes whether this PropertyAccessInfo can be handled as a monomorphic
2529 // load named. It additionally fills in the fields necessary to generate the
2531 bool CanAccessMonomorphic();
2533 // Checks whether all types behave uniform when loading name. If all maps
2534 // behave the same, a single monomorphic load instruction can be emitted,
2535 // guarded by a single map-checks instruction that whether the receiver is
2536 // an instance of any of the types.
2537 // This method skips the first type in types, assuming that this
2538 // PropertyAccessInfo is built for types->first().
2539 bool CanAccessAsMonomorphic(SmallMapList* types);
2541 bool NeedsWrappingFor(Handle<JSFunction> target) const;
2544 Handle<String> name() const { return name_; }
2546 bool IsJSObjectFieldAccessor() {
2547 int offset; // unused
2548 return Accessors::IsJSObjectFieldAccessor(map_, name_, &offset);
2551 bool GetJSObjectFieldAccess(HObjectAccess* access) {
2553 if (Accessors::IsJSObjectFieldAccessor(map_, name_, &offset)) {
2554 if (IsStringType()) {
2555 DCHECK(String::Equals(isolate()->factory()->length_string(), name_));
2556 *access = HObjectAccess::ForStringLength();
2557 } else if (IsArrayType()) {
2558 DCHECK(String::Equals(isolate()->factory()->length_string(), name_));
2559 *access = HObjectAccess::ForArrayLength(map_->elements_kind());
2561 *access = HObjectAccess::ForMapAndOffset(map_, offset);
2568 bool IsJSArrayBufferViewFieldAccessor() {
2569 int offset; // unused
2570 return Accessors::IsJSArrayBufferViewFieldAccessor(map_, name_, &offset);
2573 bool GetJSArrayBufferViewFieldAccess(HObjectAccess* access) {
2575 if (Accessors::IsJSArrayBufferViewFieldAccessor(map_, name_, &offset)) {
2576 *access = HObjectAccess::ForMapAndOffset(map_, offset);
2582 bool has_holder() { return !holder_.is_null(); }
2583 bool IsLoad() const { return access_type_ == LOAD; }
2585 Isolate* isolate() const { return builder_->isolate(); }
2586 Handle<JSObject> holder() { return holder_; }
2587 Handle<JSFunction> accessor() { return accessor_; }
2588 Handle<Object> constant() { return constant_; }
2589 Handle<Map> transition() { return transition_; }
2590 SmallMapList* field_maps() { return &field_maps_; }
2591 HType field_type() const { return field_type_; }
2592 HObjectAccess access() { return access_; }
2594 bool IsFound() const { return lookup_type_ != NOT_FOUND; }
2595 bool IsProperty() const { return IsFound() && !IsTransition(); }
2596 bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; }
2597 bool IsData() const {
2598 return lookup_type_ == DESCRIPTOR_TYPE && details_.type() == DATA;
2600 bool IsDataConstant() const {
2601 return lookup_type_ == DESCRIPTOR_TYPE &&
2602 details_.type() == DATA_CONSTANT;
2604 bool IsAccessorConstant() const {
2605 return !IsTransition() && details_.type() == ACCESSOR_CONSTANT;
2607 bool IsConfigurable() const { return details_.IsConfigurable(); }
2608 bool IsReadOnly() const { return details_.IsReadOnly(); }
2610 bool IsStringType() { return map_->instance_type() < FIRST_NONSTRING_TYPE; }
2611 bool IsNumberType() { return map_->instance_type() == HEAP_NUMBER_TYPE; }
2612 bool IsValueWrapped() { return IsStringType() || IsNumberType(); }
2613 bool IsArrayType() { return map_->instance_type() == JS_ARRAY_TYPE; }
2616 Handle<Object> GetConstantFromMap(Handle<Map> map) const {
2617 DCHECK_EQ(DESCRIPTOR_TYPE, lookup_type_);
2618 DCHECK(number_ < map->NumberOfOwnDescriptors());
2619 return handle(map->instance_descriptors()->GetValue(number_), isolate());
2621 Handle<Object> GetAccessorsFromMap(Handle<Map> map) const {
2622 return GetConstantFromMap(map);
2624 Handle<HeapType> GetFieldTypeFromMap(Handle<Map> map) const {
2626 DCHECK(number_ < map->NumberOfOwnDescriptors());
2627 return handle(map->instance_descriptors()->GetFieldType(number_),
2630 Handle<Map> GetFieldOwnerFromMap(Handle<Map> map) const {
2632 DCHECK(number_ < map->NumberOfOwnDescriptors());
2633 return handle(map->FindFieldOwner(number_));
2635 int GetLocalFieldIndexFromMap(Handle<Map> map) const {
2636 DCHECK(lookup_type_ == DESCRIPTOR_TYPE ||
2637 lookup_type_ == TRANSITION_TYPE);
2638 DCHECK(number_ < map->NumberOfOwnDescriptors());
2639 int field_index = map->instance_descriptors()->GetFieldIndex(number_);
2640 return field_index - map->inobject_properties();
2643 void LookupDescriptor(Map* map, Name* name) {
2644 DescriptorArray* descriptors = map->instance_descriptors();
2645 int number = descriptors->SearchWithCache(name, map);
2646 if (number == DescriptorArray::kNotFound) return NotFound();
2647 lookup_type_ = DESCRIPTOR_TYPE;
2648 details_ = descriptors->GetDetails(number);
2651 void LookupTransition(Map* map, Name* name, PropertyAttributes attributes) {
2653 TransitionArray::SearchTransition(map, kData, name, attributes);
2654 if (target == NULL) return NotFound();
2655 lookup_type_ = TRANSITION_TYPE;
2656 transition_ = handle(target);
2657 number_ = transition_->LastAdded();
2658 details_ = transition_->instance_descriptors()->GetDetails(number_);
2661 lookup_type_ = NOT_FOUND;
2662 details_ = PropertyDetails::Empty();
2664 Representation representation() const {
2666 return details_.representation();
2668 bool IsTransitionToData() const {
2669 return IsTransition() && details_.type() == DATA;
2672 Zone* zone() { return builder_->zone(); }
2673 CompilationInfo* top_info() { return builder_->top_info(); }
2674 CompilationInfo* current_info() { return builder_->current_info(); }
2676 bool LoadResult(Handle<Map> map);
2677 bool LoadFieldMaps(Handle<Map> map);
2678 bool LookupDescriptor();
2679 bool LookupInPrototypes();
2680 bool IsIntegerIndexedExotic();
2681 bool IsCompatible(PropertyAccessInfo* other);
2683 void GeneralizeRepresentation(Representation r) {
2684 access_ = access_.WithRepresentation(
2685 access_.representation().generalize(r));
2688 HOptimizedGraphBuilder* builder_;
2689 PropertyAccessType access_type_;
2691 Handle<String> name_;
2692 Handle<JSObject> holder_;
2693 Handle<JSFunction> accessor_;
2694 Handle<JSObject> api_holder_;
2695 Handle<Object> constant_;
2696 SmallMapList field_maps_;
2698 HObjectAccess access_;
2700 enum { NOT_FOUND, DESCRIPTOR_TYPE, TRANSITION_TYPE } lookup_type_;
2701 Handle<Map> transition_;
2703 PropertyDetails details_;
2706 HValue* BuildMonomorphicAccess(PropertyAccessInfo* info, HValue* object,
2707 HValue* checked_object, HValue* value,
2708 BailoutId ast_id, BailoutId return_id,
2709 bool can_inline_accessor = true);
2711 HValue* BuildNamedAccess(PropertyAccessType access, BailoutId ast_id,
2712 BailoutId reutrn_id, Expression* expr,
2713 FeedbackVectorICSlot slot, HValue* object,
2714 Handle<String> name, HValue* value,
2715 bool is_uninitialized = false);
2717 void HandlePolymorphicCallNamed(Call* expr,
2719 SmallMapList* types,
2720 Handle<String> name);
2721 void HandleLiteralCompareTypeof(CompareOperation* expr,
2722 Expression* sub_expr,
2723 Handle<String> check);
2724 void HandleLiteralCompareNil(CompareOperation* expr,
2725 Expression* sub_expr,
2728 enum PushBeforeSimulateBehavior {
2729 PUSH_BEFORE_SIMULATE,
2730 NO_PUSH_BEFORE_SIMULATE
2733 HControlInstruction* BuildCompareInstruction(
2734 Token::Value op, HValue* left, HValue* right, Type* left_type,
2735 Type* right_type, Type* combined_type, SourcePosition left_position,
2736 SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result,
2737 BailoutId bailout_id);
2739 HInstruction* BuildStringCharCodeAt(HValue* string,
2742 HValue* BuildBinaryOperation(
2743 BinaryOperation* expr,
2746 PushBeforeSimulateBehavior push_sim_result);
2747 HInstruction* BuildIncrement(bool returns_original_input,
2748 CountOperation* expr);
2749 HInstruction* BuildKeyedGeneric(PropertyAccessType access_type,
2750 Expression* expr, FeedbackVectorICSlot slot,
2751 HValue* object, HValue* key, HValue* value);
2753 HInstruction* TryBuildConsolidatedElementLoad(HValue* object,
2756 SmallMapList* maps);
2758 LoadKeyedHoleMode BuildKeyedHoleMode(Handle<Map> map);
2760 HInstruction* BuildMonomorphicElementAccess(HValue* object,
2765 PropertyAccessType access_type,
2766 KeyedAccessStoreMode store_mode);
2768 HValue* HandlePolymorphicElementAccess(
2769 Expression* expr, FeedbackVectorICSlot slot, HValue* object, HValue* key,
2770 HValue* val, SmallMapList* maps, PropertyAccessType access_type,
2771 KeyedAccessStoreMode store_mode, bool* has_side_effects);
2773 HValue* HandleKeyedElementAccess(HValue* obj, HValue* key, HValue* val,
2774 Expression* expr, FeedbackVectorICSlot slot,
2775 BailoutId ast_id, BailoutId return_id,
2776 PropertyAccessType access_type,
2777 bool* has_side_effects);
2779 HInstruction* BuildNamedGeneric(PropertyAccessType access, Expression* expr,
2780 FeedbackVectorICSlot slot, HValue* object,
2781 Handle<Name> name, HValue* value,
2782 bool is_uninitialized = false);
2784 HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map);
2786 void BuildLoad(Property* property,
2788 void PushLoad(Property* property,
2792 void BuildStoreForEffect(Expression* expression, Property* prop,
2793 FeedbackVectorICSlot slot, BailoutId ast_id,
2794 BailoutId return_id, HValue* object, HValue* key,
2797 void BuildStore(Expression* expression, Property* prop,
2798 FeedbackVectorICSlot slot, BailoutId ast_id,
2799 BailoutId return_id, bool is_uninitialized = false);
2801 HInstruction* BuildLoadNamedField(PropertyAccessInfo* info,
2802 HValue* checked_object);
2803 HInstruction* BuildStoreNamedField(PropertyAccessInfo* info,
2804 HValue* checked_object,
2807 HValue* BuildContextChainWalk(Variable* var);
2809 HInstruction* BuildThisFunction();
2811 HInstruction* BuildFastLiteral(Handle<JSObject> boilerplate_object,
2812 AllocationSiteUsageContext* site_context);
2814 void BuildEmitObjectHeader(Handle<JSObject> boilerplate_object,
2815 HInstruction* object);
2817 void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object,
2818 HInstruction* object,
2819 AllocationSiteUsageContext* site_context,
2820 PretenureFlag pretenure_flag);
2822 void BuildEmitElements(Handle<JSObject> boilerplate_object,
2823 Handle<FixedArrayBase> elements,
2824 HValue* object_elements,
2825 AllocationSiteUsageContext* site_context);
2827 void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements,
2829 HValue* object_elements);
2831 void BuildEmitFixedArray(Handle<FixedArrayBase> elements,
2833 HValue* object_elements,
2834 AllocationSiteUsageContext* site_context);
2836 void AddCheckPrototypeMaps(Handle<JSObject> holder,
2837 Handle<Map> receiver_map);
2839 HInstruction* NewPlainFunctionCall(HValue* fun,
2841 bool pass_argument_count);
2843 HInstruction* NewArgumentAdaptorCall(HValue* fun, HValue* context,
2845 HValue* expected_param_count);
2847 HInstruction* BuildCallConstantFunction(Handle<JSFunction> target,
2848 int argument_count);
2850 bool CanBeFunctionApplyArguments(Call* expr);
2852 // The translation state of the currently-being-translated function.
2853 FunctionState* function_state_;
2855 // The base of the function state stack.
2856 FunctionState initial_function_state_;
2858 // Expression context of the currently visited subexpression. NULL when
2859 // visiting statements.
2860 AstContext* ast_context_;
2862 // A stack of breakable statements entered.
2863 BreakAndContinueScope* break_scope_;
2866 ZoneList<Handle<Object> > globals_;
2868 bool inline_bailout_;
2872 friend class FunctionState; // Pushes and pops the state stack.
2873 friend class AstContext; // Pushes and pops the AST context stack.
2874 friend class KeyedLoadFastElementStub;
2875 friend class HOsrBuilder;
2877 DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder);
2881 Zone* AstContext::zone() const { return owner_->zone(); }
2884 class HStatistics final : public Malloced {
2893 void Initialize(CompilationInfo* info);
2895 void SaveTiming(const char* name, base::TimeDelta time, size_t size);
2897 void IncrementFullCodeGen(base::TimeDelta full_code_gen) {
2898 full_code_gen_ += full_code_gen;
2901 void IncrementCreateGraph(base::TimeDelta delta) { create_graph_ += delta; }
2903 void IncrementOptimizeGraph(base::TimeDelta delta) {
2904 optimize_graph_ += delta;
2907 void IncrementGenerateCode(base::TimeDelta delta) { generate_code_ += delta; }
2909 void IncrementSubtotals(base::TimeDelta create_graph,
2910 base::TimeDelta optimize_graph,
2911 base::TimeDelta generate_code) {
2912 IncrementCreateGraph(create_graph);
2913 IncrementOptimizeGraph(optimize_graph);
2914 IncrementGenerateCode(generate_code);
2918 List<base::TimeDelta> times_;
2919 List<const char*> names_;
2920 List<size_t> sizes_;
2921 base::TimeDelta create_graph_;
2922 base::TimeDelta optimize_graph_;
2923 base::TimeDelta generate_code_;
2925 base::TimeDelta full_code_gen_;
2926 double source_size_;
2930 class HPhase : public CompilationPhase {
2932 HPhase(const char* name, HGraph* graph)
2933 : CompilationPhase(name, graph->info()),
2938 HGraph* graph() const { return graph_; }
2943 DISALLOW_COPY_AND_ASSIGN(HPhase);
2947 class HTracer final : public Malloced {
2949 explicit HTracer(int isolate_id)
2950 : trace_(&string_allocator_), indent_(0) {
2951 if (FLAG_trace_hydrogen_file == NULL) {
2953 "hydrogen-%d-%d.cfg",
2954 base::OS::GetCurrentProcessId(),
2957 StrNCpy(filename_, FLAG_trace_hydrogen_file, filename_.length());
2959 WriteChars(filename_.start(), "", 0, false);
2962 void TraceCompilation(CompilationInfo* info);
2963 void TraceHydrogen(const char* name, HGraph* graph);
2964 void TraceLithium(const char* name, LChunk* chunk);
2965 void TraceLiveRanges(const char* name, LAllocator* allocator);
2968 class Tag final BASE_EMBEDDED {
2970 Tag(HTracer* tracer, const char* name) {
2973 tracer->PrintIndent();
2974 tracer->trace_.Add("begin_%s\n", name);
2980 tracer_->PrintIndent();
2981 tracer_->trace_.Add("end_%s\n", name_);
2982 DCHECK(tracer_->indent_ >= 0);
2983 tracer_->FlushToFile();
2991 void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
2992 void Trace(const char* name, HGraph* graph, LChunk* chunk);
2995 void PrintEmptyProperty(const char* name) {
2997 trace_.Add("%s\n", name);
3000 void PrintStringProperty(const char* name, const char* value) {
3002 trace_.Add("%s \"%s\"\n", name, value);
3005 void PrintLongProperty(const char* name, int64_t value) {
3007 trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
3010 void PrintBlockProperty(const char* name, int block_id) {
3012 trace_.Add("%s \"B%d\"\n", name, block_id);
3015 void PrintIntProperty(const char* name, int value) {
3017 trace_.Add("%s %d\n", name, value);
3020 void PrintIndent() {
3021 for (int i = 0; i < indent_; i++) {
3026 EmbeddedVector<char, 64> filename_;
3027 HeapStringAllocator string_allocator_;
3028 StringStream trace_;
3033 class NoObservableSideEffectsScope final {
3035 explicit NoObservableSideEffectsScope(HGraphBuilder* builder) :
3037 builder_->graph()->IncrementInNoSideEffectsScope();
3039 ~NoObservableSideEffectsScope() {
3040 builder_->graph()->DecrementInNoSideEffectsScope();
3044 HGraphBuilder* builder_;
3048 } } // namespace v8::internal
3050 #endif // V8_HYDROGEN_H_