48 #if V8_TARGET_ARCH_IA32
50 #elif V8_TARGET_ARCH_X64
52 #elif V8_TARGET_ARCH_ARM64
54 #elif V8_TARGET_ARCH_ARM
56 #elif V8_TARGET_ARCH_MIPS
58 #elif V8_TARGET_ARCH_MIPS64
60 #elif V8_TARGET_ARCH_X87
63 #error Unsupported target architecture.
69 HBasicBlock::HBasicBlock(HGraph* graph)
70 : block_id_(graph->GetNextBlockID()),
72 phis_(4, graph->zone()),
76 loop_information_(
NULL),
77 predecessors_(2, graph->zone()),
79 dominated_blocks_(4, graph->zone()),
80 last_environment_(
NULL),
82 first_instruction_index_(-1),
83 last_instruction_index_(-1),
84 deleted_phis_(4, graph->zone()),
85 parent_loop_header_(
NULL),
86 inlined_entry_block_(
NULL),
87 is_inline_return_target_(
false),
89 dominates_loop_successors_(
false),
91 is_ordered_(
false) { }
94 Isolate* HBasicBlock::isolate()
const {
95 return graph_->isolate();
99 void HBasicBlock::MarkUnreachable() {
100 is_reachable_ =
false;
104 void HBasicBlock::AttachLoopInformation() {
106 loop_information_ =
new(zone()) HLoopInformation(
this, zone());
110 void HBasicBlock::DetachLoopInformation() {
112 loop_information_ =
NULL;
116 void HBasicBlock::AddPhi(HPhi* phi) {
118 phis_.Add(phi, zone());
123 void HBasicBlock::RemovePhi(HPhi* phi) {
124 DCHECK(phi->block() ==
this);
125 DCHECK(phis_.Contains(phi));
127 phis_.RemoveElement(phi);
132 void HBasicBlock::AddInstruction(HInstruction* instr,
133 HSourcePosition position) {
134 DCHECK(!IsStartBlock() || !IsFinished());
135 DCHECK(!instr->IsLinked());
138 if (!position.IsUnknown()) {
139 instr->set_position(position);
141 if (first_ ==
NULL) {
143 DCHECK(!last_environment()->ast_id().IsNone());
144 HBlockEntry* entry =
new(zone()) HBlockEntry();
145 entry->InitializeAsFirst(
this);
146 if (!position.IsUnknown()) {
147 entry->set_position(position);
149 DCHECK(!FLAG_hydrogen_track_positions ||
150 !graph()->info()->IsOptimizing());
152 first_ = last_ = entry;
154 instr->InsertAfter(last_);
158 HPhi* HBasicBlock::AddNewPhi(
int merged_index) {
159 if (graph()->IsInsideNoSideEffectsScope()) {
160 merged_index = HPhi::kInvalidMergedIndex;
162 HPhi* phi =
new(zone()) HPhi(merged_index, zone());
168 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
171 HEnvironment* environment = last_environment();
173 ast_id == BailoutId::StubEntry() ||
174 environment->closure()->shared()->VerifyBailoutId(ast_id));
176 int push_count = environment->push_count();
177 int pop_count = environment->pop_count();
180 new(zone()) HSimulate(ast_id, pop_count, zone(), removable);
182 instr->set_closure(environment->closure());
187 for (
int i = 0;
i < push_count; ++
i) {
188 instr->AddPushedValue(environment->ExpressionStackAt(
i));
190 for (GrowableBitVector::Iterator it(environment->assigned_variables(),
194 int index = it.Current();
195 instr->AddAssignedValue(index, environment->Lookup(index));
197 environment->ClearHistory();
202 void HBasicBlock::Finish(HControlInstruction* end, HSourcePosition position) {
204 AddInstruction(end, position);
206 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
207 it.Current()->RegisterPredecessor(
this);
212 void HBasicBlock::Goto(HBasicBlock* block,
213 HSourcePosition position,
214 FunctionState* state,
216 bool drop_extra = state !=
NULL &&
219 if (block->IsInlineReturnTarget()) {
220 HEnvironment* env = last_environment();
221 int argument_count = env->arguments_environment()->parameter_count();
222 AddInstruction(
new(zone())
223 HLeaveInlined(state->entry(), argument_count),
225 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
229 HGoto* instr =
new(zone()) HGoto(block);
230 Finish(instr, position);
234 void HBasicBlock::AddLeaveInlined(HValue* return_value,
235 FunctionState* state,
236 HSourcePosition position) {
237 HBasicBlock* target = state->function_return();
240 DCHECK(target->IsInlineReturnTarget());
242 HEnvironment* env = last_environment();
243 int argument_count = env->arguments_environment()->parameter_count();
244 AddInstruction(
new(zone()) HLeaveInlined(state->entry(), argument_count),
246 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
247 last_environment()->Push(return_value);
249 HGoto* instr =
new(zone()) HGoto(target);
250 Finish(instr, position);
254 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
255 DCHECK(!HasEnvironment());
257 UpdateEnvironment(env);
261 void HBasicBlock::UpdateEnvironment(HEnvironment* env) {
262 last_environment_ = env;
263 graph()->update_maximum_environment_size(env->first_expression_index());
267 void HBasicBlock::SetJoinId(BailoutId ast_id) {
268 int length = predecessors_.length();
270 for (
int i = 0;
i < length;
i++) {
271 HBasicBlock* predecessor = predecessors_[
i];
272 DCHECK(predecessor->end()->IsGoto());
273 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
275 (predecessor->last_environment()->closure().is_null() ||
276 predecessor->last_environment()->closure()->shared()
277 ->VerifyBailoutId(ast_id)));
278 simulate->set_ast_id(ast_id);
279 predecessor->last_environment()->set_ast_id(ast_id);
284 bool HBasicBlock::Dominates(HBasicBlock* other)
const {
285 HBasicBlock* current = other->dominator();
286 while (current !=
NULL) {
287 if (current ==
this)
return true;
288 current = current->dominator();
294 bool HBasicBlock::EqualToOrDominates(HBasicBlock* other)
const {
295 if (
this == other)
return true;
296 return Dominates(other);
300 int HBasicBlock::LoopNestingDepth()
const {
301 const HBasicBlock* current =
this;
302 int result = (current->IsLoopHeader()) ? 1 : 0;
303 while (current->parent_loop_header() !=
NULL) {
304 current = current->parent_loop_header();
311 void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
314 SetJoinId(stmt->EntryId());
315 if (predecessors()->length() == 1) {
317 DetachLoopInformation();
323 for (
int i = 1;
i < predecessors()->length(); ++
i) {
324 loop_information()->RegisterBackEdge(predecessors()->at(
i));
329 void HBasicBlock::MarkSuccEdgeUnreachable(
int succ) {
331 HBasicBlock* succ_block = end()->SuccessorAt(succ);
333 DCHECK(succ_block->predecessors()->length() == 1);
334 succ_block->MarkUnreachable();
338 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
339 if (HasPredecessor()) {
344 HEnvironment* incoming_env = pred->last_environment();
345 if (IsLoopHeader()) {
346 DCHECK(phis()->length() == incoming_env->length());
347 for (
int i = 0;
i < phis_.length(); ++
i) {
348 phis_[
i]->AddInput(incoming_env->values()->at(
i));
351 last_environment()->AddIncomingEdge(
this, pred->last_environment());
353 }
else if (!HasEnvironment() && !IsFinished()) {
355 SetInitialEnvironment(pred->last_environment()->Copy());
358 predecessors_.Add(pred, zone());
362 void HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
363 DCHECK(!dominated_blocks_.Contains(block));
367 while (index < dominated_blocks_.length() &&
368 dominated_blocks_[index]->block_id() < block->block_id()) {
371 dominated_blocks_.InsertAt(index, block, zone());
375 void HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
376 if (dominator_ ==
NULL) {
378 other->AddDominatedBlock(
this);
379 }
else if (other->dominator() !=
NULL) {
380 HBasicBlock* first = dominator_;
381 HBasicBlock* second = other;
383 while (first != second) {
384 if (first->block_id() > second->block_id()) {
385 first = first->dominator();
387 second = second->dominator();
392 if (dominator_ != first) {
393 DCHECK(dominator_->dominated_blocks_.Contains(
this));
394 dominator_->dominated_blocks_.RemoveElement(
this);
396 first->AddDominatedBlock(
this);
402 void HBasicBlock::AssignLoopSuccessorDominators() {
412 HBasicBlock* last = loop_information()->GetLastBackEdge();
413 int outstanding_successors = 1;
415 MarkAsLoopSuccessorDominator();
416 for (
int j = block_id(); j <= last->block_id(); ++j) {
417 HBasicBlock* dominator_candidate = graph_->blocks()->at(j);
418 for (HPredecessorIterator it(dominator_candidate); !it.Done();
420 HBasicBlock* predecessor = it.Current();
422 if (predecessor->block_id() < dominator_candidate->block_id()) {
423 outstanding_successors--;
435 DCHECK(outstanding_successors >= 0);
436 HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header();
437 if (outstanding_successors == 0 &&
438 (parent_loop_header ==
this && !dominator_candidate->IsLoopHeader())) {
439 dominator_candidate->MarkAsLoopSuccessorDominator();
441 HControlInstruction* end = dominator_candidate->end();
442 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
443 HBasicBlock* successor = it.Current();
446 if (successor->block_id() > dominator_candidate->block_id() &&
447 successor->block_id() <= last->block_id()) {
449 DCHECK(successor->block_id() > dominator_candidate->block_id() ||
450 successor->IsLoopHeader());
451 outstanding_successors++;
458 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor)
const {
459 for (
int i = 0;
i < predecessors_.length(); ++
i) {
460 if (predecessors_[
i] == predecessor)
return i;
468 void HBasicBlock::Verify() {
474 if (predecessors_.length() > 1) {
475 for (
int i = 0;
i < predecessors_.length(); ++
i) {
476 DCHECK(predecessors_[
i]->end()->SecondSuccessor() ==
NULL);
483 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
484 this->back_edges_.Add(block, block->zone());
489 HBasicBlock* HLoopInformation::GetLastBackEdge()
const {
491 HBasicBlock* result =
NULL;
492 for (
int i = 0;
i < back_edges_.length(); ++
i) {
493 HBasicBlock* cur = back_edges_[
i];
494 if (cur->block_id() > max_id) {
495 max_id = cur->block_id();
503 void HLoopInformation::AddBlock(HBasicBlock* block) {
504 if (block == loop_header())
return;
505 if (block->parent_loop_header() == loop_header())
return;
506 if (block->parent_loop_header() !=
NULL) {
507 AddBlock(block->parent_loop_header());
509 block->set_parent_loop_header(loop_header());
510 blocks_.Add(block, block->zone());
511 for (
int i = 0;
i < block->predecessors()->length(); ++
i) {
512 AddBlock(block->predecessors()->at(
i));
527 ReachabilityAnalyzer(HBasicBlock* entry_block,
529 HBasicBlock* dont_visit)
531 stack_(16, entry_block->zone()),
532 reachable_(block_count, entry_block->zone()),
533 dont_visit_(dont_visit) {
534 PushBlock(entry_block);
538 int visited_count()
const {
return visited_count_; }
539 const BitVector* reachable()
const {
return &reachable_; }
542 void PushBlock(HBasicBlock* block) {
543 if (block !=
NULL && block != dont_visit_ &&
544 !reachable_.Contains(block->block_id())) {
545 reachable_.Add(block->block_id());
546 stack_.Add(block, block->zone());
552 while (!stack_.is_empty()) {
553 HControlInstruction* end = stack_.RemoveLast()->end();
554 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
555 PushBlock(it.Current());
561 ZoneList<HBasicBlock*> stack_;
562 BitVector reachable_;
563 HBasicBlock* dont_visit_;
567 void HGraph::Verify(
bool do_full_verify)
const {
568 Heap::RelocationLock relocation_lock(isolate()->heap());
571 for (
int i = 0;
i < blocks_.length();
i++) {
572 HBasicBlock* block = blocks_.at(
i);
578 HInstruction* current = block->first();
579 DCHECK(current !=
NULL && current->IsBlockEntry());
580 while (current !=
NULL) {
581 DCHECK((current->next() ==
NULL) == current->IsControlInstruction());
582 DCHECK(current->block() == block);
584 current = current->next();
588 HBasicBlock* first = block->end()->FirstSuccessor();
589 HBasicBlock* second = block->end()->SecondSuccessor();
594 DCHECK(first->predecessors()->Contains(block));
595 if (second !=
NULL) {
596 DCHECK(second->predecessors()->Contains(block));
601 for (
int j = 0; j < block->phis()->length(); j++) {
602 HPhi* phi = block->phis()->at(j);
608 if (block->predecessors()->length() >= 2) {
610 block->predecessors()->first()->last_environment()->ast_id();
611 for (
int k = 0; k < block->predecessors()->length(); k++) {
612 HBasicBlock* predecessor = block->predecessors()->at(k);
613 DCHECK(predecessor->end()->IsGoto() ||
614 predecessor->end()->IsDeoptimize());
615 DCHECK(predecessor->last_environment()->ast_id() ==
id);
621 DCHECK(blocks_.at(0)->predecessors()->is_empty());
623 if (do_full_verify) {
625 ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(),
NULL);
626 DCHECK(analyzer.visited_count() == blocks_.length());
632 for (
int i = 0;
i < blocks_.length(); ++
i) {
633 HBasicBlock* block = blocks_.at(
i);
634 if (block->dominator() ==
NULL) {
639 ReachabilityAnalyzer dominator_analyzer(entry_block_,
642 DCHECK(!dominator_analyzer.reachable()->Contains(block->block_id()));
651 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
653 if (!pointer->is_set()) {
656 HConstant* constant = HConstant::New(zone(),
NULL, value);
657 constant->InsertAfter(entry_block()->first());
658 pointer->set(constant);
661 return ReinsertConstantIfNecessary(pointer->get());
665 HConstant* HGraph::ReinsertConstantIfNecessary(HConstant* constant) {
666 if (!constant->IsLinked()) {
668 constant->ClearFlag(HValue::kIsDead);
669 constant->InsertAfter(entry_block()->first());
675 HConstant* HGraph::GetConstant0() {
676 return GetConstant(&constant_0_, 0);
680 HConstant* HGraph::GetConstant1() {
681 return GetConstant(&constant_1_, 1);
685 HConstant* HGraph::GetConstantMinus1() {
686 return GetConstant(&constant_minus1_, -1);
690 #define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value) \
691 HConstant* HGraph::GetConstant##Name() { \
692 if (!constant_##name##_.is_set()) { \
693 HConstant* constant = new(zone()) HConstant( \
694 Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \
695 Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()), \
697 Representation::Tagged(), \
703 constant->InsertAfter(entry_block()->first()); \
704 constant_##name##_.set(constant); \
706 return ReinsertConstantIfNecessary(constant_##name##_.get()); \
717 #undef DEFINE_GET_CONSTANT
719 #define DEFINE_IS_CONSTANT(Name, name) \
720 bool HGraph::IsConstant##Name(HConstant* constant) { \
721 return constant_##name##_.is_set() && constant == constant_##name##_.get(); \
732 #undef DEFINE_IS_CONSTANT
735 HConstant* HGraph::GetInvalidContext() {
736 return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
740 bool HGraph::IsStandardConstant(HConstant* constant) {
741 if (IsConstantUndefined(constant))
return true;
742 if (IsConstant0(constant))
return true;
743 if (IsConstant1(constant))
return true;
744 if (IsConstantMinus1(constant))
return true;
745 if (IsConstantTrue(constant))
return true;
746 if (IsConstantFalse(constant))
return true;
747 if (IsConstantHole(constant))
return true;
748 if (IsConstantNull(constant))
return true;
753 HGraphBuilder::IfBuilder::IfBuilder() : builder_(
NULL), needs_compare_(
true) {}
756 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
757 : needs_compare_(
true) {
762 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder,
763 HIfContinuation* continuation)
764 : needs_compare_(
false), first_true_block_(
NULL), first_false_block_(
NULL) {
765 InitializeDontCreateBlocks(builder);
766 continuation->Continue(&first_true_block_, &first_false_block_);
770 void HGraphBuilder::IfBuilder::InitializeDontCreateBlocks(
771 HGraphBuilder* builder) {
776 did_else_if_ =
false;
780 pending_merge_block_ =
false;
781 split_edge_merge_block_ =
NULL;
782 merge_at_join_blocks_ =
NULL;
783 normal_merge_at_join_block_count_ = 0;
784 deopt_merge_at_join_block_count_ = 0;
788 void HGraphBuilder::IfBuilder::Initialize(HGraphBuilder* builder) {
789 InitializeDontCreateBlocks(builder);
790 HEnvironment* env = builder->environment();
791 first_true_block_ = builder->CreateBasicBlock(env->Copy());
792 first_false_block_ = builder->CreateBasicBlock(env->Copy());
796 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
797 HControlInstruction* compare) {
798 DCHECK(did_then_ == did_else_);
806 pending_merge_block_ =
false;
807 split_edge_merge_block_ =
NULL;
808 HEnvironment* env = builder()->environment();
809 first_true_block_ = builder()->CreateBasicBlock(env->Copy());
810 first_false_block_ = builder()->CreateBasicBlock(env->Copy());
812 if (split_edge_merge_block_ !=
NULL) {
813 HEnvironment* env = first_false_block_->last_environment();
814 HBasicBlock* split_edge = builder()->CreateBasicBlock(env->Copy());
816 compare->SetSuccessorAt(0, split_edge);
817 compare->SetSuccessorAt(1, first_false_block_);
819 compare->SetSuccessorAt(0, first_true_block_);
820 compare->SetSuccessorAt(1, split_edge);
822 builder()->GotoNoSimulate(split_edge, split_edge_merge_block_);
824 compare->SetSuccessorAt(0, first_true_block_);
825 compare->SetSuccessorAt(1, first_false_block_);
827 builder()->FinishCurrentBlock(compare);
828 needs_compare_ =
false;
833 void HGraphBuilder::IfBuilder::Or() {
837 HEnvironment* env = first_false_block_->last_environment();
838 if (split_edge_merge_block_ ==
NULL) {
839 split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
840 builder()->GotoNoSimulate(first_true_block_, split_edge_merge_block_);
841 first_true_block_ = split_edge_merge_block_;
843 builder()->set_current_block(first_false_block_);
844 first_false_block_ = builder()->CreateBasicBlock(env->Copy());
848 void HGraphBuilder::IfBuilder::And() {
852 HEnvironment* env = first_false_block_->last_environment();
853 if (split_edge_merge_block_ ==
NULL) {
854 split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
855 builder()->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
856 first_false_block_ = split_edge_merge_block_;
858 builder()->set_current_block(first_true_block_);
859 first_true_block_ = builder()->CreateBasicBlock(env->Copy());
863 void HGraphBuilder::IfBuilder::CaptureContinuation(
864 HIfContinuation* continuation) {
869 HBasicBlock* true_block =
NULL;
870 HBasicBlock* false_block =
NULL;
871 Finish(&true_block, &false_block);
874 continuation->Capture(true_block, false_block);
876 builder()->set_current_block(
NULL);
881 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
885 HBasicBlock* true_block =
NULL;
886 HBasicBlock* false_block =
NULL;
887 Finish(&true_block, &false_block);
888 merge_at_join_blocks_ =
NULL;
889 if (true_block !=
NULL && !true_block->IsFinished()) {
890 DCHECK(continuation->IsTrueReachable());
891 builder()->GotoNoSimulate(true_block, continuation->true_branch());
893 if (false_block !=
NULL && !false_block->IsFinished()) {
894 DCHECK(continuation->IsFalseReachable());
895 builder()->GotoNoSimulate(false_block, continuation->false_branch());
902 void HGraphBuilder::IfBuilder::Then() {
906 if (needs_compare_) {
911 HConstant* constant_false = builder()->graph()->GetConstantFalse();
912 ToBooleanStub::Types boolean_type = ToBooleanStub::Types();
913 boolean_type.Add(ToBooleanStub::BOOLEAN);
914 HBranch* branch = builder()->New<HBranch>(
915 constant_false, boolean_type, first_true_block_, first_false_block_);
916 builder()->FinishCurrentBlock(branch);
918 builder()->set_current_block(first_true_block_);
919 pending_merge_block_ =
true;
923 void HGraphBuilder::IfBuilder::Else() {
927 AddMergeAtJoinBlock(
false);
928 builder()->set_current_block(first_false_block_);
929 pending_merge_block_ =
true;
934 void HGraphBuilder::IfBuilder::Deopt(
const char* reason) {
936 builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
937 AddMergeAtJoinBlock(
true);
941 void HGraphBuilder::IfBuilder::Return(HValue* value) {
942 HValue* parameter_count = builder()->graph()->GetConstantMinus1();
943 builder()->FinishExitCurrentBlock(
944 builder()->New<HReturn>(value, parameter_count));
945 AddMergeAtJoinBlock(
false);
949 void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(
bool deopt) {
950 if (!pending_merge_block_)
return;
951 HBasicBlock* block = builder()->current_block();
952 DCHECK(block ==
NULL || !block->IsFinished());
953 MergeAtJoinBlock* record =
new (builder()->zone())
954 MergeAtJoinBlock(block, deopt, merge_at_join_blocks_);
955 merge_at_join_blocks_ = record;
959 normal_merge_at_join_block_count_++;
961 deopt_merge_at_join_block_count_++;
964 builder()->set_current_block(
NULL);
965 pending_merge_block_ =
false;
969 void HGraphBuilder::IfBuilder::Finish() {
974 AddMergeAtJoinBlock(
false);
977 AddMergeAtJoinBlock(
false);
983 void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation,
984 HBasicBlock** else_continuation) {
987 MergeAtJoinBlock* else_record = merge_at_join_blocks_;
988 if (else_continuation !=
NULL) {
989 *else_continuation = else_record->block_;
991 MergeAtJoinBlock* then_record = else_record->next_;
992 if (then_continuation !=
NULL) {
993 *then_continuation = then_record->block_;
999 void HGraphBuilder::IfBuilder::End() {
1000 if (captured_)
return;
1003 int total_merged_blocks = normal_merge_at_join_block_count_ +
1004 deopt_merge_at_join_block_count_;
1005 DCHECK(total_merged_blocks >= 1);
1006 HBasicBlock* merge_block =
1007 total_merged_blocks == 1 ?
NULL : builder()->graph()->CreateBasicBlock();
1011 MergeAtJoinBlock* current = merge_at_join_blocks_;
1012 while (current !=
NULL) {
1013 if (!current->deopt_ && current->block_ !=
NULL) {
1017 if (total_merged_blocks == 1) {
1018 builder()->set_current_block(current->block_);
1021 builder()->GotoNoSimulate(current->block_, merge_block);
1023 current = current->next_;
1027 current = merge_at_join_blocks_;
1028 while (current !=
NULL) {
1029 if (current->deopt_ && current->block_ !=
NULL) {
1030 current->block_->FinishExit(HAbnormalExit::New(builder()->zone(),
NULL),
1031 HSourcePosition::Unknown());
1033 current = current->next_;
1035 builder()->set_current_block(merge_block);
1039 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder) {
1040 Initialize(builder,
NULL, kWhileTrue,
NULL);
1044 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
1045 LoopBuilder::Direction direction) {
1046 Initialize(builder, context, direction, builder->graph()->GetConstant1());
1050 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
1051 LoopBuilder::Direction direction,
1052 HValue* increment_amount) {
1053 Initialize(builder, context, direction, increment_amount);
1054 increment_amount_ = increment_amount;
1058 void HGraphBuilder::LoopBuilder::Initialize(HGraphBuilder* builder,
1060 Direction direction,
1061 HValue* increment_amount) {
1064 direction_ = direction;
1065 increment_amount_ = increment_amount;
1068 header_block_ = builder->CreateLoopHeaderBlock();
1071 exit_trampoline_block_ =
NULL;
1075 HValue* HGraphBuilder::LoopBuilder::BeginBody(
1077 HValue* terminating,
1078 Token::Value token) {
1079 DCHECK(direction_ != kWhileTrue);
1080 HEnvironment* env = builder_->environment();
1081 phi_ = header_block_->AddNewPhi(env->values()->length());
1082 phi_->AddInput(initial);
1084 builder_->GotoNoSimulate(header_block_);
1086 HEnvironment* body_env = env->Copy();
1087 HEnvironment* exit_env = env->Copy();
1091 body_block_ = builder_->CreateBasicBlock(body_env);
1092 exit_block_ = builder_->CreateBasicBlock(exit_env);
1094 builder_->set_current_block(header_block_);
1096 builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>(
1097 phi_, terminating, token, body_block_, exit_block_));
1099 builder_->set_current_block(body_block_);
1100 if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
1101 HValue* one = builder_->graph()->GetConstant1();
1102 if (direction_ == kPreIncrement) {
1103 increment_ = HAdd::New(zone(), context_, phi_, one);
1105 increment_ = HSub::New(zone(), context_, phi_, one);
1107 increment_->ClearFlag(HValue::kCanOverflow);
1108 builder_->AddInstruction(increment_);
1116 void HGraphBuilder::LoopBuilder::BeginBody(
int drop_count) {
1117 DCHECK(direction_ == kWhileTrue);
1118 HEnvironment* env = builder_->environment();
1119 builder_->GotoNoSimulate(header_block_);
1120 builder_->set_current_block(header_block_);
1121 env->Drop(drop_count);
1126 if (exit_trampoline_block_ ==
NULL) {
1128 if (direction_ == kWhileTrue) {
1129 HEnvironment* env = builder_->environment()->Copy();
1130 exit_trampoline_block_ = builder_->CreateBasicBlock(env);
1132 HEnvironment* env = exit_block_->last_environment()->Copy();
1133 exit_trampoline_block_ = builder_->CreateBasicBlock(env);
1134 builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
1138 builder_->GotoNoSimulate(exit_trampoline_block_);
1139 builder_->set_current_block(
NULL);
1143 void HGraphBuilder::LoopBuilder::EndBody() {
1146 if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
1147 if (direction_ == kPostIncrement) {
1148 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_);
1150 increment_ = HSub::New(zone(), context_, phi_, increment_amount_);
1152 increment_->ClearFlag(HValue::kCanOverflow);
1153 builder_->AddInstruction(increment_);
1156 if (direction_ != kWhileTrue) {
1159 builder_->environment()->Push(increment_);
1161 HBasicBlock* last_block = builder_->current_block();
1162 builder_->GotoNoSimulate(last_block, header_block_);
1163 header_block_->loop_information()->RegisterBackEdge(last_block);
1165 if (exit_trampoline_block_ !=
NULL) {
1166 builder_->set_current_block(exit_trampoline_block_);
1168 builder_->set_current_block(exit_block_);
1174 HGraph* HGraphBuilder::CreateGraph() {
1175 graph_ =
new(zone()) HGraph(info_);
1176 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
1178 set_current_block(graph()->entry_block());
1179 if (!BuildGraph())
return NULL;
1180 graph()->FinalizeUniqueness();
1187 DCHECK(!FLAG_hydrogen_track_positions ||
1188 !position_.IsUnknown() ||
1189 !info_->IsOptimizing());
1190 current_block()->AddInstruction(instr, source_position());
1191 if (graph()->IsInsideNoSideEffectsScope()) {
1192 instr->
SetFlag(HValue::kHasNoObservableSideEffects);
1199 DCHECK(!FLAG_hydrogen_track_positions ||
1200 !info_->IsOptimizing() ||
1201 !position_.IsUnknown());
1202 current_block()->Finish(last, source_position());
1203 if (last->IsReturn() || last->IsAbnormalExit()) {
1204 set_current_block(
NULL);
1210 DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
1211 !position_.IsUnknown());
1212 current_block()->FinishExit(instruction, source_position());
1213 if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
1214 set_current_block(
NULL);
1220 if (FLAG_native_code_counters && counter->
Enabled()) {
1221 HValue* reference = Add<HConstant>(ExternalReference(counter));
1222 HValue* old_value = Add<HLoadNamedField>(
1223 reference,
static_cast<HValue*
>(
NULL), HObjectAccess::ForCounter());
1224 HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1());
1225 new_value->
ClearFlag(HValue::kCanOverflow);
1226 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
1235 DCHECK(!graph()->IsInsideNoSideEffectsScope());
1236 current_block()->AddNewSimulate(
id, source_position(), removable);
1240 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
1241 HBasicBlock* b = graph()->CreateBasicBlock();
1242 b->SetInitialEnvironment(env);
1247 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
1248 HBasicBlock* header = graph()->CreateBasicBlock();
1249 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
1250 header->SetInitialEnvironment(entry_env);
1251 header->AttachLoopInformation();
1258 HObjectAccess::ForMap());
1261 HObjectAccess::ForMapBitField2());
1262 return BuildDecodeField<Map::ElementsKindBits>(bit_field2);
1267 if (obj->
type().IsHeapObject())
return obj;
1268 return Add<HCheckHeapObject>(obj);
1272 void HGraphBuilder::FinishExitWithHardDeoptimization(
const char* reason) {
1273 Add<HDeoptimize>(reason, Deoptimizer::EAGER);
1274 FinishExitCurrentBlock(New<HAbnormalExit>());
1279 if (!string->
type().IsString()) {
1280 DCHECK(!string->IsConstant() ||
1281 !HConstant::cast(
string)->HasStringValue());
1282 BuildCheckHeapObject(
string);
1283 return Add<HCheckInstanceType>(
string, HCheckInstanceType::IS_STRING);
1290 if (object->
type().IsJSObject())
return object;
1291 if (function->IsConstant() &&
1292 HConstant::cast(
function)->handle(isolate())->IsJSFunction()) {
1294 HConstant::cast(
function)->
handle(isolate()));
1298 return Add<HWrapReceiver>(
object,
function);
1302 HValue* HGraphBuilder::BuildCheckForCapacityGrow(
1310 IfBuilder length_checker(
this);
1315 length_checker.Then();
1317 HValue* current_capacity = AddLoadFixedArrayLength(elements);
1319 IfBuilder capacity_checker(
this);
1323 capacity_checker.Then();
1325 HValue* max_gap = Add<HConstant>(
static_cast<int32_t>(JSObject::kMaxGap));
1326 HValue* max_capacity = AddUncasted<HAdd>(current_capacity, max_gap);
1328 Add<HBoundsCheck>(key, max_capacity);
1330 HValue* new_capacity = BuildNewElementsCapacity(key);
1331 HValue* new_elements = BuildGrowElementsCapacity(
object, elements,
1335 environment()->Push(new_elements);
1336 capacity_checker.Else();
1338 environment()->Push(elements);
1339 capacity_checker.End();
1342 HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
1343 new_length->
ClearFlag(HValue::kCanOverflow);
1345 Add<HStoreNamedField>(
object, HObjectAccess::ForArrayLength(kind),
1350 HValue* checked_elements = environment()->Top();
1353 Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind);
1356 length_checker.Else();
1357 Add<HBoundsCheck>(key, length);
1359 environment()->Push(elements);
1360 length_checker.End();
1362 return environment()->Pop();
1370 Factory* factory = isolate()->factory();
1372 IfBuilder cow_checker(
this);
1374 cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
1377 HValue* capacity = AddLoadFixedArrayLength(elements);
1379 HValue* new_elements = BuildGrowElementsCapacity(
object, elements, kind,
1380 kind, length, capacity);
1382 environment()->Push(new_elements);
1386 environment()->Push(elements);
1390 return environment()->Pop();
1394 void HGraphBuilder::BuildTransitionElementsKind(
HValue*
object,
1403 Add<HTrapAllocationMemento>(
object);
1410 isolate()->factory()->empty_fixed_array());
1412 IfBuilder if_builder(
this);
1418 HInstruction* elements_length = AddLoadFixedArrayLength(elements);
1421 ? Add<HLoadNamedField>(
object,
static_cast<HValue*
>(
NULL),
1422 HObjectAccess::ForArrayLength(from_kind))
1425 BuildGrowElementsCapacity(
object, elements, from_kind, to_kind,
1426 array_length, elements_length);
1431 Add<HStoreNamedField>(
object, HObjectAccess::ForMap(),
map);
1435 void HGraphBuilder::BuildJSObjectCheck(
HValue* receiver,
1436 int bit_field_mask) {
1438 Add<HCheckHeapObject>(receiver);
1442 HObjectAccess::ForMap());
1446 HObjectAccess access(HObjectAccess::ForMapInstanceTypeAndBitField());
1447 HValue* instance_type_and_bit_field =
1448 Add<HLoadNamedField>(
map,
static_cast<HValue*
>(
NULL), access);
1450 HValue* mask = Add<HConstant>(0x00FF | (bit_field_mask << 8));
1451 HValue* and_result = AddUncasted<HBitwise>(Token::BIT_AND,
1452 instance_type_and_bit_field,
1454 HValue* sub_result = AddUncasted<HSub>(and_result,
1456 Add<HBoundsCheck>(sub_result,
1461 void HGraphBuilder::BuildKeyedIndexCheck(
HValue* key,
1462 HIfContinuation* join_continuation) {
1469 IfBuilder key_smi_if(
this);
1470 key_smi_if.If<HIsSmiAndBranch>(key);
1478 HObjectAccess::ForMap());
1481 HObjectAccess::ForMapInstanceType());
1486 IfBuilder not_string_or_name_if(
this);
1492 not_string_or_name_if.Then();
1497 Push(AddUncasted<HForceRepresentation>(key, Representation::Smi()));
1499 not_string_or_name_if.Else();
1503 IfBuilder not_symbol_if(
this);
1509 not_symbol_if.Then();
1514 Add<HLoadNamedField>(key,
static_cast<HValue*
>(
NULL),
1515 HObjectAccess::ForNameHashField());
1516 HValue* not_index_mask = Add<HConstant>(
static_cast<int>(
1517 String::kContainsCachedArrayIndexMask));
1519 HValue* not_index_test = AddUncasted<HBitwise>(
1520 Token::BIT_AND, hash, not_index_mask);
1522 IfBuilder string_index_if(
this);
1524 graph()->GetConstant0(),
1526 string_index_if.Then();
1529 Push(BuildDecodeField<String::ArrayIndexValueBits>(hash));
1531 string_index_if.Else();
1535 HValue* not_internalized_bit = AddUncasted<HBitwise>(
1540 IfBuilder internalized(
this);
1542 graph()->GetConstant0(),
1544 internalized.Then();
1547 internalized.Else();
1548 Add<HPushArguments>(key);
1549 HValue* intern_key = Add<HCallRuntime>(
1550 isolate()->factory()->empty_string(),
1551 Runtime::FunctionForId(Runtime::kInternalizeString), 1);
1557 string_index_if.JoinContinuation(join_continuation);
1559 not_symbol_if.Else();
1563 not_symbol_if.JoinContinuation(join_continuation);
1565 not_string_or_name_if.JoinContinuation(join_continuation);
1567 key_smi_if.JoinContinuation(join_continuation);
1571 void HGraphBuilder::BuildNonGlobalObjectCheck(
HValue* receiver) {
1575 HObjectAccess::ForMap());
1578 HObjectAccess::ForMapInstanceType());
1583 IfBuilder if_global_object(
this);
1587 if_global_object.And();
1591 if_global_object.ThenDeopt(
"receiver was a global object");
1592 if_global_object.End();
1596 void HGraphBuilder::BuildTestForDictionaryProperties(
1598 HIfContinuation* continuation) {
1599 HValue* properties = Add<HLoadNamedField>(
1601 HObjectAccess::ForPropertiesPointer());
1603 Add<HLoadNamedField>(properties,
static_cast<HValue*
>(
NULL),
1604 HObjectAccess::ForMap());
1605 HValue* hash_map = Add<HLoadRoot>(Heap::kHashTableMapRootIndex);
1606 IfBuilder builder(
this);
1608 builder.CaptureContinuation(continuation);
1617 Add<HLoadNamedField>(
object,
static_cast<HValue*
>(
NULL),
1618 HObjectAccess::ForMapAsInteger32());
1619 HValue* shifted_map = AddUncasted<HShr>(
1620 object_map, Add<HConstant>(KeyedLookupCache::kMapHashShift));
1622 Add<HLoadNamedField>(key,
static_cast<HValue*
>(
NULL),
1623 HObjectAccess::ForStringHashField());
1624 HValue* shifted_hash = AddUncasted<HShr>(
1625 string_hash, Add<HConstant>(String::kHashShift));
1626 HValue* xor_result = AddUncasted<HBitwise>(Token::BIT_XOR, shifted_map,
1628 int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
1629 return AddUncasted<HBitwise>(Token::BIT_AND, xor_result,
1630 Add<HConstant>(mask));
1635 int32_t seed_value =
static_cast<uint32_t>(isolate()->heap()->HashSeed());
1636 HValue* seed = Add<HConstant>(seed_value);
1637 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed);
1640 HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15));
1641 HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash,
1642 graph()->GetConstantMinus1());
1643 hash = AddUncasted<HAdd>(shifted_hash, not_hash);
1646 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(12));
1647 hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1650 shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(2));
1651 hash = AddUncasted<HAdd>(hash, shifted_hash);
1654 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(4));
1655 hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1658 hash = AddUncasted<HMul>(hash, Add<HConstant>(2057));
1662 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16));
1663 return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1667 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
HValue* receiver,
1671 HValue* capacity = Add<HLoadKeyed>(
1673 Add<HConstant>(NameDictionary::kCapacityIndex),
1677 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1());
1682 HValue* count = graph()->GetConstant1();
1686 HIfContinuation return_or_loop_continuation(graph()->CreateBasicBlock(),
1687 graph()->CreateBasicBlock());
1688 HIfContinuation found_key_match_continuation(graph()->CreateBasicBlock(),
1689 graph()->CreateBasicBlock());
1690 LoopBuilder probe_loop(
this);
1691 probe_loop.BeginBody(2);
1696 entry = AddUncasted<HBitwise>(Token::BIT_AND, entry, mask);
1697 int entry_size = SeededNumberDictionary::kEntrySize;
1698 HValue* base_index = AddUncasted<HMul>(entry, Add<HConstant>(entry_size));
1699 base_index->
ClearFlag(HValue::kCanOverflow);
1700 int start_offset = SeededNumberDictionary::kElementsStartIndex;
1702 AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset));
1703 key_index->
ClearFlag(HValue::kCanOverflow);
1705 HValue* candidate_key = Add<HLoadKeyed>(
1707 IfBuilder if_undefined(
this);
1709 graph()->GetConstantUndefined());
1710 if_undefined.Then();
1714 Add<HPushArguments>(receiver, key);
1715 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
1716 Runtime::FunctionForId(Runtime::kKeyedGetProperty),
1719 if_undefined.Else();
1721 IfBuilder if_match(
this);
1727 IfBuilder if_update_with_internalized(
this);
1729 if_update_with_internalized.IfNot<HIsSmiAndBranch>(candidate_key);
1730 if_update_with_internalized.And();
1731 HValue*
map = AddLoadMap(candidate_key, smi_check);
1732 HValue* instance_type = Add<HLoadNamedField>(
1733 map,
static_cast<HValue*
>(
NULL), HObjectAccess::ForMapInstanceType());
1734 HValue* not_internalized_bit = AddUncasted<HBitwise>(
1735 Token::BIT_AND, instance_type,
1738 not_internalized_bit, graph()->GetConstant0(), Token::NE);
1739 if_update_with_internalized.And();
1741 candidate_key, graph()->GetConstantHole());
1744 if_update_with_internalized.Then();
1748 if_update_with_internalized.Else();
1750 if_update_with_internalized.JoinContinuation(&found_key_match_continuation);
1751 if_match.JoinContinuation(&found_key_match_continuation);
1753 IfBuilder found_key_match(
this, &found_key_match_continuation);
1754 found_key_match.Then();
1758 AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 2));
1759 details_index->
ClearFlag(HValue::kCanOverflow);
1760 HValue* details = Add<HLoadKeyed>(
1762 int details_mask = PropertyDetails::TypeField::kMask |
1763 PropertyDetails::DeletedField::kMask;
1764 details = AddUncasted<HBitwise>(Token::BIT_AND, details,
1765 Add<HConstant>(details_mask));
1766 IfBuilder details_compare(
this);
1768 details, graph()->GetConstant0(),
Token::EQ);
1769 details_compare.Then();
1771 AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1));
1772 result_index->
ClearFlag(HValue::kCanOverflow);
1773 Push(Add<HLoadKeyed>(elements, result_index,
static_cast<HValue*
>(
NULL),
1775 details_compare.Else();
1776 Add<HPushArguments>(receiver, key);
1777 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
1778 Runtime::FunctionForId(Runtime::kKeyedGetProperty),
1780 details_compare.End();
1782 found_key_match.Else();
1783 found_key_match.JoinContinuation(&return_or_loop_continuation);
1785 if_undefined.JoinContinuation(&return_or_loop_continuation);
1787 IfBuilder return_or_loop(
this, &return_or_loop_continuation);
1788 return_or_loop.Then();
1791 return_or_loop.Else();
1792 entry = AddUncasted<HAdd>(entry, count);
1794 count = AddUncasted<HAdd>(count, graph()->GetConstant1());
1799 probe_loop.EndBody();
1801 return_or_loop.End();
1810 NoObservableSideEffectsScope scope(
this);
1811 HConstant* max_length = Add<HConstant>(JSObject::kInitialMaxFastElementArray);
1812 Add<HBoundsCheck>(length, max_length);
1817 HValue*
size = BuildCalculateElementsSize(elements_kind, length);
1820 HValue* result = Add<HAllocate>(
1821 Add<HConstant>(JSRegExpResult::kSize), HType::JSArray(),
1825 HValue* global_object = Add<HLoadNamedField>(
1827 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
1828 HValue* native_context = Add<HLoadNamedField>(
1830 HObjectAccess::ForGlobalObjectNativeContext());
1831 Add<HStoreNamedField>(
1832 result, HObjectAccess::ForMap(),
1833 Add<HLoadNamedField>(
1835 HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX)));
1836 HConstant* empty_fixed_array =
1837 Add<HConstant>(isolate()->factory()->empty_fixed_array());
1838 Add<HStoreNamedField>(
1839 result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
1841 Add<HStoreNamedField>(
1842 result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
1844 Add<HStoreNamedField>(
1845 result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), length);
1848 Add<HStoreNamedField>(
1849 result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kIndexOffset),
1851 Add<HStoreNamedField>(
1852 result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset),
1856 HAllocate* elements = BuildAllocateElements(elements_kind,
size);
1857 BuildInitializeElementsHeader(elements, elements_kind, length);
1859 if (!elements->has_size_upper_bound()) {
1860 HConstant* size_in_bytes_upper_bound = EstablishElementsAllocationSize(
1861 elements_kind, max_length->Integer32Value());
1862 elements->set_size_upper_bound(size_in_bytes_upper_bound);
1865 Add<HStoreNamedField>(
1866 result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
1870 BuildFillElementsWithValue(
1871 elements, elements_kind, graph()->GetConstant0(), length,
1872 graph()->GetConstantUndefined());
1879 NoObservableSideEffectsScope scope(
this);
1882 if (object->IsConstant() && HConstant::cast(
object)->HasNumberValue()) {
1883 Handle<Object> number = HConstant::cast(
object)->handle(isolate());
1884 Handle<String> result = isolate()->factory()->NumberToString(number);
1885 return Add<HConstant>(result);
1889 HIfContinuation found(graph()->CreateBasicBlock(),
1890 graph()->CreateBasicBlock());
1893 HValue* number_string_cache =
1894 Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);
1898 HValue* mask = AddLoadFixedArrayLength(number_string_cache);
1900 mask = AddUncasted<HSar>(mask, graph()->GetConstant1());
1901 mask = AddUncasted<HSub>(mask, graph()->GetConstant1());
1904 IfBuilder if_objectissmi(
this);
1905 if_objectissmi.If<HIsSmiAndBranch>(object);
1906 if_objectissmi.Then();
1909 HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND,
object, mask);
1912 HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
1913 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index,
1918 IfBuilder if_objectiskey(
this);
1920 if_objectiskey.Then();
1925 if_objectiskey.JoinContinuation(&found);
1927 if_objectissmi.Else();
1929 if (type->
Is(Type::SignedSmall())) {
1930 if_objectissmi.Deopt(
"Expected smi");
1933 IfBuilder if_objectisnumber(
this);
1934 HValue* objectisnumber = if_objectisnumber.If<HCompareMap>(
1935 object, isolate()->factory()->heap_number_map());
1936 if_objectisnumber.Then();
1939 HValue* low = Add<HLoadNamedField>(
1940 object, objectisnumber,
1941 HObjectAccess::ForHeapNumberValueLowestBits());
1942 HValue* high = Add<HLoadNamedField>(
1943 object, objectisnumber,
1944 HObjectAccess::ForHeapNumberValueHighestBits());
1945 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high);
1946 hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask);
1949 HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
1950 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index,
1955 IfBuilder if_keyisnotsmi(
this);
1956 HValue* keyisnotsmi = if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key);
1957 if_keyisnotsmi.Then();
1959 IfBuilder if_keyisheapnumber(
this);
1960 if_keyisheapnumber.If<HCompareMap>(
1961 key, isolate()->factory()->heap_number_map());
1962 if_keyisheapnumber.Then();
1965 IfBuilder if_keyeqobject(
this);
1967 Add<HLoadNamedField>(key, keyisnotsmi,
1968 HObjectAccess::ForHeapNumberValue()),
1969 Add<HLoadNamedField>(
object, objectisnumber,
1970 HObjectAccess::ForHeapNumberValue()),
1972 if_keyeqobject.Then();
1977 if_keyeqobject.JoinContinuation(&found);
1979 if_keyisheapnumber.JoinContinuation(&found);
1981 if_keyisnotsmi.JoinContinuation(&found);
1983 if_objectisnumber.Else();
1985 if (type->
Is(Type::Number())) {
1986 if_objectisnumber.Deopt(
"Expected heap number");
1989 if_objectisnumber.JoinContinuation(&found);
1992 if_objectissmi.JoinContinuation(&found);
1995 IfBuilder if_found(
this, &found);
1999 AddIncrementCounter(isolate()->counters()->number_to_string_native());
2002 HValue* key_index = Pop();
2003 HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1());
2004 Push(Add<HLoadKeyed>(number_string_cache, value_index,
2011 Add<HPushArguments>(
object);
2012 Push(Add<HCallRuntime>(
2013 isolate()->factory()->empty_string(),
2014 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
2023 HAllocate* HGraphBuilder::BuildAllocate(
2027 HAllocationMode allocation_mode) {
2030 if (allocation_mode.CreateAllocationMementos()) {
2031 size = AddUncasted<HAdd>(
size, Add<HConstant>(AllocationMemento::kSize));
2032 size->ClearFlag(HValue::kCanOverflow);
2036 HAllocate*
object = Add<HAllocate>(
2037 size, type, allocation_mode.GetPretenureMode(),
2038 instance_type, allocation_mode.feedback_site());
2041 if (allocation_mode.CreateAllocationMementos()) {
2042 BuildCreateAllocationMemento(
2043 object, object_size, allocation_mode.current_site());
2053 HValue* length = AddUncasted<HAdd>(left_length, right_length);
2055 HValue* max_length = Add<HConstant>(String::kMaxLength + 1);
2056 Add<HBoundsCheck>(length, max_length);
2061 HValue* HGraphBuilder::BuildCreateConsString(
2065 HAllocationMode allocation_mode) {
2067 HInstruction* left_instance_type = AddLoadStringInstanceType(left);
2068 HInstruction* right_instance_type = AddLoadStringInstanceType(right);
2076 HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize),
2081 HValue* anded_instance_types = AddUncasted<HBitwise>(
2082 Token::BIT_AND, left_instance_type, right_instance_type);
2083 HValue* xored_instance_types = AddUncasted<HBitwise>(
2084 Token::BIT_XOR, left_instance_type, right_instance_type);
2095 IfBuilder if_onebyte(
this);
2099 AddUncasted<HBitwise>(
2100 Token::BIT_AND, anded_instance_types,
2101 Add<HConstant>(
static_cast<int32_t>(
2103 graph()->GetConstant0(), Token::NE);
2109 AddUncasted<HBitwise>(
2110 Token::BIT_AND, xored_instance_types,
2111 Add<HConstant>(
static_cast<int32_t>(
2113 Add<HConstant>(
static_cast<int32_t>(
2118 Add<HStoreNamedField>(
2119 result, HObjectAccess::ForMap(),
2120 Add<HConstant>(isolate()->factory()->cons_one_byte_string_map()));
2125 Add<HStoreNamedField>(
2126 result, HObjectAccess::ForMap(),
2127 Add<HConstant>(isolate()->factory()->cons_string_map()));
2132 Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
2133 Add<HConstant>(String::kEmptyHashField));
2134 Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
2135 Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left);
2136 Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right);
2139 AddIncrementCounter(isolate()->counters()->string_add_native());
2145 void HGraphBuilder::BuildCopySeqStringChars(
HValue* src,
2152 DCHECK(dst_encoding != String::ONE_BYTE_ENCODING ||
2153 src_encoding == String::ONE_BYTE_ENCODING);
2154 LoopBuilder loop(
this, context(), LoopBuilder::kPostIncrement);
2155 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
2157 HValue* src_index = AddUncasted<HAdd>(src_offset, index);
2159 AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index);
2160 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index);
2161 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
2167 HValue* HGraphBuilder::BuildObjectSizeAlignment(
2168 HValue* unaligned_size,
int header_size) {
2171 unaligned_size, Add<HConstant>(
static_cast<int32_t>(
2173 size->ClearFlag(HValue::kCanOverflow);
2174 return AddUncasted<HBitwise>(
2175 Token::BIT_AND,
size, Add<HConstant>(
static_cast<int32_t>(
2180 HValue* HGraphBuilder::BuildUncheckedStringAdd(
2183 HAllocationMode allocation_mode) {
2185 HValue* left_length = AddLoadStringLength(left);
2186 HValue* right_length = AddLoadStringLength(right);
2189 HValue* length = BuildAddStringLengths(left_length, right_length);
2192 if (left_length->IsConstant()) {
2193 HConstant* c_left_length = HConstant::cast(left_length);
2194 DCHECK_NE(0, c_left_length->Integer32Value());
2195 if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) {
2197 return BuildCreateConsString(length, left, right, allocation_mode);
2199 }
else if (right_length->IsConstant()) {
2200 HConstant* c_right_length = HConstant::cast(right_length);
2201 DCHECK_NE(0, c_right_length->Integer32Value());
2202 if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) {
2204 return BuildCreateConsString(length, left, right, allocation_mode);
2209 IfBuilder if_createcons(
this);
2211 length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
2212 if_createcons.Then();
2215 Push(BuildCreateConsString(length, left, right, allocation_mode));
2217 if_createcons.Else();
2220 HValue* left_instance_type = AddLoadStringInstanceType(left);
2221 HValue* right_instance_type = AddLoadStringInstanceType(right);
2224 HValue* ored_instance_types = AddUncasted<HBitwise>(
2225 Token::BIT_OR, left_instance_type, right_instance_type);
2226 HValue* xored_instance_types = AddUncasted<HBitwise>(
2227 Token::BIT_XOR, left_instance_type, right_instance_type);
2231 IfBuilder if_sameencodingandsequential(
this);
2233 AddUncasted<HBitwise>(
2234 Token::BIT_AND, xored_instance_types,
2237 if_sameencodingandsequential.And();
2240 AddUncasted<HBitwise>(
2241 Token::BIT_AND, ored_instance_types,
2244 if_sameencodingandsequential.Then();
2246 HConstant* string_map =
2247 Add<HConstant>(isolate()->factory()->string_map());
2248 HConstant* one_byte_string_map =
2249 Add<HConstant>(isolate()->factory()->one_byte_string_map());
2252 IfBuilder if_onebyte(
this);
2255 AddUncasted<HBitwise>(
2256 Token::BIT_AND, ored_instance_types,
2258 graph()->GetConstant0(), Token::NE);
2263 Push(one_byte_string_map);
2268 HValue*
size = AddUncasted<HShl>(length, graph()->GetConstant1());
2269 size->ClearFlag(HValue::kCanOverflow);
2270 size->SetFlag(HValue::kUint32);
2280 HValue*
size = BuildObjectSizeAlignment(Pop(), SeqString::kHeaderSize);
2284 HAllocate* result = BuildAllocate(
2286 Add<HStoreNamedField>(result, HObjectAccess::ForMap(),
map);
2289 Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
2290 Add<HConstant>(String::kEmptyHashField));
2291 Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
2294 IfBuilder if_twobyte(
this);
2299 BuildCopySeqStringChars(
2300 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2301 result, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2305 BuildCopySeqStringChars(
2306 right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2307 result, left_length, String::TWO_BYTE_ENCODING,
2313 BuildCopySeqStringChars(
2314 left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2315 result, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2319 BuildCopySeqStringChars(
2320 right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2321 result, left_length, String::ONE_BYTE_ENCODING,
2327 AddIncrementCounter(isolate()->counters()->string_add_native());
2332 if_sameencodingandsequential.Else();
2335 Add<HPushArguments>(left, right);
2336 Push(Add<HCallRuntime>(
2337 isolate()->factory()->empty_string(),
2338 Runtime::FunctionForId(Runtime::kStringAdd),
2341 if_sameencodingandsequential.End();
2343 if_createcons.End();
2352 HAllocationMode allocation_mode) {
2353 NoObservableSideEffectsScope no_effects(
this);
2356 HValue* left_length = AddLoadStringLength(left);
2357 HValue* right_length = AddLoadStringLength(right);
2360 IfBuilder if_leftempty(
this);
2362 left_length, graph()->GetConstant0(),
Token::EQ);
2363 if_leftempty.Then();
2366 AddIncrementCounter(isolate()->counters()->string_add_native());
2371 if_leftempty.Else();
2374 IfBuilder if_rightempty(
this);
2376 right_length, graph()->GetConstant0(),
Token::EQ);
2377 if_rightempty.Then();
2380 AddIncrementCounter(isolate()->counters()->string_add_native());
2385 if_rightempty.Else();
2388 Push(BuildUncheckedStringAdd(left, right, allocation_mode));
2390 if_rightempty.End();
2423 HValue* elements = AddLoadElements(checked_object);
2424 if (access_type ==
STORE && (fast_elements || fast_smi_only_elements) &&
2426 HCheckMaps* check_cow_map = Add<HCheckMaps>(
2427 elements, isolate()->factory()->fixed_array_map());
2428 check_cow_map->ClearDependsOnFlag(kElementsKind);
2432 length = Add<HLoadNamedField>(
2434 HObjectAccess::ForArrayLength(elements_kind));
2436 length = AddLoadFixedArrayLength(elements);
2444 backing_store = Add<HLoadNamedField>(
2446 HObjectAccess::ForExternalArrayExternalPointer());
2448 backing_store = elements;
2451 NoObservableSideEffectsScope no_effects(
this);
2452 IfBuilder length_checker(
this);
2454 length_checker.Then();
2455 IfBuilder negative_checker(
this);
2457 key, graph()->GetConstant0(), Token::GTE);
2458 negative_checker.Then();
2460 backing_store, key, val, bounds_check, elements_kind, access_type);
2461 negative_checker.ElseDeopt(
"Negative key encountered");
2462 negative_checker.End();
2463 length_checker.End();
2467 checked_key = Add<HBoundsCheck>(key, length);
2468 return AddElementAccess(
2469 backing_store, checked_key, val,
2470 checked_object, elements_kind, access_type);
2473 DCHECK(fast_smi_only_elements ||
2481 !val->
type().IsSmi()) {
2482 val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
2486 NoObservableSideEffectsScope no_effects(
this);
2487 Representation representation = HStoreKeyed::RequiredValueRepresentation(
2489 val = AddUncasted<HForceRepresentation>(val, representation);
2490 elements = BuildCheckForCapacityGrow(checked_object, elements,
2491 elements_kind, length, key,
2492 is_js_array, access_type);
2495 checked_key = Add<HBoundsCheck>(key, length);
2497 if (access_type ==
STORE && (fast_elements || fast_smi_only_elements)) {
2499 NoObservableSideEffectsScope no_effects(
this);
2500 elements = BuildCopyElementsOnWrite(checked_object, elements,
2501 elements_kind, length);
2503 HCheckMaps* check_cow_map = Add<HCheckMaps>(
2504 elements, isolate()->factory()->fixed_array_map());
2505 check_cow_map->ClearDependsOnFlag(kElementsKind);
2509 return AddElementAccess(elements, checked_key, val, checked_object,
2510 elements_kind, access_type, load_mode);
2514 HValue* HGraphBuilder::BuildAllocateArrayFromLength(
2515 JSArrayBuilder* array_builder,
2516 HValue* length_argument) {
2517 if (length_argument->IsConstant() &&
2518 HConstant::cast(length_argument)->HasSmiValue()) {
2519 int array_length = HConstant::cast(length_argument)->Integer32Value();
2520 if (array_length == 0) {
2521 return array_builder->AllocateEmptyArray();
2523 return array_builder->AllocateArray(length_argument,
2529 HValue* constant_zero = graph()->GetConstant0();
2530 HConstant* max_alloc_length =
2531 Add<HConstant>(JSObject::kInitialMaxFastElementArray);
2532 HInstruction* checked_length = Add<HBoundsCheck>(length_argument,
2534 IfBuilder if_builder(
this);
2538 const int initial_capacity = JSArray::kPreallocatedArrayElements;
2539 HConstant* initial_capacity_node = Add<HConstant>(initial_capacity);
2540 Push(initial_capacity_node);
2541 Push(constant_zero);
2543 if (!(top_info()->IsStub()) &&
2546 if_builder.Deopt(
"Holey array despite packed elements_kind feedback");
2548 Push(checked_length);
2549 Push(checked_length);
2555 HValue* capacity = Pop();
2556 return array_builder->AllocateArray(capacity, max_alloc_length, length);
2566 HConstant* elements_size_value = Add<HConstant>(elements_size);
2569 elements_size_value);
2570 AddInstruction(mul);
2573 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
2575 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
2576 HValue* total_size = AddUncasted<HAdd>(mul, header_size);
2577 total_size->
ClearFlag(HValue::kCanOverflow);
2583 int base_size = JSArray::kSize;
2585 base_size += AllocationMemento::kSize;
2587 HConstant* size_in_bytes = Add<HConstant>(base_size);
2588 return Add<HAllocate>(
2593 HConstant* HGraphBuilder::EstablishElementsAllocationSize(
2597 ? FixedDoubleArray::SizeFor(capacity)
2598 : FixedArray::SizeFor(capacity);
2600 return Add<HConstant>(base_size);
2610 return Add<HAllocate>(size_in_bytes, HType::HeapObject(),
NOT_TENURED,
2615 void HGraphBuilder::BuildInitializeElementsHeader(
HValue* elements,
2618 Factory* factory = isolate()->factory();
2620 ? factory->fixed_double_array_map()
2621 : factory->fixed_array_map();
2623 Add<HStoreNamedField>(elements, HObjectAccess::ForMap(), Add<HConstant>(
map));
2624 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
2629 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader(
2634 capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
2635 HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity);
2636 HValue* new_elements = BuildAllocateElements(kind, size_in_bytes);
2637 BuildInitializeElementsHeader(new_elements, kind, capacity);
2638 return new_elements;
2642 void HGraphBuilder::BuildJSArrayHeader(
HValue* array,
2647 HValue* allocation_site_payload,
2649 Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);
2651 HConstant* empty_fixed_array =
2652 Add<HConstant>(isolate()->factory()->empty_fixed_array());
2654 Add<HStoreNamedField>(
2655 array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array);
2657 Add<HStoreNamedField>(
2658 array, HObjectAccess::ForElementsPointer(),
2659 elements !=
NULL ? elements : empty_fixed_array);
2661 Add<HStoreNamedField>(
2662 array, HObjectAccess::ForArrayLength(elements_kind), length_field);
2665 BuildCreateAllocationMemento(
2666 array, Add<HConstant>(JSArray::kSize), allocation_site_payload);
2679 if (access_type ==
STORE) {
2683 val = Add<HClampToUint8>(val);
2685 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind,
2691 HLoadKeyed* load = Add<HLoadKeyed>(
2692 elements, checked_key, dependency, elements_kind, load_mode);
2693 if (FLAG_opt_safe_uint32_operations &&
2696 graph()->RecordUint32Instruction(load);
2702 HLoadNamedField* HGraphBuilder::AddLoadMap(
HValue*
object,
2704 return Add<HLoadNamedField>(
object, dependency, HObjectAccess::ForMap());
2708 HLoadNamedField* HGraphBuilder::AddLoadElements(
HValue*
object,
2710 return Add<HLoadNamedField>(
2711 object, dependency, HObjectAccess::ForElementsPointer());
2715 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(
2718 return Add<HLoadNamedField>(
2719 array, dependency, HObjectAccess::ForFixedArrayLength());
2723 HLoadNamedField* HGraphBuilder::AddLoadArrayLength(
HValue* array,
2726 return Add<HLoadNamedField>(
2727 array, dependency, HObjectAccess::ForArrayLength(kind));
2732 HValue* half_old_capacity = AddUncasted<HShr>(old_capacity,
2733 graph_->GetConstant1());
2735 HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity);
2736 new_capacity->
ClearFlag(HValue::kCanOverflow);
2738 HValue* min_growth = Add<HConstant>(16);
2740 new_capacity = AddUncasted<HAdd>(new_capacity, min_growth);
2741 new_capacity->
ClearFlag(HValue::kCanOverflow);
2743 return new_capacity;
2753 Add<HBoundsCheck>(new_capacity, Add<HConstant>(
2754 (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >>
2757 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
2758 new_kind, new_capacity);
2760 BuildCopyElements(elements, kind, new_elements,
2761 new_kind, length, new_capacity);
2763 Add<HStoreNamedField>(
object, HObjectAccess::ForElementsPointer(),
2766 return new_elements;
2770 void HGraphBuilder::BuildFillElementsWithValue(
HValue* elements,
2776 to = AddLoadFixedArrayLength(elements);
2781 kElementLoopUnrollThreshold);
2782 int initial_capacity = -1;
2785 int constant_to =
to->GetInteger32Constant();
2787 if (constant_from == 0 && constant_to <= kElementLoopUnrollThreshold) {
2788 initial_capacity = constant_to;
2798 if (initial_capacity >= 0) {
2799 for (
int i = 0;
i < initial_capacity;
i++) {
2801 Add<HStoreKeyed>(elements, key, value, elements_kind);
2808 LoopBuilder builder(
this, context(), LoopBuilder::kPostDecrement);
2810 HValue* key = builder.BeginBody(
to, from, Token::GT);
2812 HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1());
2813 adjusted_key->
ClearFlag(HValue::kCanOverflow);
2815 Add<HStoreKeyed>(elements, adjusted_key, value, elements_kind);
2822 void HGraphBuilder::BuildFillElementsWithHole(
HValue* elements,
2828 Factory* factory = isolate()->factory();
2830 double nan_double = FixedDoubleArray::hole_nan_as_double();
2832 ? Add<HConstant>(factory->the_hole_value())
2833 : Add<HConstant>(nan_double);
2835 BuildFillElementsWithValue(elements, elements_kind, from,
to, hole);
2839 void HGraphBuilder::BuildCopyElements(
HValue* from_elements,
2845 int constant_capacity = -1;
2846 if (capacity !=
NULL &&
2847 capacity->IsConstant() &&
2848 HConstant::cast(capacity)->HasInteger32Value()) {
2849 int constant_candidate = HConstant::cast(capacity)->Integer32Value();
2850 if (constant_candidate <= kElementLoopUnrollThreshold) {
2851 constant_capacity = constant_candidate;
2855 bool pre_fill_with_holes =
2858 if (pre_fill_with_holes) {
2862 BuildFillElementsWithHole(to_elements, to_elements_kind,
2863 graph()->GetConstant0(),
NULL);
2866 if (constant_capacity != -1) {
2868 for (
int i = 0;
i < constant_capacity;
i++) {
2869 HValue* key_constant = Add<HConstant>(
i);
2870 HInstruction* value = Add<HLoadKeyed>(from_elements, key_constant,
2872 from_elements_kind);
2873 Add<HStoreKeyed>(to_elements, key_constant, value, to_elements_kind);
2876 if (!pre_fill_with_holes &&
2877 (capacity ==
NULL || !length->
Equals(capacity))) {
2878 BuildFillElementsWithHole(to_elements, to_elements_kind,
2882 if (capacity ==
NULL) {
2883 capacity = AddLoadFixedArrayLength(to_elements);
2886 LoopBuilder builder(
this, context(), LoopBuilder::kPostDecrement);
2888 HValue* key = builder.BeginBody(length, graph()->GetConstant0(),
2891 key = AddUncasted<HSub>(key, graph()->GetConstant1());
2894 HValue* element = Add<HLoadKeyed>(from_elements, key,
2904 from_elements_kind != to_elements_kind) {
2905 IfBuilder if_hole(
this);
2906 if_hole.If<HCompareHoleAndBranch>(element);
2909 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double())
2910 : graph()->GetConstantHole();
2911 Add<HStoreKeyed>(to_elements, key, hole_constant, kind);
2913 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
2914 store->SetFlag(HValue::kAllowUndefinedAsNaN);
2917 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
2918 store->SetFlag(HValue::kAllowUndefinedAsNaN);
2924 Counters* counters = isolate()->counters();
2925 AddIncrementCounter(counters->inlined_copied_elements());
2933 HAllocate* array = AllocateJSArrayObject(
mode);
2936 HValue* elements = AddLoadElements(boilerplate);
2937 HValue* length = AddLoadArrayLength(boilerplate, kind);
2939 BuildJSArrayHeader(array,
2953 HAllocate* array = AllocateJSArrayObject(
mode);
2957 BuildJSArrayHeader(array,
2963 graph()->GetConstant0());
2972 HValue* boilerplate_elements = AddLoadElements(boilerplate);
2973 HValue* capacity = AddLoadFixedArrayLength(boilerplate_elements);
2977 HValue* elements_size = BuildCalculateElementsSize(kind, capacity);
2983 HValue* result = BuildCloneShallowArrayEmpty(
2984 boilerplate, allocation_site,
mode);
2986 HAllocate* elements = BuildAllocateElements(kind, elements_size);
2992 HConstant* size_upper_bound = EstablishElementsAllocationSize(
2993 kind, JSObject::kInitialMaxFastElementArray);
2994 elements->set_size_upper_bound(size_upper_bound);
2996 Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), elements);
3002 boilerplate_elements = AddLoadElements(boilerplate);
3003 boilerplate_elements->
SetFlag(HValue::kCantBeReplaced);
3007 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(
i);
3008 Add<HStoreNamedField>(elements, access,
3009 Add<HLoadNamedField>(boilerplate_elements,
3014 HValue* length = AddLoadArrayLength(boilerplate, kind);
3015 Add<HStoreNamedField>(result, HObjectAccess::ForArrayLength(kind), length);
3017 BuildCopyElements(boilerplate_elements, kind, elements,
3018 kind, length,
NULL);
3023 void HGraphBuilder::BuildCompareNil(
3026 HIfContinuation* continuation) {
3027 IfBuilder if_nil(
this);
3028 bool some_case_handled =
false;
3029 bool some_case_missing =
false;
3032 if (some_case_handled) if_nil.Or();
3034 some_case_handled =
true;
3036 some_case_missing =
true;
3040 if (some_case_handled) if_nil.Or();
3042 graph()->GetConstantUndefined());
3043 some_case_handled =
true;
3045 some_case_missing =
true;
3048 if (type->
Maybe(Type::Undetectable())) {
3049 if (some_case_handled) if_nil.Or();
3050 if_nil.If<HIsUndetectableAndBranch>(value);
3051 some_case_handled =
true;
3053 some_case_missing =
true;
3056 if (some_case_missing) {
3060 BuildCheckHeapObject(value);
3065 Add<HCheckMaps>(value, type->
Classes().Current());
3067 if_nil.Deopt(
"Too many undetectable types");
3071 if_nil.CaptureContinuation(continuation);
3075 void HGraphBuilder::BuildCreateAllocationMemento(
3077 HValue* previous_object_size,
3078 HValue* allocation_site) {
3080 HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>(
3081 previous_object, previous_object_size, HType::HeapObject());
3082 AddStoreMapConstant(
3083 allocation_memento, isolate()->factory()->allocation_memento_map());
3084 Add<HStoreNamedField>(
3086 HObjectAccess::ForAllocationMementoSite(),
3088 if (FLAG_allocation_site_pretenuring) {
3089 HValue* memento_create_count = Add<HLoadNamedField>(
3091 HObjectAccess::ForAllocationSiteOffset(
3092 AllocationSite::kPretenureCreateCountOffset));
3093 memento_create_count = AddUncasted<HAdd>(
3094 memento_create_count, graph()->GetConstant1());
3097 memento_create_count->
ClearFlag(HValue::kCanOverflow);
3098 Add<HStoreNamedField>(
3099 allocation_site, HObjectAccess::ForAllocationSiteOffset(
3100 AllocationSite::kPretenureCreateCountOffset), memento_create_count);
3108 Add<HLoadNamedField>(closure,
static_cast<HValue*
>(
NULL),
3109 HObjectAccess::ForFunctionContextPointer());
3112 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
3113 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
3114 GlobalObject::kNativeContextOffset);
3115 return Add<HLoadNamedField>(
3116 global_object,
static_cast<HValue*
>(
NULL), access);
3122 HValue* global_object = Add<HLoadNamedField>(
3124 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
3125 return Add<HLoadNamedField>(
3127 HObjectAccess::ForObservableJSObjectOffset(
3128 GlobalObject::kNativeContextOffset));
3133 HInstruction* native_context = BuildGetNativeContext();
3135 Add<HConstant>(
static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
3136 return Add<HLoadKeyed>(
3141 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(
HGraphBuilder* builder,
3143 HValue* allocation_site_payload,
3144 HValue* constructor_function,
3148 allocation_site_payload_(allocation_site_payload),
3149 constructor_function_(constructor_function) {
3150 DCHECK(!allocation_site_payload->IsConstant() ||
3151 HConstant::cast(allocation_site_payload)->handle(
3152 builder_->isolate())->IsAllocationSite());
3159 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
3161 HValue* constructor_function) :
3165 allocation_site_payload_(
NULL),
3166 constructor_function_(constructor_function) {
3170 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
3171 if (!builder()->top_info()->IsStub()) {
3173 Handle<Map>
map(builder()->isolate()->get_initial_js_array_map(kind_),
3174 builder()->isolate());
3175 return builder()->Add<HConstant>(
map);
3181 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
3182 return builder()->Add<HLoadNamedField>(
3183 constructor_function_,
static_cast<HValue*
>(
NULL), access);
3188 HInstruction* native_context = constructor_function_ !=
NULL
3189 ? builder()->BuildGetNativeContext(constructor_function_)
3190 : builder()->BuildGetNativeContext();
3192 HInstruction* index = builder()->Add<HConstant>(
3195 HInstruction* map_array = builder()->Add<HLoadKeyed>(
3198 HInstruction* kind_index = builder()->Add<HConstant>(kind_);
3200 return builder()->Add<HLoadKeyed>(
3205 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
3207 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
3208 return builder()->Add<HLoadNamedField>(
3209 constructor_function_,
static_cast<HValue*
>(
NULL), access);
3213 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() {
3214 HConstant* capacity = builder()->Add<HConstant>(initial_capacity());
3215 return AllocateArray(capacity,
3217 builder()->graph()->GetConstant0());
3221 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3223 HConstant* capacity_upper_bound,
3224 HValue* length_field,
3225 FillMode fill_mode) {
3226 return AllocateArray(capacity,
3227 capacity_upper_bound->GetInteger32Constant(),
3233 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3235 int capacity_upper_bound,
3236 HValue* length_field,
3237 FillMode fill_mode) {
3238 HConstant* elememts_size_upper_bound = capacity->IsInteger32Constant()
3239 ? HConstant::cast(capacity)
3240 : builder()->EstablishElementsAllocationSize(kind_, capacity_upper_bound);
3242 HAllocate* array = AllocateArray(capacity, length_field, fill_mode);
3243 if (!elements_location_->has_size_upper_bound()) {
3244 elements_location_->set_size_upper_bound(elememts_size_upper_bound);
3250 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3252 HValue* length_field,
3253 FillMode fill_mode) {
3258 builder()->AddUncasted<HForceRepresentation>(capacity,
3261 builder()->AddUncasted<HForceRepresentation>(length_field,
3266 HValue* elements_size =
3267 builder()->BuildCalculateElementsSize(kind_, capacity);
3270 HAllocate* array_object = builder()->AllocateJSArrayObject(mode_);
3274 if (allocation_site_payload_ ==
NULL) {
3275 map = EmitInternalMapCode();
3277 map = EmitMapCode();
3280 builder()->BuildJSArrayHeader(array_object,
3285 allocation_site_payload_,
3289 elements_location_ = builder()->BuildAllocateElements(kind_, elements_size);
3291 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
3294 builder()->Add<HStoreNamedField>(
3295 array_object, HObjectAccess::ForElementsPointer(), elements_location_);
3297 if (fill_mode == FILL_WITH_HOLE) {
3298 builder()->BuildFillElementsWithHole(elements_location_, kind_,
3299 graph()->GetConstant0(), capacity);
3302 return array_object;
3307 HValue* global_object = Add<HLoadNamedField>(
3310 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
3312 HValue* builtins = Add<HLoadNamedField>(
3313 global_object,
static_cast<HValue*
>(
NULL), access);
3314 HObjectAccess function_access = HObjectAccess::ForObservableJSObjectOffset(
3316 return Add<HLoadNamedField>(
3317 builtins,
static_cast<HValue*
>(
NULL), function_access);
3323 function_state_(
NULL),
3328 globals_(10, info->zone()),
3334 InitializeAstVisitor(info->
zone());
3335 if (FLAG_hydrogen_track_positions) {
3342 HBasicBlock* second,
3344 if (first ==
NULL) {
3346 }
else if (second ==
NULL) {
3349 HBasicBlock* join_block =
graph()->CreateBasicBlock();
3350 Goto(first, join_block);
3351 Goto(second, join_block);
3352 join_block->SetJoinId(join_id);
3359 HBasicBlock* exit_block,
3360 HBasicBlock* continue_block) {
3361 if (continue_block !=
NULL) {
3362 if (exit_block !=
NULL)
Goto(exit_block, continue_block);
3363 continue_block->SetJoinId(statement->
ContinueId());
3364 return continue_block;
3371 HBasicBlock* loop_entry,
3372 HBasicBlock* body_exit,
3373 HBasicBlock* loop_successor,
3374 HBasicBlock* break_block) {
3375 if (body_exit !=
NULL)
Goto(body_exit, loop_entry);
3376 loop_entry->PostProcessLoopHeader(statement);
3377 if (break_block !=
NULL) {
3378 if (loop_successor !=
NULL)
Goto(loop_successor, break_block);
3379 break_block->SetJoinId(statement->
ExitId());
3382 return loop_successor;
3406 Finish(instruction, position);
3412 return os <<
"B" << b.block_id();
3416 HGraph::HGraph(CompilationInfo* info)
3417 : isolate_(info->isolate()),
3420 blocks_(8, info->zone()),
3421 values_(16, info->zone()),
3423 uint32_instructions_(
NULL),
3426 zone_(info->zone()),
3427 is_recursive_(
false),
3428 use_optimistic_licm_(
false),
3429 depends_on_empty_array_proto_elements_(
false),
3430 type_change_checksum_(0),
3431 maximum_environment_size_(0),
3432 no_side_effects_scope_count_(0),
3433 disallow_adding_new_values_(
false),
3435 inlined_functions_(5, info->zone()) {
3436 if (info->IsStub()) {
3437 CallInterfaceDescriptor descriptor =
3438 info->code_stub()->GetCallInterfaceDescriptor();
3439 start_environment_ =
new (zone_)
3440 HEnvironment(zone_, descriptor.GetEnvironmentParameterCount());
3443 start_environment_ =
3444 new(zone_) HEnvironment(
NULL, info->scope(), info->closure(), zone_);
3447 entry_block_ = CreateBasicBlock();
3448 entry_block_->SetInitialEnvironment(start_environment_);
3452 HBasicBlock* HGraph::CreateBasicBlock() {
3453 HBasicBlock* result =
new(zone()) HBasicBlock(
this);
3454 blocks_.Add(result, zone());
3459 void HGraph::FinalizeUniqueness() {
3461 DCHECK(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
3462 for (
int i = 0;
i < blocks()->length(); ++
i) {
3463 for (HInstructionIterator it(blocks()->at(
i)); !it.Done(); it.Advance()) {
3464 it.Current()->FinalizeUniqueness();
3470 int HGraph::TraceInlinedFunction(
3471 Handle<SharedFunctionInfo> shared,
3472 HSourcePosition position) {
3473 if (!FLAG_hydrogen_track_positions) {
3478 for (;
id < inlined_functions_.length();
id++) {
3479 if (inlined_functions_[
id].shared().is_identical_to(shared)) {
3484 if (
id == inlined_functions_.length()) {
3485 inlined_functions_.Add(InlinedFunctionInfo(shared), zone());
3487 if (!shared->script()->IsUndefined()) {
3488 Handle<Script> script(Script::cast(shared->script()));
3489 if (!script->source()->IsUndefined()) {
3490 CodeTracer::Scope tracing_scopex(isolate()->GetCodeTracer());
3491 OFStream os(tracing_scopex.file());
3492 os <<
"--- FUNCTION SOURCE (" << shared->DebugName()->ToCString().get()
3493 <<
") id{" << info()->optimization_id() <<
"," <<
id <<
"} ---\n";
3495 ConsStringIteratorOp op;
3496 StringCharacterStream stream(String::cast(script->source()),
3498 shared->start_position());
3502 shared->end_position() - shared->start_position() + 1;
3503 for (
int i = 0;
i < source_len;
i++) {
3504 if (stream.HasMore()) {
3505 os << AsReversiblyEscapedUC16(stream.GetNext());
3510 os <<
"\n--- END ---\n";
3515 int inline_id = next_inline_id_++;
3517 if (inline_id != 0) {
3518 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
3519 OFStream os(tracing_scope.file());
3520 os <<
"INLINE (" << shared->DebugName()->ToCString().get() <<
") id{"
3521 << info()->optimization_id() <<
"," <<
id <<
"} AS " << inline_id
3522 <<
" AT " << position <<
endl;
3529 int HGraph::SourcePositionToScriptPosition(HSourcePosition pos) {
3530 if (!FLAG_hydrogen_track_positions || pos.IsUnknown()) {
3534 return inlined_functions_[pos.inlining_id()].start_position() +
3591 HLoopInformation*
loop() {
return loop_; }
3595 HBasicBlock* block) {
3603 PerformNonBacktrackingStep(zone, order);
3607 return Backtrack(zone, order);
3613 : father_(father), child_(
NULL), successor_iterator(
NULL) { }
3621 SUCCESSORS_OF_LOOP_MEMBER
3627 HBasicBlock* loop_header) {
3628 if (block ==
NULL || block->IsOrdered() ||
3629 block->parent_loop_header() != loop_header) {
3633 loop_header_ =
NULL;
3638 block->MarkAsOrdered();
3640 if (block->IsLoopHeader()) {
3641 kind_ = SUCCESSORS_OF_LOOP_HEADER;
3642 loop_header_ = block;
3643 InitializeSuccessors();
3648 DCHECK(block->IsFinished());
3650 loop_header_ = loop_header;
3651 InitializeSuccessors();
3659 HLoopInformation* loop,
3660 HBasicBlock* loop_header) {
3661 kind_ = LOOP_MEMBERS;
3664 loop_header_ = loop_header;
3665 InitializeLoopMembers();
3671 HLoopInformation* loop,
3672 HBasicBlock* loop_header) {
3673 kind_ = SUCCESSORS_OF_LOOP_MEMBER;
3676 loop_header_ = loop_header;
3677 InitializeSuccessors();
3683 if (child_ ==
NULL) {
3690 DCHECK(block_->end()->FirstSuccessor() ==
NULL ||
3691 order->
Contains(block_->end()->FirstSuccessor()) ||
3692 block_->end()->FirstSuccessor()->IsLoopHeader());
3693 DCHECK(block_->end()->SecondSuccessor() ==
NULL ||
3694 order->
Contains(block_->end()->SecondSuccessor()) ||
3695 block_->end()->SecondSuccessor()->IsLoopHeader());
3696 order->
Add(block_, zone);
3704 case SUCCESSORS_OF_LOOP_HEADER:
3705 ClosePostorder(order, zone);
3709 case SUCCESSORS_OF_LOOP_MEMBER:
3710 if (block()->IsLoopHeader() && block() != loop_->loop_header()) {
3713 return SetupLoopMembers(zone, block(),
3714 block()->loop_information(), loop_header_);
3729 while (parent !=
NULL) {
3735 parent = parent->
Pop(zone, order);
3744 HBasicBlock* next_block;
3747 next_block = AdvanceSuccessors();
3748 if (next_block !=
NULL) {
3753 case SUCCESSORS_OF_LOOP_HEADER:
3754 next_block = AdvanceSuccessors();
3755 if (next_block !=
NULL) {
3761 next_block = AdvanceLoopMembers();
3762 if (next_block !=
NULL) {
3765 loop_, loop_header_);
3768 case SUCCESSORS_OF_LOOP_MEMBER:
3769 next_block = AdvanceSuccessors();
3770 if (next_block !=
NULL) {
3785 successor_iterator = HSuccessorIterator(block_->end());
3789 if (!successor_iterator.Done()) {
3790 HBasicBlock* result = successor_iterator.Current();
3791 successor_iterator.Advance();
3800 loop_length = loop_->blocks()->length();
3804 if (loop_index < loop_length) {
3805 HBasicBlock* result = loop_->blocks()->at(loop_index);
3825 void HGraph::OrderBlocks() {
3830 for (
int i = 0;
i < blocks_.length(); ++
i) {
3831 DCHECK(!blocks_[
i]->IsOrdered());
3835 PostorderProcessor* postorder =
3836 PostorderProcessor::CreateEntryProcessor(zone(), blocks_[0]);
3839 postorder = postorder->PerformStep(zone(), &blocks_);
3844 for (
int i = 0;
i < blocks_.length(); ++
i) {
3845 DCHECK(blocks_[
i]->IsOrdered());
3850 for (
int i = 0, j = blocks_.length(); --j >=
i; ++
i) {
3851 HBasicBlock* bi = blocks_[
i];
3852 HBasicBlock* bj = blocks_[j];
3853 bi->set_block_id(j);
3854 bj->set_block_id(
i);
3861 void HGraph::AssignDominators() {
3862 HPhase phase(
"H_Assign dominators",
this);
3863 for (
int i = 0;
i < blocks_.length(); ++
i) {
3864 HBasicBlock* block = blocks_[
i];
3865 if (block->IsLoopHeader()) {
3868 block->AssignCommonDominator(block->predecessors()->first());
3869 block->AssignLoopSuccessorDominators();
3871 for (
int j = blocks_[
i]->predecessors()->length() - 1; j >= 0; --j) {
3872 blocks_[
i]->AssignCommonDominator(blocks_[
i]->predecessors()->at(j));
3879 bool HGraph::CheckArgumentsPhiUses() {
3880 int block_count = blocks_.length();
3881 for (
int i = 0;
i < block_count; ++
i) {
3882 for (
int j = 0; j < blocks_[
i]->phis()->length(); ++j) {
3883 HPhi* phi = blocks_[
i]->phis()->at(j);
3885 if (phi->CheckFlag(HValue::kIsArguments))
return false;
3892 bool HGraph::CheckConstPhiUses() {
3893 int block_count = blocks_.length();
3894 for (
int i = 0;
i < block_count; ++
i) {
3895 for (
int j = 0; j < blocks_[
i]->phis()->length(); ++j) {
3896 HPhi* phi = blocks_[
i]->phis()->at(j);
3898 for (
int k = 0; k < phi->OperandCount(); k++) {
3899 if (phi->OperandAt(k) == GetConstantHole())
return false;
3907 void HGraph::CollectPhis() {
3908 int block_count = blocks_.length();
3909 phi_list_ =
new(zone()) ZoneList<HPhi*>(block_count, zone());
3910 for (
int i = 0;
i < block_count; ++
i) {
3911 for (
int j = 0; j < blocks_[
i]->phis()->length(); ++j) {
3912 HPhi* phi = blocks_[
i]->phis()->at(j);
3913 phi_list_->Add(phi, zone());
3921 FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
3922 CompilationInfo* info,
3926 compilation_info_(info),
3927 call_context_(
NULL),
3928 inlining_kind_(inlining_kind),
3929 function_return_(
NULL),
3930 test_context_(
NULL),
3932 arguments_object_(
NULL),
3933 arguments_elements_(
NULL),
3934 inlining_id_(inlining_id),
3935 outer_source_position_(HSourcePosition::Unknown()),
3936 outer_(owner->function_state()) {
3937 if (outer_ !=
NULL) {
3939 if (owner->ast_context()->IsTest()) {
3940 HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
3941 HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
3942 if_true->MarkAsInlineReturnTarget(owner->current_block());
3943 if_false->MarkAsInlineReturnTarget(owner->current_block());
3944 TestContext* outer_test_context = TestContext::cast(owner->ast_context());
3945 Expression* cond = outer_test_context->condition();
3948 test_context_ =
new TestContext(owner, cond, if_true, if_false);
3950 function_return_ = owner->graph()->CreateBasicBlock();
3951 function_return()->MarkAsInlineReturnTarget(owner->current_block());
3954 call_context_ = owner->ast_context();
3958 owner->set_function_state(
this);
3960 if (FLAG_hydrogen_track_positions) {
3961 outer_source_position_ = owner->source_position();
3962 owner->EnterInlinedSource(
3963 info->shared_info()->start_position(),
3965 owner->SetSourcePosition(info->shared_info()->start_position());
3970 FunctionState::~FunctionState() {
3971 delete test_context_;
3972 owner_->set_function_state(outer_);
3974 if (FLAG_hydrogen_track_positions) {
3975 owner_->set_source_position(outer_source_position_);
3976 owner_->EnterInlinedSource(
3977 outer_->compilation_info()->shared_info()->start_position(),
3978 outer_->inlining_id());
3988 outer_(owner->ast_context()),
3989 for_typeof_(
false) {
4003 EffectContext::~EffectContext() {
4004 DCHECK(owner()->HasStackOverflow() ||
4005 owner()->current_block() ==
NULL ||
4006 (owner()->environment()->length() == original_length_ &&
4007 owner()->environment()->frame_type() ==
JS_FUNCTION));
4011 ValueContext::~ValueContext() {
4012 DCHECK(owner()->HasStackOverflow() ||
4013 owner()->current_block() ==
NULL ||
4014 (owner()->environment()->length() == original_length_ + 1 &&
4015 owner()->environment()->frame_type() ==
JS_FUNCTION));
4019 void EffectContext::ReturnValue(HValue* value) {
4024 void ValueContext::ReturnValue(HValue* value) {
4028 owner()->Bailout(kBadValueContextForArgumentsValue);
4030 owner()->Push(value);
4034 void TestContext::ReturnValue(HValue* value) {
4039 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
4040 DCHECK(!instr->IsControlInstruction());
4041 owner()->AddInstruction(instr);
4042 if (instr->HasObservableSideEffects()) {
4048 void EffectContext::ReturnControl(HControlInstruction* instr,
4050 DCHECK(!instr->HasObservableSideEffects());
4051 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
4052 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
4053 instr->SetSuccessorAt(0, empty_true);
4054 instr->SetSuccessorAt(1, empty_false);
4055 owner()->FinishCurrentBlock(instr);
4056 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
4057 owner()->set_current_block(join);
4061 void EffectContext::ReturnContinuation(HIfContinuation* continuation,
4063 HBasicBlock* true_branch =
NULL;
4064 HBasicBlock* false_branch =
NULL;
4065 continuation->Continue(&true_branch, &false_branch);
4066 if (!continuation->IsTrueReachable()) {
4067 owner()->set_current_block(false_branch);
4068 }
else if (!continuation->IsFalseReachable()) {
4069 owner()->set_current_block(true_branch);
4071 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id);
4072 owner()->set_current_block(join);
4077 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
4078 DCHECK(!instr->IsControlInstruction());
4080 return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
4082 owner()->AddInstruction(instr);
4083 owner()->Push(instr);
4084 if (instr->HasObservableSideEffects()) {
4090 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
4091 DCHECK(!instr->HasObservableSideEffects());
4093 return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
4095 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
4096 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
4097 instr->SetSuccessorAt(0, materialize_true);
4098 instr->SetSuccessorAt(1, materialize_false);
4099 owner()->FinishCurrentBlock(instr);
4100 owner()->set_current_block(materialize_true);
4101 owner()->Push(owner()->graph()->GetConstantTrue());
4102 owner()->set_current_block(materialize_false);
4103 owner()->Push(owner()->graph()->GetConstantFalse());
4105 owner()->CreateJoin(materialize_true, materialize_false, ast_id);
4106 owner()->set_current_block(join);
4110 void ValueContext::ReturnContinuation(HIfContinuation* continuation,
4112 HBasicBlock* materialize_true =
NULL;
4113 HBasicBlock* materialize_false =
NULL;
4114 continuation->Continue(&materialize_true, &materialize_false);
4115 if (continuation->IsTrueReachable()) {
4116 owner()->set_current_block(materialize_true);
4117 owner()->Push(owner()->graph()->GetConstantTrue());
4118 owner()->set_current_block(materialize_true);
4120 if (continuation->IsFalseReachable()) {
4121 owner()->set_current_block(materialize_false);
4122 owner()->Push(owner()->graph()->GetConstantFalse());
4123 owner()->set_current_block(materialize_false);
4125 if (continuation->TrueAndFalseReachable()) {
4127 owner()->CreateJoin(materialize_true, materialize_false, ast_id);
4128 owner()->set_current_block(join);
4133 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
4134 DCHECK(!instr->IsControlInstruction());
4135 HOptimizedGraphBuilder* builder = owner();
4136 builder->AddInstruction(instr);
4139 if (instr->HasObservableSideEffects()) {
4140 builder->Push(instr);
4148 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
4149 DCHECK(!instr->HasObservableSideEffects());
4150 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
4151 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
4152 instr->SetSuccessorAt(0, empty_true);
4153 instr->SetSuccessorAt(1, empty_false);
4154 owner()->FinishCurrentBlock(instr);
4155 owner()->Goto(empty_true, if_true(), owner()->function_state());
4156 owner()->Goto(empty_false, if_false(), owner()->function_state());
4157 owner()->set_current_block(
NULL);
4161 void TestContext::ReturnContinuation(HIfContinuation* continuation,
4163 HBasicBlock* true_branch =
NULL;
4164 HBasicBlock* false_branch =
NULL;
4165 continuation->Continue(&true_branch, &false_branch);
4166 if (continuation->IsTrueReachable()) {
4167 owner()->Goto(true_branch, if_true(), owner()->function_state());
4169 if (continuation->IsFalseReachable()) {
4170 owner()->Goto(false_branch, if_false(), owner()->function_state());
4172 owner()->set_current_block(
NULL);
4176 void TestContext::BuildBranch(HValue* value) {
4181 HOptimizedGraphBuilder* builder = owner();
4183 builder->Bailout(kArgumentsObjectValueInATestContext);
4185 ToBooleanStub::Types expected(condition()->to_boolean_types());
4186 ReturnControl(owner()->New<HBranch>(value, expected),
BailoutId::None());
4191 #define CHECK_BAILOUT(call) \
4194 if (HasStackOverflow()) return; \
4198 #define CHECK_ALIVE(call) \
4201 if (HasStackOverflow() || current_block() == NULL) return; \
4205 #define CHECK_ALIVE_OR_RETURN(call, value) \
4208 if (HasStackOverflow() || current_block() == NULL) return value; \
4219 EffectContext for_effect(
this);
4226 ValueContext for_value(
this,
flag);
4233 for_value.set_for_typeof(
true);
4239 HBasicBlock* true_block,
4240 HBasicBlock* false_block) {
4241 TestContext for_test(
this, expr, true_block, false_block);
4248 for (
int i = 0;
i < exprs->length(); ++
i) {
4256 Bailout(kFunctionIsAGenerator);
4261 Bailout(kFunctionWithIllegalRedeclaration);
4285 HEnvironment* initial_env =
environment()->CopyWithoutHistory();
4299 Add<HStackCheck>(HStackCheck::kFunctionEntry);
4302 if (HasStackOverflow())
return false;
4305 Add<HReturn>(
graph()->GetConstantUndefined());
4314 DCHECK(unoptimized_code->kind() == Code::FUNCTION);
4316 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
4317 int checksum = type_info->own_type_change_checksum();
4318 int composite_checksum =
graph()->update_type_change_checksum(checksum);
4319 graph()->set_use_optimistic_licm(
4320 !type_info->matches_inlined_type_change_checksum(composite_checksum));
4321 type_info->set_inlined_type_change_checksum(composite_checksum);
4345 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
4346 Run<HEnvironmentLivenessAnalysisPhase>();
4349 if (!CheckConstPhiUses()) {
4350 *bailout_reason = kUnsupportedPhiUseOfConstVariable;
4353 Run<HRedundantPhiEliminationPhase>();
4354 if (!CheckArgumentsPhiUses()) {
4355 *bailout_reason = kUnsupportedPhiUseOfArguments;
4361 Run<HMarkUnreachableBlocksPhase>();
4363 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
4364 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
4366 if (FLAG_load_elimination) Run<HLoadEliminationPhase>();
4370 if (has_osr()) osr()->FinishOsrValues();
4372 Run<HInferRepresentationPhase>();
4377 Run<HMergeRemovableSimulatesPhase>();
4379 Run<HMarkDeoptimizeOnUndefinedPhase>();
4380 Run<HRepresentationChangesPhase>();
4382 Run<HInferTypesPhase>();
4387 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>();
4389 if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
4391 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
4393 if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
4395 if (FLAG_store_elimination) Run<HStoreEliminationPhase>();
4397 Run<HRangeAnalysisPhase>();
4399 Run<HComputeChangeUndefinedToNaN>();
4402 Run<HStackCheckEliminationPhase>();
4404 if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>();
4405 if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>();
4406 if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
4407 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
4409 RestoreActualValues();
4413 Run<HMarkUnreachableBlocksPhase>();
4419 void HGraph::RestoreActualValues() {
4420 HPhase phase(
"H_Restore actual values",
this);
4422 for (
int block_index = 0; block_index < blocks()->length(); block_index++) {
4423 HBasicBlock* block = blocks()->at(block_index);
4426 for (
int i = 0;
i < block->phis()->length();
i++) {
4427 HPhi* phi = block->phis()->at(
i);
4428 DCHECK(phi->ActualValue() == phi);
4432 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
4433 HInstruction* instruction = it.Current();
4434 if (instruction->ActualValue() == instruction)
continue;
4439 instruction->DeleteAndReplaceWith(instruction->ActualValue());
4441 DCHECK(instruction->IsInformativeDefinition());
4442 if (instruction->IsPurelyInformativeDefinition()) {
4443 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand());
4445 instruction->ReplaceAllUsesWith(instruction->ActualValue());
4455 for (
int i = 0;
i < count; ++
i) {
4459 HPushArguments* push_args = New<HPushArguments>();
4460 while (!arguments.is_empty()) {
4461 push_args->AddInput(arguments.RemoveLast());
4467 template <
class Instruction>
4482 HArgumentsObject* arguments_object =
4483 New<HArgumentsObject>(
environment()->parameter_count());
4486 arguments_object->AddArgument(parameter,
zone());
4490 graph()->SetArgumentsObject(arguments_object);
4492 HConstant* undefined_constant =
graph()->GetConstantUndefined();
4504 return Bailout(kContextAllocatedArguments);
4508 graph()->GetArgumentsObject());
4514 return IC::MapToType<Type>(
map,
zone());
4519 for (
int i = 0;
i < statements->length();
i++) {
4522 if (stmt->
IsJump())
break;
4527 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
4528 DCHECK(!HasStackOverflow());
4534 BreakAndContinueInfo break_info(stmt, outer_scope);
4536 { BreakAndContinueScope push(&break_info,
this);
4544 function =
new(
zone()) HLoadContextSlot(
4547 function = New<HThisFunction>();
4551 HInstruction* inner_context = Add<HAllocateBlockContext>(
4553 HInstruction* instr = Add<HStoreFrameContext>(inner_context);
4554 if (instr->HasObservableSideEffects()) {
4567 HValue* outer_context = Add<HLoadNamedField>(
4568 inner_context,
static_cast<HValue*
>(
NULL),
4571 HInstruction* instr = Add<HStoreFrameContext>(outer_context);
4572 if (instr->HasObservableSideEffects()) {
4577 HBasicBlock* break_block = break_info.break_block();
4578 if (break_block !=
NULL) {
4580 break_block->SetJoinId(stmt->ExitId());
4586 void HOptimizedGraphBuilder::VisitExpressionStatement(
4587 ExpressionStatement* stmt) {
4588 DCHECK(!HasStackOverflow());
4595 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
4596 DCHECK(!HasStackOverflow());
4602 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
4603 DCHECK(!HasStackOverflow());
4606 if (stmt->condition()->ToBooleanIsTrue()) {
4607 Add<HSimulate>(stmt->ThenId());
4608 Visit(stmt->then_statement());
4609 }
else if (stmt->condition()->ToBooleanIsFalse()) {
4610 Add<HSimulate>(stmt->ElseId());
4611 Visit(stmt->else_statement());
4613 HBasicBlock* cond_true =
graph()->CreateBasicBlock();
4614 HBasicBlock* cond_false =
graph()->CreateBasicBlock();
4617 if (cond_true->HasPredecessor()) {
4618 cond_true->SetJoinId(stmt->ThenId());
4626 if (cond_false->HasPredecessor()) {
4627 cond_false->SetJoinId(stmt->ElseId());
4635 HBasicBlock* join =
CreateJoin(cond_true, cond_false, stmt->IfId());
4641 HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
4642 BreakableStatement* stmt,
4647 BreakAndContinueScope* current =
this;
4648 while (current !=
NULL && current->info()->target() != stmt) {
4649 *drop_extra += current->info()->drop_extra();
4650 current = current->next();
4653 *scope = current->info()->scope();
4655 if (type ==
BREAK) {
4656 *drop_extra += current->info()->drop_extra();
4659 HBasicBlock* block =
NULL;
4662 block = current->info()->break_block();
4663 if (block ==
NULL) {
4664 block = current->owner()->graph()->CreateBasicBlock();
4665 current->info()->set_break_block(block);
4670 block = current->info()->continue_block();
4671 if (block ==
NULL) {
4672 block = current->owner()->graph()->CreateBasicBlock();
4673 current->info()->set_continue_block(block);
4682 void HOptimizedGraphBuilder::VisitContinueStatement(
4683 ContinueStatement* stmt) {
4684 DCHECK(!HasStackOverflow());
4687 Scope* outer_scope =
NULL;
4688 Scope* inner_scope =
scope();
4691 stmt->target(), BreakAndContinueScope::CONTINUE,
4692 &outer_scope, &drop_extra);
4695 int context_pop_count = inner_scope->ContextChainLength(outer_scope);
4696 if (context_pop_count > 0) {
4697 while (context_pop_count-- > 0) {
4698 HInstruction* context_instruction = Add<HLoadNamedField>(
4701 context = context_instruction;
4703 HInstruction* instr = Add<HStoreFrameContext>(
context);
4704 if (instr->HasObservableSideEffects()) {
4710 Goto(continue_block);
4715 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
4716 DCHECK(!HasStackOverflow());
4719 Scope* outer_scope =
NULL;
4720 Scope* inner_scope =
scope();
4724 &outer_scope, &drop_extra);
4727 int context_pop_count = inner_scope->ContextChainLength(outer_scope);
4728 if (context_pop_count > 0) {
4729 while (context_pop_count-- > 0) {
4730 HInstruction* context_instruction = Add<HLoadNamedField>(
4733 context = context_instruction;
4735 HInstruction* instr = Add<HStoreFrameContext>(
context);
4736 if (instr->HasObservableSideEffects()) {
4746 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
4747 DCHECK(!HasStackOverflow());
4756 Add<HReturn>(result);
4762 TestContext* test = TestContext::cast(
context);
4764 Goto(test->if_true(), state);
4765 }
else if (
context->IsEffect()) {
4771 HValue* return_value =
Pop();
4772 HValue* receiver =
environment()->arguments_environment()->Lookup(0);
4773 HHasInstanceTypeAndBranch* typecheck =
4774 New<HHasInstanceTypeAndBranch>(return_value,
4777 HBasicBlock* if_spec_object =
graph()->CreateBasicBlock();
4778 HBasicBlock* not_spec_object =
graph()->CreateBasicBlock();
4779 typecheck->SetSuccessorAt(0, if_spec_object);
4780 typecheck->SetSuccessorAt(1, not_spec_object);
4790 HValue* rhs =
environment()->arguments_environment()->Lookup(1);
4792 }
else if (
context->IsEffect()) {
4796 HValue* rhs =
environment()->arguments_environment()->Lookup(1);
4803 TestContext* test = TestContext::cast(
context);
4804 VisitForControl(stmt->expression(), test->if_true(), test->if_false());
4805 }
else if (
context->IsEffect()) {
4823 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
4824 DCHECK(!HasStackOverflow());
4827 return Bailout(kWithStatement);
4831 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
4832 DCHECK(!HasStackOverflow());
4836 ZoneList<CaseClause*>* clauses = stmt->cases();
4837 int clause_count = clauses->length();
4838 ZoneList<HBasicBlock*> body_blocks(clause_count,
zone());
4841 Add<HSimulate>(stmt->EntryId());
4842 HValue* tag_value =
Top();
4843 Type* tag_type = stmt->tag()->bounds().lower;
4847 for (
int i = 0;
i < clause_count; ++
i) {
4848 CaseClause* clause = clauses->at(
i);
4849 if (clause->is_default()) {
4851 if (default_id.IsNone()) default_id = clause->EntryId();
4857 HValue* label_value =
Pop();
4859 Type* label_type = clause->label()->bounds().lower;
4860 Type* combined_type = clause->compare_type();
4862 Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
4868 HBasicBlock* next_test_block =
graph()->CreateBasicBlock();
4869 HBasicBlock* body_block =
graph()->CreateBasicBlock();
4870 body_blocks.Add(body_block,
zone());
4871 compare->SetSuccessorAt(0, body_block);
4872 compare->SetSuccessorAt(1, next_test_block);
4888 HBasicBlock* fall_through_block =
NULL;
4890 BreakAndContinueInfo break_info(stmt,
scope());
4891 { BreakAndContinueScope push(&break_info,
this);
4892 for (
int i = 0;
i < clause_count; ++
i) {
4893 CaseClause* clause = clauses->at(
i);
4897 HBasicBlock* normal_block =
NULL;
4898 if (clause->is_default()) {
4899 if (last_block ==
NULL)
continue;
4900 normal_block = last_block;
4903 normal_block = body_blocks[
i];
4906 if (fall_through_block ==
NULL) {
4909 HBasicBlock* join =
CreateJoin(fall_through_block,
4922 HBasicBlock* break_block = break_info.break_block();
4923 if (break_block ==
NULL) {
4928 if (fall_through_block !=
NULL)
Goto(fall_through_block, break_block);
4929 if (last_block !=
NULL)
Goto(last_block, break_block);
4930 break_block->SetJoinId(stmt->ExitId());
4937 HBasicBlock* loop_entry) {
4939 HStackCheck* stack_check =
4940 HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch));
4941 DCHECK(loop_entry->IsLoopHeader());
4942 loop_entry->loop_information()->set_stack_check(stack_check);
4947 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
4948 DCHECK(!HasStackOverflow());
4954 BreakAndContinueInfo break_info(stmt,
scope());
4956 BreakAndContinueScope push(&break_info,
this);
4959 HBasicBlock* body_exit =
4961 HBasicBlock* loop_successor =
NULL;
4962 if (body_exit !=
NULL && !stmt->cond()->ToBooleanIsTrue()) {
4964 loop_successor =
graph()->CreateBasicBlock();
4965 if (stmt->cond()->ToBooleanIsFalse()) {
4966 loop_entry->loop_information()->stack_check()->Eliminate();
4967 Goto(loop_successor);
4972 body_exit =
graph()->CreateBasicBlock();
4975 if (body_exit !=
NULL && body_exit->HasPredecessor()) {
4976 body_exit->SetJoinId(stmt->BackEdgeId());
4980 if (loop_successor->HasPredecessor()) {
4981 loop_successor->SetJoinId(stmt->ExitId());
4983 loop_successor =
NULL;
4990 break_info.break_block());
4995 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
4996 DCHECK(!HasStackOverflow());
5003 HBasicBlock* loop_successor =
NULL;
5004 if (!stmt->cond()->ToBooleanIsTrue()) {
5005 HBasicBlock* body_entry =
graph()->CreateBasicBlock();
5006 loop_successor =
graph()->CreateBasicBlock();
5008 if (body_entry->HasPredecessor()) {
5009 body_entry->SetJoinId(stmt->BodyId());
5012 if (loop_successor->HasPredecessor()) {
5013 loop_successor->SetJoinId(stmt->ExitId());
5015 loop_successor =
NULL;
5019 BreakAndContinueInfo break_info(stmt,
scope());
5021 BreakAndContinueScope push(&break_info,
this);
5024 HBasicBlock* body_exit =
5030 break_info.break_block());
5035 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
5036 DCHECK(!HasStackOverflow());
5039 if (stmt->init() !=
NULL) {
5045 HBasicBlock* loop_successor =
NULL;
5046 if (stmt->cond() !=
NULL) {
5047 HBasicBlock* body_entry =
graph()->CreateBasicBlock();
5048 loop_successor =
graph()->CreateBasicBlock();
5050 if (body_entry->HasPredecessor()) {
5051 body_entry->SetJoinId(stmt->BodyId());
5054 if (loop_successor->HasPredecessor()) {
5055 loop_successor->SetJoinId(stmt->ExitId());
5057 loop_successor =
NULL;
5061 BreakAndContinueInfo break_info(stmt,
scope());
5063 BreakAndContinueScope push(&break_info,
this);
5066 HBasicBlock* body_exit =
5069 if (stmt->next() !=
NULL && body_exit !=
NULL) {
5079 break_info.break_block());
5084 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
5085 DCHECK(!HasStackOverflow());
5089 if (!FLAG_optimize_for_in) {
5090 return Bailout(kForInStatementOptimizationIsDisabled);
5093 if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) {
5094 return Bailout(kForInStatementIsNotFastCase);
5097 if (!stmt->each()->IsVariableProxy() ||
5098 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
5099 return Bailout(kForInStatementWithNonLocalEachVariable);
5102 Variable* each_var = stmt->each()->AsVariableProxy()->var();
5105 HValue* enumerable =
Top();
5107 HInstruction*
map = Add<HForInPrepareMap>(enumerable);
5108 Add<HSimulate>(stmt->PrepareId());
5110 HInstruction* array = Add<HForInCacheArray>(
5113 HInstruction* enum_length = Add<HMapEnumLength>(
map);
5115 HInstruction* start_index = Add<HConstant>(0);
5122 HInstruction* index_cache = Add<HForInCacheArray>(
5124 HForInCacheArray::cast(array)->set_index_cache(
5125 HForInCacheArray::cast(index_cache));
5129 HValue* index =
environment()->ExpressionStackAt(0);
5130 HValue* limit =
environment()->ExpressionStackAt(1);
5133 HCompareNumericAndBranch* compare_index =
5134 New<HCompareNumericAndBranch>(index, limit, Token::LT);
5135 compare_index->set_observed_input_representation(
5138 HBasicBlock* loop_body =
graph()->CreateBasicBlock();
5139 HBasicBlock* loop_successor =
graph()->CreateBasicBlock();
5141 compare_index->SetSuccessorAt(0, loop_body);
5142 compare_index->SetSuccessorAt(1, loop_successor);
5150 HValue* key = Add<HLoadKeyed>(
5158 Add<HCheckMapValue>(
environment()->ExpressionStackAt(4),
5161 Bind(each_var, key);
5163 BreakAndContinueInfo break_info(stmt,
scope(), 5);
5165 BreakAndContinueScope push(&break_info,
this);
5169 HBasicBlock* body_exit =
5172 if (body_exit !=
NULL) {
5175 HValue* current_index =
Pop();
5176 Push(AddUncasted<HAdd>(current_index,
graph()->GetConstant1()));
5184 break_info.break_block());
5190 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
5191 DCHECK(!HasStackOverflow());
5194 return Bailout(kForOfStatement);
5198 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
5199 DCHECK(!HasStackOverflow());
5202 return Bailout(kTryCatchStatement);
5206 void HOptimizedGraphBuilder::VisitTryFinallyStatement(
5207 TryFinallyStatement* stmt) {
5208 DCHECK(!HasStackOverflow());
5211 return Bailout(kTryFinallyStatement);
5215 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
5216 DCHECK(!HasStackOverflow());
5219 return Bailout(kDebuggerStatement);
5223 void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) {
5228 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
5229 DCHECK(!HasStackOverflow());
5232 Handle<SharedFunctionInfo> shared_info = expr->shared_info();
5233 if (shared_info.is_null()) {
5238 if (HasStackOverflow())
return;
5239 HFunctionLiteral* instr =
5240 New<HFunctionLiteral>(shared_info, expr->pretenure());
5245 void HOptimizedGraphBuilder::VisitClassLiteral(ClassLiteral* lit) {
5246 DCHECK(!HasStackOverflow());
5249 return Bailout(kClassLiteral);
5253 void HOptimizedGraphBuilder::VisitNativeFunctionLiteral(
5254 NativeFunctionLiteral* expr) {
5255 DCHECK(!HasStackOverflow());
5258 return Bailout(kNativeFunctionLiteral);
5262 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
5263 DCHECK(!HasStackOverflow());
5266 HBasicBlock* cond_true =
graph()->CreateBasicBlock();
5267 HBasicBlock* cond_false =
graph()->CreateBasicBlock();
5272 if (cond_true->HasPredecessor()) {
5273 cond_true->SetJoinId(expr->ThenId());
5281 if (cond_false->HasPredecessor()) {
5282 cond_false->SetJoinId(expr->ElseId());
5291 HBasicBlock* join =
CreateJoin(cond_true, cond_false, expr->id());
5307 switch (it->state()) {
5309 case LookupIterator::ACCESS_CHECK:
5310 case LookupIterator::INTERCEPTOR:
5311 case LookupIterator::NOT_FOUND:
5313 case LookupIterator::DATA:
5316 case LookupIterator::JSPROXY:
5317 case LookupIterator::TRANSITION:
5329 while (length-- > 0) {
5330 context = Add<HLoadNamedField>(
5338 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
5339 if (expr->is_this()) {
5343 DCHECK(!HasStackOverflow());
5346 Variable* variable = expr->var();
5347 switch (variable->location()) {
5351 return Bailout(kReferenceToGlobalLexicalVariable);
5355 Handle<Object> constant_value =
5357 if (!constant_value.is_null()) {
5358 HConstant* instr = New<HConstant>(constant_value);
5362 Handle<GlobalObject> global(
current_info()->global_object());
5363 LookupIterator it(global, variable->name(),
5364 LookupIterator::OWN_SKIP_INTERCEPTOR);
5368 Handle<PropertyCell> cell = it.GetPropertyCell();
5369 if (cell->type()->IsConstant()) {
5371 Handle<Object> constant_object = cell->type()->AsConstant()->Value();
5372 if (constant_object->IsConsString()) {
5376 HConstant* constant = New<HConstant>(constant_object);
5379 HLoadGlobalCell* instr =
5380 New<HLoadGlobalCell>(cell, it.property_details());
5384 HValue* global_object = Add<HLoadNamedField>(
5387 HLoadGlobalGeneric* instr =
5388 New<HLoadGlobalGeneric>(global_object,
5391 if (FLAG_vector_ics) {
5392 Handle<SharedFunctionInfo> current_shared =
5394 instr->SetVectorAndSlot(
5396 expr->VariableFeedbackSlot());
5405 if (value ==
graph()->GetConstantHole()) {
5407 variable->mode() !=
VAR);
5408 return Bailout(kReferenceToUninitializedVariable);
5415 HLoadContextSlot::Mode
mode;
5416 switch (variable->mode()) {
5419 mode = HLoadContextSlot::kCheckDeoptimize;
5422 mode = HLoadContextSlot::kCheckReturnUndefined;
5425 mode = HLoadContextSlot::kNoCheck;
5428 HLoadContextSlot* instr =
5434 return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
5439 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) {
5440 DCHECK(!HasStackOverflow());
5443 HConstant* instr = New<HConstant>(expr->value());
5448 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
5449 DCHECK(!HasStackOverflow());
5452 Handle<JSFunction> closure =
function_state()->compilation_info()->closure();
5453 Handle<FixedArray>
literals(closure->literals());
5454 HRegExpLiteral* instr = New<HRegExpLiteral>(
literals,
5457 expr->literal_index());
5463 if (type->
Is(Type::NumberOrString()))
return true;
5464 if (!type->
IsClass())
return false;
5466 return map->IsJSObjectMap() &&
5467 !
map->is_dictionary_map() &&
5468 !
map->has_named_interceptor();
5477 int* max_properties) {
5478 if (boilerplate->map()->is_deprecated() &&
5483 DCHECK(max_depth >= 0 && *max_properties >= 0);
5484 if (max_depth == 0)
return false;
5486 Isolate* isolate = boilerplate->GetIsolate();
5488 if (elements->length() > 0 &&
5489 elements->map() != isolate->
heap()->fixed_cow_array_map()) {
5490 if (boilerplate->HasFastObjectElements()) {
5492 int length = elements->length();
5493 for (
int i = 0;
i < length;
i++) {
5494 if ((*max_properties)-- == 0)
return false;
5496 if (value->IsJSObject()) {
5505 }
else if (!boilerplate->HasFastDoubleElements()) {
5511 if (properties->length() > 0) {
5515 boilerplate->map()->instance_descriptors());
5516 int limit = boilerplate->map()->NumberOfOwnDescriptors();
5517 for (
int i = 0;
i < limit;
i++) {
5518 PropertyDetails details = descriptors->GetDetails(
i);
5519 if (details.type() !=
FIELD)
continue;
5520 int index = descriptors->GetFieldIndex(
i);
5521 if ((*max_properties)-- == 0)
return false;
5522 Handle<Object> value(boilerplate->InObjectPropertyAt(index), isolate);
5523 if (value->IsJSObject()) {
5537 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
5538 DCHECK(!HasStackOverflow());
5541 expr->BuildConstantProperties(
isolate());
5543 HInstruction* literal;
5547 Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()),
5551 if (!literals_cell->IsUndefined()) {
5558 if (!boilerplate.is_null() &&
5560 AllocationSiteUsageContext usage_context(
isolate(), site,
false);
5561 usage_context.EnterNewScope();
5563 usage_context.ExitScope(site, boilerplate);
5565 NoObservableSideEffectsScope no_effects(
this);
5566 Handle<FixedArray> closure_literals(closure->literals(),
isolate());
5567 Handle<FixedArray> constant_properties = expr->constant_properties();
5568 int literal_index = expr->literal_index();
5569 int flags = expr->fast_elements()
5570 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags;
5571 flags |= expr->has_function()
5572 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags;
5574 Add<HPushArguments>(Add<HConstant>(closure_literals),
5575 Add<HConstant>(literal_index),
5576 Add<HConstant>(constant_properties),
5577 Add<HConstant>(
flags));
5583 literal = Add<HCallRuntime>(
isolate()->factory()->empty_string(),
5592 expr->CalculateEmitStore(
zone());
5594 for (
int i = 0;
i < expr->properties()->length();
i++) {
5595 ObjectLiteral::Property*
property = expr->properties()->at(
i);
5596 if (property->IsCompileTimeValue())
continue;
5598 Literal* key =
property->key();
5599 Expression* value =
property->value();
5601 switch (property->kind()) {
5602 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
5605 case ObjectLiteral::Property::COMPUTED:
5606 if (key->value()->IsInternalizedString()) {
5607 if (property->emit_store()) {
5609 HValue* value =
Pop();
5610 Handle<Map>
map =
property->GetReceiverType();
5611 Handle<String>
name =
property->key()->AsPropertyName();
5612 HInstruction* store;
5613 if (
map.is_null()) {
5619 if (info.CanAccessMonomorphic()) {
5620 HValue* checked_literal = Add<HCheckMaps>(literal,
map);
5621 DCHECK(!info.IsAccessor());
5623 &info, literal, checked_literal, value,
5631 if (store->HasObservableSideEffects()) {
5640 case ObjectLiteral::Property::PROTOTYPE:
5641 case ObjectLiteral::Property::SETTER:
5642 case ObjectLiteral::Property::GETTER:
5643 return Bailout(kObjectLiteralWithComplexProperty);
5648 if (expr->has_function()) {
5654 HToFastProperties* result = Add<HToFastProperties>(
Pop());
5662 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
5663 DCHECK(!HasStackOverflow());
5666 expr->BuildConstantElements(
isolate());
5667 ZoneList<Expression*>* subexprs = expr->values();
5668 int length = subexprs->length();
5669 HInstruction* literal;
5671 Handle<AllocationSite> site;
5673 bool uninitialized =
false;
5674 Handle<Object> literals_cell(
literals->get(expr->literal_index()),
5676 Handle<JSObject> boilerplate_object;
5677 if (literals_cell->IsUndefined()) {
5678 uninitialized =
true;
5679 Handle<Object> raw_boilerplate;
5684 Bailout(kArrayBoilerplateCreationFailed));
5687 AllocationSiteCreationContext creation_context(
isolate());
5688 site = creation_context.EnterNewScope();
5690 return Bailout(kArrayBoilerplateCreationFailed);
5692 creation_context.ExitScope(site, boilerplate_object);
5693 literals->set(expr->literal_index(), *site);
5695 if (boilerplate_object->elements()->map() ==
5696 isolate()->heap()->fixed_cow_array_map()) {
5700 DCHECK(literals_cell->IsAllocationSite());
5702 boilerplate_object = Handle<JSObject>(
5703 JSObject::cast(site->transition_info()),
isolate());
5706 DCHECK(!boilerplate_object.is_null());
5707 DCHECK(site->SitePointsToLiteral());
5710 boilerplate_object->GetElementsKind();
5717 AllocationSiteUsageContext usage_context(
isolate(), site,
false);
5718 usage_context.EnterNewScope();
5720 usage_context.ExitScope(site, boilerplate_object);
5722 NoObservableSideEffectsScope no_effects(
this);
5725 Handle<FixedArray> constants =
isolate()->
factory()->empty_fixed_array();
5726 int literal_index = expr->literal_index();
5727 int flags = expr->depth() == 1
5728 ? ArrayLiteral::kShallowElements
5729 : ArrayLiteral::kNoFlags;
5730 flags |= ArrayLiteral::kDisableMementos;
5732 Add<HPushArguments>(Add<HConstant>(
literals),
5733 Add<HConstant>(literal_index),
5734 Add<HConstant>(constants),
5735 Add<HConstant>(
flags));
5741 literal = Add<HCallRuntime>(
isolate()->factory()->empty_string(),
5746 Handle<Map>
map = Handle<Map>(boilerplate_object->map(),
isolate());
5747 literal = Add<HCheckMaps>(literal,
map);
5754 Push(Add<HConstant>(expr->literal_index()));
5756 HInstruction* elements =
NULL;
5758 for (
int i = 0;
i < length;
i++) {
5759 Expression* subexpr = subexprs->at(
i);
5765 HValue* value =
Pop();
5770 HValue* key = Add<HConstant>(
i);
5772 switch (boilerplate_elements_kind) {
5779 HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value,
5780 boilerplate_elements_kind);
5781 instr->SetUninitialized(uninitialized);
5789 Add<HSimulate>(expr->GetIdForElement(
i));
5800 return Add<HCheckMaps>(
object,
map);
5806 HValue* checked_object) {
5808 if (checked_object->
ActualValue()->IsConstant()) {
5812 if (object->IsJSObject()) {
5813 LookupIterator it(
object, info->
name(),
5814 LookupIterator::OWN_SKIP_INTERCEPTOR);
5816 if (it.IsFound() && it.IsReadOnly() && !it.IsConfigurable()) {
5817 return New<HConstant>(value);
5822 HObjectAccess access = info->
access();
5823 if (access.representation().IsDouble()) {
5825 checked_object = Add<HLoadNamedField>(
5829 access = HObjectAccess::ForHeapNumberValue();
5833 if (map_list->length() == 0) {
5834 return New<HLoadNamedField>(checked_object, checked_object, access);
5838 for (
int i = 0;
i < map_list->length(); ++
i) {
5841 return New<HLoadNamedField>(
5842 checked_object, checked_object, access, maps, info->
field_type());
5852 HObjectAccess field_access = info->
access();
5854 HStoreNamedField *instr;
5855 if (field_access.representation().IsDouble()) {
5856 HObjectAccess heap_number_access =
5858 if (transition_to_field) {
5860 NoObservableSideEffectsScope no_side_effects(
this);
5864 HInstruction* heap_number = Add<HAllocate>(heap_number_size,
5865 HType::HeapObject(),
5869 heap_number,
isolate()->factory()->mutable_heap_number_map());
5870 Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
5872 instr = New<HStoreNamedField>(checked_object->
ActualValue(),
5878 checked_object,
static_cast<HValue*
>(
NULL), heap_number_access);
5879 instr = New<HStoreNamedField>(heap_number,
5880 HObjectAccess::ForHeapNumberValue(),
5884 if (field_access.representation().IsHeapObject()) {
5889 DCHECK(field_access.representation().IsHeapObject());
5890 value = Add<HCheckMaps>(value, info->
field_maps());
5894 instr = New<HStoreNamedField>(
5895 checked_object->
ActualValue(), field_access, value,
5899 if (transition_to_field) {
5901 DCHECK(!transition->is_deprecated());
5902 instr->SetTransition(Add<HConstant>(transition));
5915 if (
type_->
Is(Type::Number()))
return false;
5919 if (
type_->
Is(Type::NumberOrString())) {
5920 if (!info->
type_->
Is(Type::NumberOrString()))
return false;
5922 if (info->
type_->
Is(Type::NumberOrString()))
return false;
5929 map()->prototype() == info->
map()->prototype();
5946 if (!info->
IsField())
return false;
5950 if (!info->
access_.representation().IsCompatibleForLoad(r))
return false;
5952 if (!info->
access_.representation().IsCompatibleForStore(r))
return false;
5955 if (info->
access_.IsInobject() !=
access_.IsInobject())
return false;
5982 if (!type_->IsClass())
return true;
5983 map()->LookupDescriptor(
NULL, *name_, &lookup_);
5984 return LoadResult(
map());
5989 if (!
IsLoad() && IsProperty() && IsReadOnly()) {
5995 int index = GetLocalFieldIndexFromMap(
map);
5996 access_ = HObjectAccess::ForField(
map, index, representation(), name_);
6000 }
else if (IsAccessor()) {
6002 if (!accessors->IsAccessorPair())
return false;
6006 if (!raw_accessor->IsJSFunction())
return false;
6008 if (accessor->shared()->IsApiFunction()) {
6009 CallOptimization call_optimization(accessor);
6010 if (call_optimization.is_simple_api_call()) {
6011 CallOptimization::HolderLookup holder_lookup;
6013 api_holder_ = call_optimization.LookupHolderOfExpectedType(
6014 receiver_map, &holder_lookup);
6017 accessor_ = accessor;
6018 }
else if (IsConstant()) {
6019 constant_ = GetConstantFromMap(
map);
6029 field_maps_.Clear();
6030 field_type_ = HType::Tagged();
6036 int num_field_maps = field_type->NumClasses();
6037 if (num_field_maps == 0)
return;
6038 DCHECK(access_.representation().IsHeapObject());
6039 field_maps_.Reserve(num_field_maps,
zone());
6041 while (!it.
Done()) {
6043 if (!field_map->is_stable()) {
6044 field_maps_.Clear();
6047 field_maps_.Add(field_map,
zone());
6051 DCHECK_EQ(num_field_maps, field_maps_.length());
6054 field_type_ = HType::FromType<HeapType>(field_type);
6055 DCHECK(field_type_.IsHeapObject());
6066 while (map->prototype()->IsJSObject()) {
6067 holder_ =
handle(JSObject::cast(
map->prototype()));
6068 if (holder_->map()->is_deprecated()) {
6076 map->LookupDescriptor(*holder_, *name_, &lookup_);
6077 if (IsFound())
return LoadResult(
map);
6086 if (IsJSObjectFieldAccessor())
return IsLoad();
6087 if (this->
map()->function_with_prototype() &&
6088 !this->
map()->has_non_instance_prototype() &&
6089 name_.is_identical_to(
isolate()->factory()->prototype_string())) {
6092 if (!LookupDescriptor())
return false;
6093 if (IsFound())
return IsLoad() || !IsReadOnly();
6094 if (!LookupInPrototypes())
return false;
6095 if (
IsLoad())
return true;
6097 if (IsAccessor())
return true;
6099 map->LookupTransition(
NULL, *name_, &lookup_);
6100 if (lookup_.IsTransitionToField() &&
map->unused_property_fields() > 0) {
6102 int descriptor = transition()->LastAdded();
6104 transition()->instance_descriptors()->GetFieldIndex(descriptor) -
6105 map->inobject_properties();
6106 PropertyDetails details =
6107 transition()->instance_descriptors()->GetDetails(descriptor);
6109 access_ = HObjectAccess::ForField(
map, index, representation, name_);
6112 LoadFieldMaps(transition());
6120 SmallMapList* types) {
6122 if (!CanAccessMonomorphic())
return false;
6126 HObjectAccess access = HObjectAccess::ForMap();
6127 if (GetJSObjectFieldAccess(&access)) {
6128 for (
int i = 1;
i < types->length(); ++
i) {
6130 builder_, access_type_,
ToType(types->at(
i)), name_);
6131 HObjectAccess test_access = HObjectAccess::ForMap();
6133 if (!access.Equals(test_access))
return false;
6141 if (type_->Is(Type::Number()))
return false;
6145 if (IsTransition() && types->length() > 1)
return false;
6147 for (
int i = 1;
i < types->length(); ++
i) {
6149 builder_, access_type_,
ToType(types->at(
i)), name_);
6161 return type_->AsClass()->Map();
6166 return type->
Is(Type::NumberOrString()) &&
6167 target->shared()->strict_mode() ==
SLOPPY &&
6168 !target->shared()->native();
6179 bool can_inline_accessor) {
6181 HObjectAccess access = HObjectAccess::ForMap();
6184 return New<HLoadNamedField>(
object, checked_object, access);
6187 if (info->
name().is_identical_to(
isolate()->factory()->prototype_string()) &&
6188 info->
map()->function_with_prototype()) {
6189 DCHECK(!info->
map()->has_non_instance_prototype());
6190 return New<HLoadFunctionPrototype>(checked_object);
6193 HValue* checked_holder = checked_object;
6201 return graph()->GetConstantUndefined();
6218 Push(checked_object);
6219 int argument_count = 1;
6228 return New<HCallFunction>(
function, argument_count,
WRAP_AND_CALL);
6229 }
else if (FLAG_inline_accessors && can_inline_accessor) {
6230 bool success = info->
IsLoad()
6233 info->
accessor(), info->
map(), ast_id, return_id, value);
6234 if (success || HasStackOverflow())
return NULL;
6243 return New<HConstant>(info->
constant());
6257 SmallMapList* types,
6261 HBasicBlock* join =
NULL;
6262 HBasicBlock* number_block =
NULL;
6263 bool handled_string =
false;
6265 bool handle_smi =
false;
6270 if (info.
type()->
Is(Type::String())) {
6271 if (handled_string)
continue;
6272 handled_string =
true;
6276 if (info.
type()->
Is(Type::Number())) {
6283 if (i < types->length()) {
6290 handled_string =
false;
6294 if (info.
type()->
Is(Type::String())) {
6295 if (handled_string)
continue;
6296 handled_string =
true;
6301 join =
graph()->CreateBasicBlock();
6303 HBasicBlock* empty_smi_block =
graph()->CreateBasicBlock();
6304 HBasicBlock* not_smi_block =
graph()->CreateBasicBlock();
6305 number_block =
graph()->CreateBasicBlock();
6306 smi_check = New<HIsSmiAndBranch>(
6307 object, empty_smi_block, not_smi_block);
6316 HBasicBlock* if_true =
graph()->CreateBasicBlock();
6317 HBasicBlock* if_false =
graph()->CreateBasicBlock();
6321 if (info.
type()->
Is(Type::Number())) {
6323 compare = New<HCompareMap>(
object, heap_number_map, if_true, if_false);
6324 dependency = smi_check;
6325 }
else if (info.
type()->
Is(Type::String())) {
6326 compare = New<HIsStringAndBranch>(
object, if_true, if_false);
6327 dependency = compare;
6329 compare = New<HCompareMap>(
object, info.
map(), if_true, if_false);
6330 dependency = compare;
6334 if (info.
type()->
Is(Type::Number())) {
6336 if_true = number_block;
6342 &info,
object, dependency, value, ast_id,
6343 return_id, FLAG_polymorphic_inlining);
6346 switch (access_type) {
6355 if (access ==
NULL) {
6356 if (HasStackOverflow())
return;
6369 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
6387 if (join->HasPredecessor()) {
6388 join->SetJoinId(ast_id);
6406 types->FilterForPossibleTransitions(root_map);
6407 monomorphic = types->length() == 1;
6409 return monomorphic &&
6415 for (
int i = 0;
i < types->length();
i++) {
6426 bool is_uninitialized) {
6427 if (!prop->key()->IsPropertyName()) {
6432 bool has_side_effects =
false;
6445 Literal* key = prop->key()->AsLiteral();
6450 object,
name, value, is_uninitialized);
6451 if (instr ==
NULL)
return;
6464 Property* prop = expr->target()->AsProperty();
6467 if (!prop->key()->IsPropertyName()) {
6472 expr->AssignmentId(), expr->IsUninitialized());
6484 LookupIterator it(global, var->
name(), LookupIterator::OWN_SKIP_INTERCEPTOR);
6488 if (cell->type()->IsConstant()) {
6490 if (value->IsConstant()) {
6491 HConstant* c_value = HConstant::cast(value);
6492 if (!constant.is_identical_to(c_value->handle(
isolate()))) {
6493 Add<HDeoptimize>(
"Constant global variable assignment",
6497 HValue* c_constant = Add<HConstant>(constant);
6498 IfBuilder builder(
this);
6499 if (constant->IsNumber()) {
6506 Add<HDeoptimize>(
"Constant global variable assignment",
6512 Add<HStoreGlobalCell>(value, cell, it.property_details());
6517 HValue* global_object = Add<HLoadNamedField>(
6520 HStoreNamedGeneric* instr =
6521 Add<HStoreNamedGeneric>(global_object, var->
name(),
6524 DCHECK(instr->HasObservableSideEffects());
6532 VariableProxy* proxy = target->AsVariableProxy();
6533 Property* prop = target->AsProperty();
6538 BinaryOperation* operation = expr->binary_operation();
6540 if (proxy !=
NULL) {
6543 return Bailout(kUnsupportedLetCompoundAssignment);
6552 expr->AssignmentId());
6558 return Bailout(kUnsupportedConstCompoundAssignment);
6572 for (
int i = 0;
i < count; ++
i) {
6574 Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
6579 HStoreContextSlot::Mode
mode;
6581 switch (var->
mode()) {
6583 mode = HStoreContextSlot::kCheckDeoptimize;
6592 mode = HStoreContextSlot::kNoCheck;
6596 HStoreContextSlot* instr = Add<HStoreContextSlot>(
6598 if (instr->HasObservableSideEffects()) {
6605 return Bailout(kCompoundAssignmentToLookupSlot);
6609 }
else if (prop !=
NULL) {
6613 if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
6627 expr->AssignmentId(), expr->IsUninitialized());
6629 return Bailout(kInvalidLhsInCompoundAssignment);
6634 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
6635 DCHECK(!HasStackOverflow());
6638 VariableProxy* proxy = expr->target()->AsVariableProxy();
6639 Property* prop = expr->target()->AsProperty();
6642 if (expr->is_compound()) {
6649 }
else if (proxy !=
NULL) {
6650 Variable* var = proxy->var();
6652 if (var->mode() ==
CONST) {
6653 if (expr->op() != Token::INIT_CONST) {
6654 return Bailout(kNonInitializerAssignmentToConst);
6657 if (expr->op() != Token::INIT_CONST_LEGACY) {
6662 if (var->IsStackAllocated()) {
6666 Add<HUseConst>(old_value);
6670 if (proxy->IsArguments())
return Bailout(kAssignmentToArguments);
6673 switch (var->location()) {
6678 expr->AssignmentId());
6685 if (var->mode() ==
LET && expr->op() == Token::ASSIGN) {
6687 if (env_value ==
graph()->GetConstantHole()) {
6688 return Bailout(kAssignmentToLetVariableBeforeInitialization);
6695 HValue* value =
Pop();
6708 for (
int i = 0;
i < count; ++
i) {
6710 return Bailout(kAssignmentToParameterInArgumentsObject);
6716 HStoreContextSlot::Mode
mode;
6717 if (expr->op() == Token::ASSIGN) {
6718 switch (var->mode()) {
6720 mode = HStoreContextSlot::kCheckDeoptimize;
6729 mode = HStoreContextSlot::kNoCheck;
6731 }
else if (expr->op() == Token::INIT_VAR ||
6732 expr->op() == Token::INIT_LET ||
6733 expr->op() == Token::INIT_CONST) {
6734 mode = HStoreContextSlot::kNoCheck;
6736 DCHECK(expr->op() == Token::INIT_CONST_LEGACY);
6738 mode = HStoreContextSlot::kCheckIgnoreAssignment;
6742 HStoreContextSlot* instr = Add<HStoreContextSlot>(
6744 if (instr->HasObservableSideEffects()) {
6751 return Bailout(kAssignmentToLOOKUPVariable);
6754 return Bailout(kInvalidLeftHandSideInAssignment);
6759 void HOptimizedGraphBuilder::VisitYield(Yield* expr) {
6765 void HOptimizedGraphBuilder::VisitThrow(
Throw* expr) {
6766 DCHECK(!HasStackOverflow());
6773 return Bailout(kInvalidLeftHandSideInAssignment);
6779 Add<HPushArguments>(value);
6780 Add<HCallRuntime>(
isolate()->factory()->empty_string(),
6782 Add<HSimulate>(expr->id());
6794 if (string->IsConstant()) {
6795 HConstant* c_string = HConstant::cast(
string);
6796 if (c_string->HasStringValue()) {
6797 return Add<HConstant>(c_string->StringValue()->map()->instance_type());
6800 return Add<HLoadNamedField>(
6801 Add<HLoadNamedField>(
string,
static_cast<HValue*
>(
NULL),
6802 HObjectAccess::ForMap()),
6803 static_cast<HValue*
>(
NULL), HObjectAccess::ForMapInstanceType());
6808 if (string->IsConstant()) {
6809 HConstant* c_string = HConstant::cast(
string);
6810 if (c_string->HasStringValue()) {
6811 return Add<HConstant>(c_string->StringValue()->length());
6814 return Add<HLoadNamedField>(
string,
static_cast<HValue*
>(
NULL),
6815 HObjectAccess::ForStringLength());
6825 bool is_uninitialized) {
6826 if (is_uninitialized) {
6827 Add<HDeoptimize>(
"Insufficient type feedback for generic named access",
6830 if (access_type ==
LOAD) {
6831 HLoadNamedGeneric* result = New<HLoadNamedGeneric>(
object,
name);
6832 if (FLAG_vector_ics) {
6835 result->SetVectorAndSlot(
6837 expr->AsProperty()->PropertyFeedbackSlot());
6853 if (access_type ==
LOAD) {
6854 HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
object, key);
6855 if (FLAG_vector_ics) {
6858 result->SetVectorAndSlot(
6860 expr->AsProperty()->PropertyFeedbackSlot());
6873 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
6878 graph()->MarkDependsOnEmptyArrayProtoElements();
6893 HCheckMaps* checked_object = Add<HCheckMaps>(
object,
map, dependency);
6895 checked_object->ClearDependsOnFlag(kElementsKind);
6898 if (access_type ==
STORE &&
map->prototype()->IsJSObject()) {
6908 DCHECK(holder && holder->IsJSObject());
6916 checked_object, key, val,
6918 map->elements_kind(), access_type,
6919 load_mode, store_mode);
6927 SmallMapList* maps) {
6932 bool has_double_maps =
false;
6933 bool has_smi_or_object_maps =
false;
6934 bool has_js_array_access =
false;
6935 bool has_non_js_array_access =
false;
6936 bool has_seen_holey_elements =
false;
6938 for (
int i = 0;
i < maps->length(); ++
i) {
6940 if (!
map->IsJSObjectMap())
return NULL;
6943 if (has_non_js_array_access)
return NULL;
6944 has_js_array_access =
true;
6945 }
else if (has_js_array_access) {
6948 has_non_js_array_access =
true;
6951 if (
map->has_fast_double_elements()) {
6952 if (has_smi_or_object_maps)
return NULL;
6953 has_double_maps =
true;
6954 }
else if (
map->has_fast_smi_or_object_elements()) {
6955 if (has_double_maps)
return NULL;
6956 has_smi_or_object_maps =
true;
6962 has_seen_holey_elements =
true;
6967 most_general_consolidated_map->elements_kind(),
6968 map->elements_kind())) {
6969 most_general_consolidated_map =
map;
6972 if (!has_double_maps && !has_smi_or_object_maps)
return NULL;
6974 HCheckMaps* checked_object = Add<HCheckMaps>(
object, maps);
6977 ElementsKind consolidated_elements_kind = has_seen_holey_elements
6979 : most_general_consolidated_map->elements_kind();
6981 checked_object, key, val,
6982 most_general_consolidated_map->instance_type() ==
JS_ARRAY_TYPE,
6983 consolidated_elements_kind,
6997 bool* has_side_effects) {
6998 *has_side_effects =
false;
7001 if (access_type ==
LOAD) {
7004 if (consolidated_load !=
NULL) {
7006 return consolidated_load;
7014 for (
int i = 0;
i < maps->length(); ++
i) {
7019 possible_transitioned_maps.
Add(
map);
7029 for (
int i = 0;
i < maps->length(); ++
i) {
7032 map->FindTransitionedMap(&possible_transitioned_maps);
7033 transition_target.
Add(transitioned_map);
7037 HTransitionElementsKind* transition =
NULL;
7038 for (
int i = 0;
i < maps->length(); ++
i) {
7043 map->elements_kind(),
7044 transition_target.
at(
i)->elements_kind()));
7045 transition = Add<HTransitionElementsKind>(
object,
map,
7046 transition_target.
at(
i));
7048 untransitionable_maps.
Add(
map);
7054 DCHECK(untransitionable_maps.length() >= 1);
7055 if (untransitionable_maps.length() == 1) {
7056 Handle<Map> untransitionable_map = untransitionable_maps[0];
7058 if (untransitionable_map->has_slow_elements_kind() ||
7059 !untransitionable_map->IsJSObjectMap()) {
7064 object, key, val, transition, untransitionable_map, access_type,
7068 return access_type ==
STORE ?
NULL : instr;
7071 HBasicBlock* join =
graph()->CreateBasicBlock();
7073 for (
int i = 0;
i < untransitionable_maps.length(); ++
i) {
7075 if (!
map->IsJSObjectMap())
continue;
7077 HBasicBlock* this_map =
graph()->CreateBasicBlock();
7078 HBasicBlock* other_map =
graph()->CreateBasicBlock();
7079 HCompareMap* mapcompare =
7080 New<HCompareMap>(
object,
map, this_map, other_map);
7095 mapcompare, key, val,
7097 elements_kind, access_type,
7104 if (access_type ==
LOAD) {
7107 NoObservableSideEffectsScope
scope(
this);
7116 DCHECK(join->predecessors()->length() > 0);
7118 NoObservableSideEffectsScope
scope(
this);
7128 bool* has_side_effects) {
7133 if (constant->IsString() &&
7135 if (!constant->IsUniqueName()) {
7143 *has_side_effects =
false;
7155 SmallMapList* types;
7158 bool force_generic =
false;
7159 if (access_type ==
STORE &&
7160 (monomorphic || (types !=
NULL && !types->is_empty()))) {
7165 for (
int i = 0;
i < types->length();
i++) {
7167 if (current_map->DictionaryElementsInPrototypeChainOnly()) {
7168 force_generic =
true;
7169 monomorphic =
false;
7177 if (
map->has_slow_elements_kind() || !
map->IsJSObjectMap()) {
7185 }
else if (!force_generic && (types !=
NULL && !types->is_empty())) {
7187 expr, obj, key, val, types, access_type,
7190 if (access_type ==
STORE) {
7191 if (expr->IsAssignment() &&
7192 expr->AsAssignment()->HasNoTypeInformation()) {
7193 Add<HDeoptimize>(
"Insufficient type feedback for keyed store",
7197 if (expr->AsProperty()->HasNoTypeInformation()) {
7198 Add<HDeoptimize>(
"Insufficient type feedback for keyed load",
7217 entry->set_arguments_pushed();
7219 HArgumentsObject* arguments = entry->arguments_object();
7223 for (
int i = 0;
i < arguments_values->length();
i++) {
7224 HValue* argument = arguments_values->
at(
i);
7225 HInstruction* push_argument = New<HPushArguments>(argument);
7227 insert_after = push_argument;
7230 HArgumentsElements* arguments_elements = New<HArgumentsElements>(
true);
7232 arguments_elements->InsertAfter(insert_after);
7238 VariableProxy* proxy = expr->obj()->AsVariableProxy();
7239 if (proxy ==
NULL)
return false;
7240 if (!proxy->var()->IsStackAllocated())
return false;
7246 if (expr->key()->IsPropertyName()) {
7253 HInstruction* elements = Add<HArgumentsElements>(
false);
7254 result = New<HArgumentsLength>(elements);
7258 arguments_environment()->parameter_count() - 1;
7259 result = New<HConstant>(argument_count);
7267 HInstruction* elements = Add<HArgumentsElements>(
false);
7268 HInstruction* length = Add<HArgumentsLength>(elements);
7269 HInstruction* checked_key = Add<HBoundsCheck>(key, length);
7270 result = New<HAccessArgumentsAt>(elements, length, checked_key);
7277 arguments_environment()->parameter_count() - 1;
7279 HInstruction* checked_key = Add<HBoundsCheck>(key, length);
7280 result = New<HAccessArgumentsAt>(elements, length, checked_key);
7296 bool is_uninitialized) {
7297 SmallMapList* types;
7301 if (types->length() > 0) {
7305 access, expr, ast_id, return_id,
object, value, types,
name);
7315 Add<HCheckInstanceType>(
object, HCheckInstanceType::IS_STRING);
7317 checked_object = Add<HCheckMaps>(
object, types);
7320 &info,
object, checked_object, value, ast_id, return_id);
7340 if (expr->IsStringAccess()) {
7345 instr = NewUncasted<HStringCharFromCode>(char_code);
7347 }
else if (expr->key()->IsPropertyName()) {
7352 object,
name,
NULL, expr->IsUninitialized());
7353 if (instr ==
NULL)
return;
7360 bool has_side_effects =
false;
7362 obj, key,
NULL, expr, ast_id, expr->LoadId(),
LOAD, &has_side_effects);
7363 if (has_side_effects) {
7372 if (load ==
NULL)
return;
7379 void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
7380 DCHECK(!HasStackOverflow());
7387 if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) {
7396 HCheckMaps* check = Add<HCheckMaps>(
7397 Add<HConstant>(constant),
handle(constant->map()));
7398 check->ClearDependsOnFlag(kElementsKind);
7431 HValue* fun,
int argument_count,
bool pass_argument_count) {
7432 return New<HCallJSFunction>(
7433 fun, argument_count, pass_argument_count);
7439 int argument_count,
HValue* expected_param_count) {
7441 HValue* arity = Add<HConstant>(argument_count - 1);
7443 HValue* op_vals[] = {
context, fun, arity, expected_param_count };
7447 HConstant* adaptor_value = Add<HConstant>(adaptor);
7449 return New<HCallWithDescriptor>(
7450 adaptor_value, argument_count, descriptor,
7457 HValue* target = Add<HConstant>(jsfun);
7460 int formal_parameter_count = jsfun->shared()->formal_parameter_count();
7461 bool dont_adapt_arguments =
7462 (formal_parameter_count ==
7464 int arity = argument_count - 1;
7465 bool can_invoke_directly =
7466 dont_adapt_arguments || formal_parameter_count == arity;
7467 if (can_invoke_directly) {
7468 if (jsfun.is_identical_to(
current_info()->closure())) {
7469 graph()->MarkRecursive();
7473 HValue* param_count_value = Add<HConstant>(formal_parameter_count);
7476 HObjectAccess::ForFunctionContextPointer());
7478 argument_count, param_count_value);
7488 : index_(index), ticks_(ticks), size_(
size) {}
7503 if (diff != 0)
return diff > 0;
7511 SmallMapList* types,
7513 int argument_count = expr->arguments()->length() + 1;
7516 bool handle_smi =
false;
7517 bool handled_string =
false;
7518 int ordered_functions = 0;
7526 if (info.
type()->
Is(Type::String())) {
7527 if (handled_string)
continue;
7528 handled_string =
true;
7531 if (info.
type()->
Is(Type::Number())) {
7534 expr->set_target(target);
7540 std::sort(order, order + ordered_functions);
7542 if (i < types->length()) {
7544 ordered_functions = -1;
7547 HBasicBlock* number_block =
NULL;
7548 HBasicBlock* join =
NULL;
7549 handled_string =
false;
7552 for (
int fn = 0; fn < ordered_functions; ++fn) {
7553 int i = order[fn].
index();
7555 if (info.
type()->
Is(Type::String())) {
7556 if (handled_string)
continue;
7557 handled_string =
true;
7563 expr->set_target(target);
7566 join =
graph()->CreateBasicBlock();
7568 HBasicBlock* empty_smi_block =
graph()->CreateBasicBlock();
7569 HBasicBlock* not_smi_block =
graph()->CreateBasicBlock();
7570 number_block =
graph()->CreateBasicBlock();
7572 receiver, empty_smi_block, not_smi_block));
7580 HBasicBlock* if_true =
graph()->CreateBasicBlock();
7581 HBasicBlock* if_false =
graph()->CreateBasicBlock();
7585 if (info.
type()->
Is(Type::Number())) {
7587 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
7588 }
else if (info.
type()->
Is(Type::String())) {
7589 compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
7591 compare = New<HCompareMap>(receiver,
map, if_true, if_false);
7595 if (info.
type()->
Is(Type::Number())) {
7597 if_true = number_block;
7604 HValue*
function = Add<HConstant>(expr->target());
7609 bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
7610 if (FLAG_trace_inlining && try_inline) {
7613 caller->shared()->DebugName()->ToCString();
7614 PrintF(
"Trying to inline the polymorphic call to %s from %s\n",
7615 name->ToCString().get(),
7621 if (HasStackOverflow())
return;
7628 ? NewUncasted<HCallFunction>(
7644 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
7647 Property* prop = expr->expression()->AsProperty();
7649 LOAD, prop, receiver,
name,
NULL, prop->IsUninitialized());
7661 function, argument_count,
flags);
7680 if (join->HasPredecessor()) {
7682 join->SetJoinId(expr->id());
7692 const char* reason) {
7693 if (FLAG_trace_inlining) {
7695 target->shared()->DebugName()->ToCString();
7697 caller->shared()->DebugName()->ToCString();
7698 if (reason ==
NULL) {
7699 PrintF(
"Inlined %s called from %s.\n", target_name.
get(),
7702 PrintF(
"Did not inline %s called from %s (%s).\n",
7703 target_name.
get(), caller_name.
get(), reason);
7721 if (target->IsBuiltin()) {
7725 if (target_shared->IsApiFunction()) {
7726 TraceInline(target, caller,
"target is api function");
7732 if (target_shared->SourceSize() >
7734 TraceInline(target, caller,
"target text too big");
7739 if (!target_shared->IsInlineable()) {
7740 TraceInline(target, caller,
"target not inlineable");
7743 if (target_shared->DisableOptimizationReason() != kNoReason) {
7744 TraceInline(target, caller,
"target contains unsupported syntax [early]");
7748 int nodes_added = target_shared->ast_node_count();
7754 int arguments_count,
7755 HValue* implicit_return_value,
7766 TraceInline(target, caller,
"target AST is too large [early]");
7772 int current_level = 1;
7773 while (env->outer() !=
NULL) {
7774 if (current_level == FLAG_max_inlining_levels) {
7775 TraceInline(target, caller,
"inline depth limit reached");
7787 state = state->outer()) {
7788 if (*state->compilation_info()->closure() == *target) {
7789 TraceInline(target, caller,
"target is recursive");
7797 TraceInline(target, caller,
"cumulative AST node limit reached");
7811 target_shared->DisableOptimization(kParseScopeError);
7818 TraceInline(target, caller,
"target has context-allocated variables");
7821 FunctionLiteral*
function = target_info.
function();
7825 nodes_added =
function->ast_node_count();
7827 TraceInline(target, caller,
"target AST is too large [late]");
7830 if (function->dont_optimize()) {
7831 TraceInline(target, caller,
"target contains unsupported syntax [late]");
7838 if (function->scope()->arguments() !=
NULL) {
7839 if (!FLAG_inline_arguments) {
7840 TraceInline(target, caller,
"target uses arguments object");
7844 if (!function->scope()->arguments()->IsStackAllocated()) {
7847 "target uses non-stackallocated arguments object");
7854 int decl_count = decls->length();
7855 for (
int i = 0;
i < decl_count; ++
i) {
7856 if (!decls->
at(
i)->IsInlineable()) {
7857 TraceInline(target, caller,
"target has non-trivial declaration");
7865 TraceInline(target, caller,
"could not generate deoptimization info");
7874 DCHECK(target_shared->has_deoptimization_support());
7877 int function_id =
graph()->TraceInlinedFunction(target_shared, position);
7883 this, &target_info, inlining_kind, function_id);
7885 HConstant* undefined =
graph()->GetConstantUndefined();
7887 HEnvironment* inner_env =
7895 inner_env->BindContext(
context);
7899 HEnvironment* arguments_env = inner_env->arguments_environment();
7900 int parameter_count = arguments_env->parameter_count();
7901 HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count);
7902 for (
int i = 0;
i < parameter_count;
i++) {
7903 arguments_object->AddArgument(arguments_env->Lookup(
i),
zone());
7907 if (function->scope()->arguments() !=
NULL) {
7908 DCHECK(function->scope()->arguments()->IsStackAllocated());
7909 inner_env->Bind(function->scope()->arguments(), arguments_object);
7922 HEnterInlined* enter_inlined =
7923 Add<HEnterInlined>(return_id, target,
context, arguments_count,
function,
7925 function->scope()->arguments(), arguments_object);
7931 if (HasStackOverflow()) {
7934 TraceInline(target, caller,
"inline graph construction failed");
7935 target_shared->DisableOptimization(kInliningBailedOut);
7937 delete target_state;
7945 DCHECK(unoptimized_code->kind() == Code::FUNCTION);
7947 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
7948 graph()->update_type_change_checksum(type_info->own_type_change_checksum());
8002 delete target_state;
8005 if (if_true->HasPredecessor()) {
8006 entry->RegisterReturnTarget(if_true,
zone());
8007 if_true->SetJoinId(ast_id);
8008 HBasicBlock* true_target = TestContext::cast(
ast_context())->if_true();
8011 if (if_false->HasPredecessor()) {
8012 entry->RegisterReturnTarget(if_false,
zone());
8013 if_false->SetJoinId(ast_id);
8014 HBasicBlock* false_target = TestContext::cast(
ast_context())->if_false();
8027 delete target_state;
8034 expr->arguments()->length(),
8044 HValue* implicit_return_value) {
8046 expr->arguments()->length(),
8047 implicit_return_value,
8074 HValue* implicit_return_value) {
8078 implicit_return_value,
8087 int arguments_count) {
8099 if (!expr->target()->shared()->HasBuiltinFunctionId())
return false;
8103 if (!FLAG_fast_math)
break;
8112 if (expr->arguments()->length() == 1) {
8115 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument,
id);
8121 if (expr->arguments()->length() == 2) {
8143 if (!expr->target()->shared()->HasBuiltinFunctionId())
return false;
8145 int argument_count = expr->arguments()->length() + 1;
8147 case kStringCharCodeAt:
8149 if (argument_count == 2) {
8155 if (
id == kStringCharCodeAt) {
8160 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
8165 case kStringFromCharCode:
8166 if (argument_count == 2) {
8169 HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
8175 if (!FLAG_fast_math)
break;
8184 if (argument_count == 2) {
8187 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument,
id);
8193 if (argument_count == 3) {
8199 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
8200 double exponent = HConstant::cast(right)->DoubleValue();
8201 if (exponent == 0.5) {
8202 result = NewUncasted<HUnaryMathOperation>(left,
kMathPowHalf);
8203 }
else if (exponent == -0.5) {
8210 result = NewUncasted<HDiv>(one, sqrt);
8211 }
else if (exponent == 2.0) {
8212 result = NewUncasted<HMul>(left, left);
8216 if (result ==
NULL) {
8217 result = NewUncasted<HPower>(left, right);
8225 if (argument_count == 3) {
8229 HMathMinMax::Operation op = (
id == kMathMin) ? HMathMinMax::kMathMin
8230 : HMathMinMax::kMathMax;
8231 HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
8237 if (argument_count == 3) {
8247 if (receiver_map.
is_null())
return false;
8248 if (receiver_map->instance_type() !=
JS_ARRAY_TYPE)
return false;
8249 ElementsKind elements_kind = receiver_map->elements_kind();
8251 if (receiver_map->is_observed())
return false;
8252 if (!receiver_map->is_extensible())
return false;
8254 Drop(expr->arguments()->length());
8260 HValue* length = Add<HLoadNamedField>(
8262 HObjectAccess::ForArrayLength(elements_kind));
8266 { NoObservableSideEffectsScope
scope(
this);
8267 IfBuilder length_checker(
this);
8271 length_checker.Then();
8275 length_checker.Else();
8280 elements_kind, length);
8282 reduced_length = AddUncasted<HSub>(length,
graph()->GetConstant1());
8284 bounds_check, elements_kind,
LOAD);
8288 ? Add<HConstant>(factory->the_hole_value())
8289 : Add<HConstant>(nan_double);
8294 elements, reduced_length, hole, bounds_check, elements_kind,
STORE);
8295 Add<HStoreNamedField>(
8296 checked_object, HObjectAccess::ForArrayLength(elements_kind),
8301 length_checker.End();
8311 if (receiver_map.
is_null())
return false;
8312 if (receiver_map->instance_type() !=
JS_ARRAY_TYPE)
return false;
8313 ElementsKind elements_kind = receiver_map->elements_kind();
8315 if (receiver_map->is_observed())
return false;
8317 if (!receiver_map->is_extensible())
return false;
8321 if (receiver_map->DictionaryElementsInPrototypeChainOnly())
return false;
8330 const int argc = expr->arguments()->length();
8331 if (argc != 1)
return false;
8341 NoObservableSideEffectsScope
scope(
this);
8343 length = Add<HLoadNamedField>(array,
static_cast<HValue*
>(
NULL),
8344 HObjectAccess::ForArrayLength(elements_kind));
8346 new_size = AddUncasted<HAdd>(length,
graph()->GetConstant1());
8348 bool is_array = receiver_map->instance_type() ==
JS_ARRAY_TYPE;
8350 value_to_push, is_array,
8351 elements_kind,
STORE,
8364 if (receiver_map.
is_null())
return false;
8365 if (receiver_map->instance_type() !=
JS_ARRAY_TYPE)
return false;
8368 if (receiver_map->is_observed())
return false;
8369 if (!receiver_map->is_extensible())
return false;
8373 if (receiver_map->DictionaryElementsInPrototypeChainOnly())
return false;
8381 handle(JSObject::cast(receiver_map->prototype()),
isolate()),
8385 HConstant* inline_threshold = Add<HConstant>(
static_cast<int32_t>(16));
8387 Drop(expr->arguments()->length());
8393 NoObservableSideEffectsScope
scope(
this);
8395 HValue* length = Add<HLoadNamedField>(
8397 HObjectAccess::ForArrayLength(kind));
8399 IfBuilder if_lengthiszero(
this);
8402 if_lengthiszero.Then();
8406 if_lengthiszero.Else();
8411 IfBuilder if_inline(
this);
8413 length, inline_threshold, Token::LTE);
8416 if_inline.AndIf<HCompareMap>(
8424 lengthiszero, kind,
LOAD));
8428 HValue* new_length = AddUncasted<HSub>(
8429 length,
graph()->GetConstant1());
8433 LoopBuilder loop(
this,
context(), LoopBuilder::kPostIncrement);
8435 HValue* new_key = loop.BeginBody(
8436 graph()->GetConstant0(), new_length, Token::LT);
8437 HValue* key = AddUncasted<HAdd>(new_key,
graph()->GetConstant1());
8439 HValue* element = AddUncasted<HLoadKeyed>(
8441 HStoreKeyed* store = Add<HStoreKeyed>(
8442 elements, new_key, element, kind);
8449 ? Add<HConstant>(
isolate()->factory()->the_hole_value())
8456 Add<HStoreNamedField>(
8457 receiver, HObjectAccess::ForArrayLength(kind),
8462 Add<HPushArguments>(receiver);
8463 result = Add<HCallJSFunction>(
function, 1,
true);
8468 if_lengthiszero.End();
8477 case kArrayLastIndexOf: {
8478 if (receiver_map.
is_null())
return false;
8479 if (receiver_map->instance_type() !=
JS_ARRAY_TYPE)
return false;
8482 if (receiver_map->is_observed())
return false;
8483 if (argument_count != 2)
return false;
8484 if (!receiver_map->is_extensible())
return false;
8488 if (receiver_map->DictionaryElementsInPrototypeChainOnly())
return false;
8496 handle(JSObject::cast(receiver_map->prototype()),
isolate()),
8524 int argc = expr->arguments()->length();
8525 SmallMapList receiver_maps;
8538 SmallMapList* receiver_maps) {
8540 int argc = expr->arguments()->length();
8553 SmallMapList receiver_maps(1,
zone());
8554 receiver_maps.Add(receiver_map,
zone());
8567 SmallMapList receiver_maps(1,
zone());
8568 receiver_maps.Add(receiver_map,
zone());
8580 SmallMapList* receiver_maps,
8584 CallOptimization optimization(
function);
8585 if (!optimization.is_simple_api_call())
return false;
8592 receiver_maps->Add(
handle(function->global_proxy()->map()),
zone());
8594 CallOptimization::HolderLookup holder_lookup =
8595 CallOptimization::kHolderNotFound;
8597 receiver_maps->first(), &holder_lookup);
8598 if (holder_lookup == CallOptimization::kHolderNotFound)
return false;
8600 if (FLAG_trace_inlining) {
8601 PrintF(
"Inlining api function ");
8602 function->ShortPrint();
8606 bool drop_extra =
false;
8607 bool is_store =
false;
8608 switch (call_type) {
8612 Add<HCheckMaps>(receiver, receiver_maps);
8614 if (holder_lookup == CallOptimization::kHolderFound) {
8617 DCHECK_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
8630 Add<HPushArguments>(receiver);
8641 Add<HPushArguments>(receiver, value);
8647 switch (holder_lookup) {
8648 case CallOptimization::kHolderFound:
8649 holder = Add<HConstant>(api_holder);
8651 case CallOptimization::kHolderIsReceiver:
8654 case CallOptimization::kHolderNotFound:
8660 bool call_data_is_undefined = call_data_obj->IsUndefined();
8661 HValue* call_data = Add<HConstant>(call_data_obj);
8662 ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
8663 ExternalReference ref = ExternalReference(&fun,
8664 ExternalReference::DIRECT_API_CALL,
8666 HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
8670 Add<HConstant>(
function),
8673 api_function_address
8679 HConstant* code_value = Add<HConstant>(code);
8684 code_value, argc + 1, descriptor,
8687 if (drop_extra)
Drop(1);
8694 DCHECK(expr->expression()->IsProperty());
8696 if (!expr->IsMonomorphic()) {
8699 Handle<Map> function_map = expr->GetReceiverTypes()->first();
8701 !expr->target()->shared()->HasBuiltinFunctionId() ||
8702 expr->target()->shared()->builtin_function_id() != kFunctionApply) {
8709 if (args->length() != 2)
return false;
8711 VariableProxy* arg_two = args->
at(1)->AsVariableProxy();
8712 if (arg_two ==
NULL || !arg_two->var()->IsStackAllocated())
return false;
8725 HInstruction* elements = Add<HArgumentsElements>(
false);
8726 HInstruction* length = Add<HArgumentsLength>(elements);
8738 function_state()->entry()->arguments_object()->arguments_count());
8739 HArgumentsObject* args =
function_state()->entry()->arguments_object();
8741 int arguments_count = arguments_values->length();
8744 for (
int i = 1;
i < arguments_count;
i++) {
8745 Push(arguments_values->
at(
i));
8749 if (function->IsConstant() &&
8750 HConstant::cast(
function)->handle(
isolate())->IsJSFunction()) {
8753 int args_count = arguments_count - 1;
8754 if (
TryInlineApply(known_function, expr, args_count))
return true;
8758 HInvokeFunction* call = New<HInvokeFunction>(
8759 function, known_function, arguments_count);
8775 return Add<HConstant>(global_proxy);
8777 return graph()->GetConstantUndefined();
8782 int arguments_count,
8793 function, arguments_count + 1, site->GetElementsKind()));
8794 if (expression->IsCall()) {
8807 NoObservableSideEffectsScope no_effects(
this);
8815 LoopBuilder::Direction direction;
8817 initial =
graph()->GetConstant0();
8818 terminating = length;
8820 direction = LoopBuilder::kPostIncrement;
8824 terminating =
graph()->GetConstant0();
8826 direction = LoopBuilder::kPreDecrement;
8833 search_element = AddUncasted<HForceRepresentation>(
8837 LoopBuilder loop(
this,
context(), direction);
8839 HValue* index = loop.BeginBody(initial, terminating, token);
8840 HValue* element = AddUncasted<HLoadKeyed>(
8843 IfBuilder if_issame(
this);
8856 IfBuilder if_isstring(
this);
8857 if_isstring.If<HIsStringAndBranch>(search_element);
8860 LoopBuilder loop(
this,
context(), direction);
8862 HValue* index = loop.BeginBody(initial, terminating, token);
8863 HValue* element = AddUncasted<HLoadKeyed>(
8866 IfBuilder if_issame(
this);
8867 if_issame.If<HIsStringAndBranch>(element);
8869 element, search_element, Token::EQ_STRICT);
8882 IfBuilder if_isnumber(
this);
8883 if_isnumber.If<HIsSmiAndBranch>(search_element);
8884 if_isnumber.OrIf<HCompareMap>(
8889 AddUncasted<HForceRepresentation>(search_element,
8891 LoopBuilder loop(
this,
context(), direction);
8893 HValue* index = loop.BeginBody(initial, terminating, token);
8894 HValue* element = AddUncasted<HLoadKeyed>(
8898 IfBuilder if_element_isnumber(
this);
8899 if_element_isnumber.If<HIsSmiAndBranch>(element);
8900 if_element_isnumber.OrIf<HCompareMap>(
8902 if_element_isnumber.Then();
8905 AddUncasted<HForceRepresentation>(element,
8907 IfBuilder if_issame(
this);
8909 number, search_number, Token::EQ_STRICT);
8918 if_element_isnumber.End();
8924 LoopBuilder loop(
this,
context(), direction);
8926 HValue* index = loop.BeginBody(initial, terminating, token);
8927 HValue* element = AddUncasted<HLoadKeyed>(
8930 IfBuilder if_issame(
this);
8932 element, search_element);
8958 if (site.
is_null())
return false;
8961 expr->arguments()->length(),
8975 expr->arguments()->length(),
8977 expr->allocation_site());
8982 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
8983 DCHECK(!HasStackOverflow());
8987 int argument_count = expr->arguments()->length() + 1;
8990 Property* prop = callee->AsProperty();
8995 SmallMapList* types;
8998 if (prop->key()->IsPropertyName() && types->length() > 0) {
9000 PropertyAccessInfo info(
this,
LOAD,
ToType(types->first()),
name);
9001 if (!info.CanAccessAsMonomorphic(types)) {
9008 if (!prop->key()->IsPropertyName()) {
9014 HValue*
function =
Pop();
9023 if (function->IsConstant() &&
9024 HConstant::cast(
function)->handle(
isolate())->IsJSFunction()) {
9027 expr->set_target(known_function);
9032 Handle<Map>
map = types->length() == 1 ? types->first() : Handle<Map>();
9034 if (FLAG_trace_inlining) {
9035 PrintF(
"Inlining builtin ");
9036 known_function->ShortPrint();
9050 call = New<HCallFunction>(
9062 call = New<HCallFunction>(
function, argument_count,
flags);
9067 VariableProxy* proxy = expr->expression()->AsVariableProxy();
9068 if (proxy !=
NULL && proxy->var()->is_possibly_eval(
isolate())) {
9069 return Bailout(kPossibleDirectCallToEval);
9075 HValue*
function =
Top();
9076 if (expr->global_call()) {
9077 Variable* var = proxy->var();
9078 bool known_global_function =
false;
9082 Handle<GlobalObject> global(
current_info()->global_object());
9083 LookupIterator it(global, var->name(),
9084 LookupIterator::OWN_SKIP_INTERCEPTOR);
9087 Handle<GlobalObject> global(
current_info()->global_object());
9088 known_global_function = expr->ComputeGlobalTarget(global, &it);
9090 if (known_global_function) {
9091 Add<HCheckValue>(
function, expr->target());
9099 const int receiver_index = argument_count - 1;
9100 environment()->SetExpressionStackAt(receiver_index, receiver);
9103 if (FLAG_trace_inlining) {
9104 PrintF(
"Inlining builtin ");
9105 expr->target()->ShortPrint();
9120 call = New<HCallFunction>(
function, argument_count);
9123 }
else if (expr->IsMonomorphic()) {
9124 Add<HCheckValue>(
function, expr->target());
9130 const int receiver_index = argument_count - 1;
9131 environment()->SetExpressionStackAt(receiver_index, receiver);
9134 if (FLAG_trace_inlining) {
9135 PrintF(
"Inlining builtin ");
9136 expr->target()->ShortPrint();
9146 function, expr->target(), argument_count));
9152 call = New<HCallFunction>(
function, argument_count);
9166 DCHECK(argument_count >= 0 && argument_count <= 1);
9167 NoObservableSideEffectsScope no_effects(
this);
9182 if (argument->IsConstant()) {
9183 HConstant* constant_argument = HConstant::cast(argument);
9184 DCHECK(constant_argument->HasSmiValue());
9185 int constant_array_size = constant_argument->Integer32Value();
9186 if (constant_array_size != 0) {
9193 JSArrayBuilder array_builder(
this,
9198 HValue* new_object = argument_count == 0
9199 ? array_builder.AllocateEmptyArray()
9202 int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1);
9210 return constructor->has_initial_map() &&
9212 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize &&
9213 constructor->initial_map()->InitialPropertiesLength() == 0;
9226 bool inline_ok =
false;
9227 if (site->CanInlineCall()) {
9229 if (argument_count == 1) {
9231 if (argument->IsConstant()) {
9234 HConstant* constant_argument = HConstant::cast(argument);
9235 if (constant_argument->HasSmiValue()) {
9236 int value = constant_argument->Integer32Value();
9240 "Constant length outside of valid inlining range.");
9245 "Dont inline [new] Array(n) where n isn't constant.");
9247 }
else if (argument_count == 0) {
9250 TraceInline(target, caller,
"Too many arguments to inline.");
9253 TraceInline(target, caller,
"AllocationSite requested no inlining.");
9263 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
9264 DCHECK(!HasStackOverflow());
9268 int argument_count = expr->arguments()->length() + 1;
9277 if (FLAG_inline_construct &&
9278 expr->IsMonomorphic() &&
9281 HValue* check = Add<HCheckValue>(
function, constructor);
9285 if (constructor->IsInobjectSlackTrackingInProgress()) {
9286 constructor->CompleteInobjectSlackTracking();
9290 DCHECK(constructor->has_initial_map());
9291 Handle<Map> initial_map(constructor->initial_map());
9292 int instance_size = initial_map->instance_size();
9293 DCHECK(initial_map->InitialPropertiesLength() == 0);
9296 HValue* size_in_bytes = Add<HConstant>(instance_size);
9297 HAllocationMode allocation_mode;
9298 if (FLAG_pretenuring_call_new) {
9299 if (FLAG_allocation_site_pretenuring) {
9302 allocation_mode = HAllocationMode(allocation_site);
9311 size_in_bytes, HType::JSObject(),
JS_OBJECT_TYPE, allocation_mode);
9312 receiver->set_known_initial_map(initial_map);
9315 { NoObservableSideEffectsScope no_effects(
this);
9317 Add<HStoreNamedField>(receiver,
9319 Add<HConstant>(initial_map));
9320 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
9321 Add<HStoreNamedField>(receiver,
9322 HObjectAccess::ForMapAndOffset(initial_map,
9325 Add<HStoreNamedField>(receiver,
9326 HObjectAccess::ForMapAndOffset(initial_map,
9329 if (initial_map->inobject_properties() != 0) {
9330 HConstant* undefined =
graph()->GetConstantUndefined();
9331 for (
int i = 0;
i < initial_map->inobject_properties();
i++) {
9332 int property_offset = initial_map->GetInObjectPropertyOffset(
i);
9333 Add<HStoreNamedField>(receiver,
9334 HObjectAccess::ForMapAndOffset(initial_map, property_offset),
9342 const int receiver_index = argument_count - 1;
9344 environment()->SetExpressionStackAt(receiver_index, receiver);
9361 HInstruction* prev_instr = instr->previous();
9362 instr->DeleteAndReplaceWith(
NULL);
9364 }
while (instr != check);
9365 environment()->SetExpressionStackAt(receiver_index,
function);
9366 HInstruction* call =
9374 HInstruction* call =
9386 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
9387 &HOptimizedGraphBuilder::Generate##Name,
9394 #undef INLINE_FUNCTION_GENERATOR_ADDRESS
9397 template <
class ViewClass>
9404 for (
int offset = ViewClass::kSize;
9405 offset < ViewClass::kSizeWithInternalFields;
9407 Add<HStoreNamedField>(obj,
9408 HObjectAccess::ForObservableJSObjectOffset(offset),
9409 graph()->GetConstant0());
9412 Add<HStoreNamedField>(
9414 HObjectAccess::ForJSArrayBufferViewByteOffset(),
9416 Add<HStoreNamedField>(
9418 HObjectAccess::ForJSArrayBufferViewByteLength(),
9421 if (buffer !=
NULL) {
9422 Add<HStoreNamedField>(
9424 HObjectAccess::ForJSArrayBufferViewBuffer(), buffer);
9425 HObjectAccess weak_first_view_access =
9426 HObjectAccess::ForJSArrayBufferWeakFirstView();
9427 Add<HStoreNamedField>(obj,
9428 HObjectAccess::ForJSArrayBufferViewWeakNext(),
9429 Add<HLoadNamedField>(buffer,
9431 weak_first_view_access));
9432 Add<HStoreNamedField>(buffer, weak_first_view_access, obj);
9434 Add<HStoreNamedField>(
9436 HObjectAccess::ForJSArrayBufferViewBuffer(),
9437 Add<HConstant>(
static_cast<int32_t>(0)));
9438 Add<HStoreNamedField>(obj,
9439 HObjectAccess::ForJSArrayBufferViewWeakNext(),
9440 graph()->GetConstantUndefined());
9445 void HOptimizedGraphBuilder::GenerateDataViewInitialize(
9446 CallRuntime* expr) {
9449 DCHECK(arguments->length()== 4);
9463 NoObservableSideEffectsScope
scope(
this);
9464 BuildArrayBufferViewInitialization<JSDataView>(
9465 obj, buffer, byte_offset, byte_length);
9475 switch (array_type) {
9476 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
9477 case kExternal##Type##Array: \
9478 fun = Handle<JSFunction>(native_context->type##_array_fun()); \
9482 #undef TYPED_ARRAY_CASE
9491 bool is_zero_byte_offset,
9494 isolate()->heap()->MapForExternalArrayType(array_type));
9502 HType::HeapObject(),
9504 external_array_map->instance_type());
9507 Add<HStoreNamedField>(elements,
9508 HObjectAccess::ForFixedArrayLength(), length);
9510 HValue* backing_store = Add<HLoadNamedField>(
9512 HObjectAccess::ForJSArrayBufferBackingStore());
9514 HValue* typed_array_start;
9515 if (is_zero_byte_offset) {
9516 typed_array_start = backing_store;
9519 AddUncasted<HAdd>(backing_store, byte_offset);
9523 typed_array_start = external_pointer;
9526 Add<HStoreNamedField>(elements,
9527 HObjectAccess::ForExternalArrayExternalPointer(),
9548 total_size = AddUncasted<HAdd>(byte_length,
9557 isolate()->heap()->MapForFixedTypedArray(array_type));
9559 Add<HAllocate>(total_size, HType::HeapObject(),
9560 NOT_TENURED, fixed_typed_array_map->instance_type());
9563 Add<HStoreNamedField>(elements,
9564 HObjectAccess::ForFixedArrayLength(),
9570 LoopBuilder builder(
this,
context(), LoopBuilder::kPostIncrement);
9572 HValue* key = builder.BeginBody(
9573 Add<HConstant>(
static_cast<int32_t>(0)),
9575 Add<HStoreKeyed>(elements, key, filler, fixed_elements_kind);
9583 void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
9584 CallRuntime* expr) {
9587 static const int kObjectArg = 0;
9588 static const int kArrayIdArg = 1;
9589 static const int kBufferArg = 2;
9590 static const int kByteOffsetArg = 3;
9591 static const int kByteLengthArg = 4;
9592 static const int kArgsLength = 5;
9593 DCHECK(arguments->length() == kArgsLength);
9599 if (arguments->
at(kArrayIdArg)->IsLiteral()) {
9606 static_cast<Literal*
>(arguments->
at(kArrayIdArg))->value();
9607 if (!value->IsSmi()) {
9613 int array_id = Smi::cast(*value)->value();
9616 if (!arguments->
at(kBufferArg)->IsNullLiteral()) {
9623 HValue* byte_offset;
9624 bool is_zero_byte_offset;
9626 if (arguments->
at(kByteOffsetArg)->IsLiteral()
9628 *
static_cast<Literal*
>(arguments->
at(kByteOffsetArg))->
value()) {
9629 byte_offset = Add<HConstant>(
static_cast<int32_t>(0));
9630 is_zero_byte_offset =
true;
9633 byte_offset =
Pop();
9634 is_zero_byte_offset =
false;
9639 HValue* byte_length =
Pop();
9641 NoObservableSideEffectsScope
scope(
this);
9642 IfBuilder byte_offset_smi(
this);
9644 if (!is_zero_byte_offset) {
9645 byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
9646 byte_offset_smi.Then();
9651 size_t element_size = 1;
9658 &external_elements_kind,
9659 &fixed_elements_kind,
9664 BuildArrayBufferViewInitialization<JSTypedArray>(
9665 obj, buffer, byte_offset, byte_length);
9668 HInstruction* length = AddUncasted<HDiv>(byte_length,
9669 Add<HConstant>(
static_cast<int32_t>(element_size)));
9671 Add<HStoreNamedField>(obj,
9672 HObjectAccess::ForJSTypedArrayLength(),
9676 if (buffer !=
NULL) {
9678 array_type, is_zero_byte_offset, buffer, byte_offset, length);
9680 isolate(), array_type, external_elements_kind);
9683 DCHECK(is_zero_byte_offset);
9685 array_type, element_size, fixed_elements_kind,
9686 byte_length, length);
9688 Add<HStoreNamedField>(
9689 obj, HObjectAccess::ForElementsPointer(), elements);
9692 if (!is_zero_byte_offset) {
9693 byte_offset_smi.Else();
9701 Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength);
9704 byte_offset_smi.End();
9708 void HOptimizedGraphBuilder::GenerateMaxSmi(CallRuntime* expr) {
9709 DCHECK(expr->arguments()->length() == 0);
9715 void HOptimizedGraphBuilder::GenerateTypedArrayMaxSizeInHeap(
9716 CallRuntime* expr) {
9717 DCHECK(expr->arguments()->length() == 0);
9718 HConstant* result = New<HConstant>(
static_cast<int32_t>(
9719 FLAG_typed_array_max_size_in_heap));
9724 void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength(
9725 CallRuntime* expr) {
9726 DCHECK(expr->arguments()->length() == 1);
9728 HValue* buffer =
Pop();
9729 HInstruction* result = New<HLoadNamedField>(
9731 static_cast<HValue*
>(
NULL),
9732 HObjectAccess::ForJSArrayBufferByteLength());
9737 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength(
9738 CallRuntime* expr) {
9739 DCHECK(expr->arguments()->length() == 1);
9741 HValue* buffer =
Pop();
9742 HInstruction* result = New<HLoadNamedField>(
9744 static_cast<HValue*
>(
NULL),
9745 HObjectAccess::ForJSArrayBufferViewByteLength());
9750 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset(
9751 CallRuntime* expr) {
9752 DCHECK(expr->arguments()->length() == 1);
9754 HValue* buffer =
Pop();
9755 HInstruction* result = New<HLoadNamedField>(
9757 static_cast<HValue*
>(
NULL),
9758 HObjectAccess::ForJSArrayBufferViewByteOffset());
9763 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength(
9764 CallRuntime* expr) {
9765 DCHECK(expr->arguments()->length() == 1);
9767 HValue* buffer =
Pop();
9768 HInstruction* result = New<HLoadNamedField>(
9770 static_cast<HValue*
>(
NULL),
9771 HObjectAccess::ForJSTypedArrayLength());
9776 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
9777 DCHECK(!HasStackOverflow());
9780 if (expr->is_jsruntime()) {
9781 return Bailout(kCallToAJavaScriptRuntimeFunction);
9784 const Runtime::Function*
function = expr->function();
9789 DCHECK(expr->name()->length() > 0);
9790 DCHECK(expr->name()->Get(0) ==
'_');
9792 int lookup_index =
static_cast<int>(
function->function_id) -
9794 DCHECK(lookup_index >= 0);
9795 DCHECK(
static_cast<size_t>(lookup_index) <
9800 (this->*generator)(expr);
9803 Handle<String>
name = expr->name();
9804 int argument_count = expr->arguments()->length();
9807 HCallRuntime* call = New<HCallRuntime>(
name,
function,
9814 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
9815 DCHECK(!HasStackOverflow());
9818 switch (expr->op()) {
9829 Property* prop = expr->expression()->AsProperty();
9830 VariableProxy* proxy = expr->expression()->AsVariableProxy();
9840 HInstruction* instr = New<HInvokeFunction>(
function, 3);
9842 }
else if (proxy !=
NULL) {
9845 Bailout(kDeleteWithGlobalVariable);
9851 ?
graph()->GetConstantTrue()
9852 :
graph()->GetConstantFalse();
9855 Bailout(kDeleteWithNonGlobalVariable);
9895 HBasicBlock* materialize_false =
graph()->CreateBasicBlock();
9896 HBasicBlock* materialize_true =
graph()->CreateBasicBlock();
9901 if (materialize_false->HasPredecessor()) {
9902 materialize_false->SetJoinId(expr->MaterializeFalseId());
9906 materialize_false =
NULL;
9909 if (materialize_true->HasPredecessor()) {
9910 materialize_true->SetJoinId(expr->MaterializeTrueId());
9914 materialize_true =
NULL;
9918 CreateJoin(materialize_false, materialize_true, expr->id());
9925 bool returns_original_input,
9926 CountOperation* expr) {
9933 if (returns_original_input) {
9938 HInstruction* number_input = AddUncasted<HForceRepresentation>(
Pop(), rep);
9949 HConstant* delta = (expr->op() == Token::INC)
9950 ?
graph()->GetConstant1()
9951 :
graph()->GetConstantMinus1();
9953 if (instr->IsAdd()) {
9954 HAdd* add = HAdd::cast(instr);
9955 add->set_observed_input_representation(1, rep);
9971 EffectContext for_effect(
this);
9979 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
9980 DCHECK(!HasStackOverflow());
9985 VariableProxy* proxy = target->AsVariableProxy();
9986 Property* prop = target->AsProperty();
9987 if (proxy ==
NULL && prop ==
NULL) {
9988 return Bailout(kInvalidLhsInCountOperation);
9994 bool returns_original_input =
9996 HValue* input =
NULL;
9997 HValue* after =
NULL;
9999 if (proxy !=
NULL) {
10000 Variable* var = proxy->var();
10002 return Bailout(kUnsupportedCountOperationWithConst);
10009 input = returns_original_input ?
Top() :
Pop();
10012 switch (var->location()) {
10016 expr->AssignmentId());
10033 for (
int i = 0;
i < count; ++
i) {
10035 return Bailout(kAssignmentToParameterInArgumentsObject);
10042 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
10043 HStoreContextSlot* instr = Add<HStoreContextSlot>(
context, var->index(),
10045 if (instr->HasObservableSideEffects()) {
10052 return Bailout(kLookupVariableInCountOperation);
10055 Drop(returns_original_input ? 2 : 1);
10061 if (returns_original_input)
Push(
graph()->GetConstantUndefined());
10064 HValue*
object =
Top();
10066 HValue* key =
NULL;
10067 if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
10076 if (returns_original_input) {
10082 expr, prop, expr->id(), expr->AssignmentId(),
object, key, after));
10087 return BuildStore(expr, prop, expr->id(), expr->AssignmentId());
10094 if (string->IsConstant() && index->IsConstant()) {
10095 HConstant* c_string = HConstant::cast(
string);
10096 HConstant* c_index = HConstant::cast(index);
10097 if (c_string->HasStringValue() && c_index->HasNumberValue()) {
10098 int32_t i = c_index->NumberValueAsInteger32();
10100 if (i < 0 || i >= s->length()) {
10103 return New<HConstant>(s->Get(
i));
10108 return New<HStringCharCodeAt>(
string, index);
10115 HValue* const32_minus_sa) {
10116 if (sa->IsConstant() && const32_minus_sa->IsConstant()) {
10117 const HConstant* c1 = HConstant::cast(sa);
10118 const HConstant* c2 = HConstant::cast(const32_minus_sa);
10119 return c1->HasInteger32Value() && c2->HasInteger32Value() &&
10120 (c1->Integer32Value() + c2->Integer32Value() == 32);
10122 if (!const32_minus_sa->IsSub())
return false;
10123 HSub* sub = HSub::cast(const32_minus_sa);
10124 return sub->left()->EqualsInteger32Constant(32) && sub->right() == sa;
10135 HValue** shift_amount) {
10138 if (left->IsShl() && right->IsShr()) {
10139 shl = HShl::cast(left);
10140 shr = HShr::cast(right);
10141 }
else if (left->IsShr() && right->IsShl()) {
10142 shl = HShl::cast(right);
10143 shr = HShr::cast(left);
10147 if (shl->left() != shr->left())
return false;
10153 *operand= shr->left();
10154 *shift_amount = shr->right();
10160 if (right->IsConstant()) {
10161 HConstant* right_const = HConstant::cast(right);
10162 if (right_const->HasInteger32Value() &&
10163 (right_const->Integer32Value() & 0x1f) != 0) {
10173 if (expected->
Is(Type::SignedSmall())) {
10176 if (expected->
Is(Type::Signed32())) {
10177 return AddUncasted<HForceRepresentation>(number,
10185 if (value->IsConstant()) {
10186 HConstant* constant = HConstant::cast(value);
10189 *expected = Type::Number(
zone());
10197 NoObservableSideEffectsScope no_effects(
this);
10199 Type* expected_type = *expected;
10202 Type* expected_obj =
10204 Type* expected_number =
10225 BinaryOperation* expr,
10229 Type* left_type = expr->left()->bounds().lower;
10230 Type* right_type = expr->right()->bounds().lower;
10231 Type* result_type = expr->bounds().lower;
10232 Maybe<int> fixed_right_arg = expr->fixed_right_arg();
10235 HAllocationMode allocation_mode;
10236 if (FLAG_allocation_site_pretenuring && !allocation_site.
is_null()) {
10237 allocation_mode = HAllocationMode(allocation_site);
10241 expr->op(), left, right, left_type, right_type, result_type,
10242 fixed_right_arg, allocation_mode);
10267 HAllocationMode allocation_mode) {
10273 (left_type->
Maybe(Type::String()) ||
10274 left_type->
Maybe(Type::Receiver()) ||
10275 right_type->
Maybe(Type::String()) ||
10276 right_type->
Maybe(Type::Receiver()));
10279 Add<HDeoptimize>(
"Insufficient type feedback for LHS of binary operation",
10283 left_type = Type::Any(
zone());
10290 Add<HDeoptimize>(
"Insufficient type feedback for RHS of binary operation",
10292 right_type = Type::Any(
zone());
10300 (left_type->
Is(Type::String()) || right_type->
Is(Type::String()))) {
10302 if (left_type->
Is(Type::String())) {
10307 if (right_type->
Is(Type::String())) {
10312 if (left_type->
Is(Type::Number())) {
10313 DCHECK(right_type->
Is(Type::String()));
10315 }
else if (!left_type->
Is(Type::String())) {
10316 DCHECK(right_type->
Is(Type::String()));
10318 Add<HPushArguments>(left, right);
10319 return AddUncasted<HInvokeFunction>(
function, 2);
10323 if (right_type->
Is(Type::Number())) {
10324 DCHECK(left_type->
Is(Type::String()));
10326 }
else if (!right_type->
Is(Type::String())) {
10327 DCHECK(left_type->
Is(Type::String()));
10329 Add<HPushArguments>(left, right);
10330 return AddUncasted<HInvokeFunction>(
function, 2);
10334 if (left->IsConstant() &&
10335 HConstant::cast(left)->HasStringValue() &&
10336 HConstant::cast(left)->StringValue()->length() == 0) {
10339 if (right->IsConstant() &&
10340 HConstant::cast(right)->HasStringValue() &&
10341 HConstant::cast(right)->StringValue()->length() == 0) {
10346 if (!allocation_mode.feedback_site().is_null()) {
10356 if ((
graph()->info()->IsStub() &&
10357 allocation_mode.CreateAllocationMementos()) ||
10358 (left->IsConstant() &&
10359 HConstant::cast(left)->HasStringValue() &&
10360 HConstant::cast(left)->StringValue()->length() + 1 >=
10362 (right->IsConstant() &&
10363 HConstant::cast(right)->HasStringValue() &&
10364 HConstant::cast(right)->StringValue()->length() + 1 >=
10370 return AddUncasted<HStringAdd>(
10371 left, right, allocation_mode.GetPretenureMode(),
10375 if (
graph()->info()->IsStub()) {
10382 bool is_non_primitive = (left_rep.
IsTagged() && !left_rep.
IsSmi()) ||
10389 if (
graph()->info()->IsStub() && is_non_primitive) {
10391 Add<HPushArguments>(left, right);
10392 instr = AddUncasted<HInvokeFunction>(
function, 2);
10396 instr = AddUncasted<HAdd>(left, right);
10399 instr = AddUncasted<HSub>(left, right);
10402 instr = AddUncasted<HMul>(left, right);
10407 HConstant* fixed_right = Add<HConstant>(
10408 static_cast<int>(fixed_right_arg.
value));
10409 IfBuilder if_same(
this);
10412 if_same.ElseDeopt(
"Unexpected RHS of binary operation");
10413 right = fixed_right;
10415 instr = AddUncasted<HMod>(left, right);
10419 instr = AddUncasted<HDiv>(left, right);
10421 case Token::BIT_XOR:
10422 case Token::BIT_AND:
10423 instr = AddUncasted<HBitwise>(op, left, right);
10425 case Token::BIT_OR: {
10426 HValue* operand, *shift_amount;
10427 if (left_type->
Is(Type::Signed32()) &&
10428 right_type->
Is(Type::Signed32()) &&
10430 instr = AddUncasted<HRor>(operand, shift_amount);
10432 instr = AddUncasted<HBitwise>(op, left, right);
10437 instr = AddUncasted<HSar>(left, right);
10440 instr = AddUncasted<HShr>(left, right);
10441 if (FLAG_opt_safe_uint32_operations && instr->IsShr() &&
10443 graph()->RecordUint32Instruction(instr);
10447 instr = AddUncasted<HShl>(left, right);
10454 if (instr->IsBinaryOperation()) {
10459 if (
graph()->info()->IsStub()) {
10463 if (left->IsForceRepresentation()) {
10467 if (right->IsForceRepresentation()) {
10479 if (expr->op() != Token::EQ_STRICT)
return false;
10480 CallRuntime* call = expr->left()->AsCallRuntime();
10481 if (call ==
NULL)
return false;
10482 Literal* literal = expr->right()->AsLiteral();
10483 if (literal ==
NULL)
return false;
10484 if (!literal->value()->IsString())
return false;
10488 DCHECK(call->arguments()->length() == 1);
10493 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
10494 DCHECK(!HasStackOverflow());
10497 switch (expr->op()) {
10513 Visit(expr->right());
10518 bool is_logical_and = expr->op() ==
Token::AND;
10522 HBasicBlock* eval_right =
graph()->CreateBasicBlock();
10523 if (is_logical_and) {
10535 if (eval_right->HasPredecessor()) {
10536 eval_right->SetJoinId(expr->RightId());
10538 Visit(expr->right());
10547 if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) {
10552 if (is_logical_and == expr->left()->ToBooleanIsTrue()) {
10560 HBasicBlock* empty_block =
graph()->CreateBasicBlock();
10561 HBasicBlock* eval_right =
graph()->CreateBasicBlock();
10563 HBranch* test = is_logical_and
10564 ? New<HBranch>(left_value, expected, eval_right, empty_block)
10565 : New<HBranch>(left_value, expected, empty_block, eval_right);
10572 HBasicBlock* join_block =
10582 HBasicBlock* empty_block =
graph()->CreateBasicBlock();
10583 HBasicBlock* right_block =
graph()->CreateBasicBlock();
10584 if (is_logical_and) {
10596 if (empty_block->HasPredecessor()) {
10597 empty_block->SetJoinId(expr->id());
10599 empty_block =
NULL;
10602 if (right_block->HasPredecessor()) {
10603 right_block->SetJoinId(expr->RightId());
10608 right_block =
NULL;
10611 HBasicBlock* join_block =
10612 CreateJoin(empty_block, right_block, expr->id());
10630 if (FLAG_hydrogen_track_positions && result->IsBinaryOperation()) {
10646 HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
10655 return op == Token::EQ_STRICT &&
10656 ((left->IsConstant() &&
10657 HConstant::cast(left)->handle(
isolate)->IsBoolean()) ||
10658 (right->IsConstant() &&
10659 HConstant::cast(right)->handle(
isolate)->IsBoolean()));
10663 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
10664 DCHECK(!HasStackOverflow());
10673 Expression* sub_expr =
NULL;
10675 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
10678 if (expr->IsLiteralCompareUndefined(&sub_expr,
isolate())) {
10681 if (expr->IsLiteralCompareNull(&sub_expr)) {
10686 CallRuntime* call = expr->left()->AsCallRuntime();
10687 DCHECK(call->arguments()->length() == 1);
10689 HValue* value =
Pop();
10690 Literal* literal = expr->right()->AsLiteral();
10692 HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
10696 Type* left_type = expr->left()->bounds().lower;
10697 Type* right_type = expr->right()->bounds().lower;
10698 Type* combined_type = expr->combined_type();
10705 HValue* right =
Pop();
10706 HValue* left =
Pop();
10710 HCompareObjectEqAndBranch* result =
10711 New<HCompareObjectEqAndBranch>(left, right);
10715 if (op == Token::INSTANCEOF) {
10720 VariableProxy* proxy = expr->right()->AsVariableProxy();
10721 bool global_function = (proxy !=
NULL) && proxy->var()->IsUnallocated();
10723 Handle<String>
name = proxy->name();
10724 Handle<GlobalObject> global(
current_info()->global_object());
10725 LookupIterator it(global,
name, LookupIterator::OWN_SKIP_INTERCEPTOR);
10727 if (it.IsFound() && value->IsJSFunction()) {
10731 if (!
isolate()->heap()->InNewSpace(*candidate)) {
10732 target = candidate;
10739 if (target.is_null()) {
10740 HInstanceOf* result = New<HInstanceOf>(left, right);
10743 Add<HCheckValue>(right, target);
10744 HInstanceOfKnownGlobal* result =
10745 New<HInstanceOfKnownGlobal>(left, target);
10753 Add<HPushArguments>(left, right);
10756 HInstruction* result = New<HInvokeFunction>(
function, 2);
10764 op, left, right, left_type, right_type, combined_type,
10767 push_behavior, expr->id());
10768 if (compare ==
NULL)
return;
10779 Type* combined_type,
10787 Add<HDeoptimize>(
"Insufficient type feedback for combined type "
10788 "of binary operation",
10790 combined_type = left_type = right_type = Type::Any(
zone());
10797 if (combined_type->
Is(Type::Receiver())) {
10801 if ((left->IsConstant() &&
10802 HConstant::cast(left)->HasNumberValue()) ||
10803 (right->IsConstant() &&
10804 HConstant::cast(right)->HasNumberValue())) {
10805 Add<HDeoptimize>(
"Type mismatch between feedback and constant",
10808 return New<HBranch>(
graph()->GetConstantTrue());
10811 HValue* operand_to_check =
10812 left->
block()->block_id() < right->
block()->block_id() ? left : right;
10813 if (combined_type->
IsClass()) {
10817 New<HCompareObjectEqAndBranch>(left, right);
10818 if (FLAG_hydrogen_track_positions) {
10825 Add<HCheckInstanceType>(operand_to_check,
10826 HCheckInstanceType::IS_SPEC_OBJECT);
10828 New<HCompareObjectEqAndBranch>(left, right);
10832 Bailout(kUnsupportedNonPrimitiveCompare);
10835 }
else if (combined_type->
Is(Type::InternalizedString()) &&
10839 if ((left->IsConstant() &&
10840 !HConstant::cast(left)->HasInternalizedStringValue()) ||
10841 (right->IsConstant() &&
10842 !HConstant::cast(right)->HasInternalizedStringValue())) {
10843 Add<HDeoptimize>(
"Type mismatch between feedback and constant",
10846 return New<HBranch>(
graph()->GetConstantTrue());
10849 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
10851 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
10853 New<HCompareObjectEqAndBranch>(left, right);
10855 }
else if (combined_type->
Is(Type::String())) {
10857 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
10859 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
10861 New<HStringCompareAndBranch>(left, right, op);
10865 HCompareGeneric* result = Add<HCompareGeneric>(left, right, op);
10866 result->set_observed_input_representation(1, left_rep);
10867 result->set_observed_input_representation(2, right_rep);
10868 if (result->HasObservableSideEffects()) {
10878 HBranch* branch = New<HBranch>(result);
10882 New<HCompareNumericAndBranch>(left, right, op);
10884 if (FLAG_hydrogen_track_positions) {
10896 DCHECK(!HasStackOverflow());
10903 if (expr->op() == Token::EQ_STRICT) {
10905 ?
graph()->GetConstantNull()
10906 :
graph()->GetConstantUndefined();
10908 New<HCompareObjectEqAndBranch>(value, nil_constant);
10913 ? Type::Any(
zone()) : expr->combined_type();
10914 HIfContinuation continuation;
10925 return New<HConstant>(
10928 return New<HThisFunction>();
10936 NoObservableSideEffectsScope no_effects(
this);
10937 InstanceType instance_type = boilerplate_object->map()->instance_type();
10941 ? HType::JSArray() : HType::JSObject();
10942 HValue* object_size_constant = Add<HConstant>(
10943 boilerplate_object->map()->instance_size());
10946 if (FLAG_allocation_site_pretenuring) {
10947 pretenure_flag = site_context->
current()->GetPretenureMode();
10953 HInstruction*
object = Add<HAllocate>(object_size_constant, type,
10954 pretenure_flag, instance_type, site_context->
current());
10960 HConstant* empty_fixed_array = Add<HConstant>(
10961 isolate()->factory()->empty_fixed_array());
10962 Add<HStoreNamedField>(
object, HObjectAccess::ForElementsPointer(),
10963 empty_fixed_array);
10968 int elements_size = (elements->length() > 0 &&
10969 elements->map() !=
isolate()->
heap()->fixed_cow_array_map()) ?
10970 elements->Size() : 0;
10972 if (pretenure_flag ==
TENURED &&
10973 elements->map() ==
isolate()->
heap()->fixed_cow_array_map() &&
10979 isolate()->factory()->CopyAndTenureFixedCOWArray(
10981 boilerplate_object->set_elements(*elements);
10985 if (elements_size > 0) {
10986 HValue* object_elements_size = Add<HConstant>(elements_size);
10987 InstanceType instance_type = boilerplate_object->HasFastDoubleElements()
10989 object_elements = Add<HAllocate>(
10990 object_elements_size, HType::HeapObject(),
10991 pretenure_flag, instance_type, site_context->
current());
10996 if (object_elements !=
NULL) {
11002 if (boilerplate_object->map()->NumberOfFields() != 0 ||
11003 boilerplate_object->map()->unused_property_fields() > 0) {
11014 DCHECK(boilerplate_object->properties()->length() == 0);
11016 Handle<Map> boilerplate_object_map(boilerplate_object->map());
11021 DCHECK(*properties_field ==
isolate()->heap()->empty_fixed_array());
11022 HInstruction* properties = Add<HConstant>(properties_field);
11023 HObjectAccess access = HObjectAccess::ForPropertiesPointer();
11024 Add<HStoreNamedField>(
object, access, properties);
11026 if (boilerplate_object->IsJSArray()) {
11033 DCHECK(boilerplate_array->length()->IsSmi());
11034 Add<HStoreNamedField>(
object, HObjectAccess::ForArrayLength(
11035 boilerplate_array->GetElementsKind()), length);
11044 DCHECK(boilerplate_object->properties()->length() == 0);
11045 if (object_elements ==
NULL) {
11048 object_elements = Add<HConstant>(elements_field);
11050 Add<HStoreNamedField>(
object, HObjectAccess::ForElementsPointer(),
11060 Handle<Map> boilerplate_map(boilerplate_object->map());
11062 int limit = boilerplate_map->NumberOfOwnDescriptors();
11064 int copied_fields = 0;
11065 for (
int i = 0;
i < limit;
i++) {
11066 PropertyDetails details = descriptors->GetDetails(
i);
11067 if (details.type() !=
FIELD)
continue;
11069 int index = descriptors->GetFieldIndex(
i);
11070 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index);
11077 HObjectAccess access = boilerplate_object->IsJSArray() ?
11078 HObjectAccess::ForJSArrayOffset(property_offset) :
11079 HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
11081 if (value->IsJSObject()) {
11086 site_context->
ExitScope(current_site, value_object);
11087 Add<HStoreNamedField>(
object, access, result);
11100 Add<HAllocate>(heap_number_constant, HType::HeapObject(),
11103 isolate()->factory()->mutable_heap_number_map());
11107 Add<HStoreNamedField>(
11108 double_box, HObjectAccess::ForHeapNumberValue(), double_value);
11109 value_instruction = double_box;
11110 }
else if (representation.
IsSmi()) {
11111 value_instruction = value->IsUninitialized()
11112 ?
graph()->GetConstant0()
11113 : Add<HConstant>(value);
11115 access = access.WithRepresentation(representation);
11117 value_instruction = Add<HConstant>(value);
11120 Add<HStoreNamedField>(
object, access, value_instruction);
11124 int inobject_properties = boilerplate_object->map()->inobject_properties();
11126 Add<HConstant>(
isolate()->factory()->one_pointer_filler_map());
11127 for (
int i = copied_fields;
i < inobject_properties;
i++) {
11128 DCHECK(boilerplate_object->IsJSObject());
11129 int property_offset = boilerplate_object->GetInObjectPropertyOffset(
i);
11130 HObjectAccess access =
11131 HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
11132 Add<HStoreNamedField>(
object, access, value_instruction);
11140 HValue* object_elements,
11142 ElementsKind kind = boilerplate_object->map()->elements_kind();
11143 int elements_length = elements->length();
11144 HValue* object_elements_length = Add<HConstant>(elements_length);
11148 if (elements->IsFixedDoubleArray()) {
11150 }
else if (elements->IsFixedArray()) {
11162 HValue* object_elements) {
11163 HInstruction* boilerplate_elements = Add<HConstant>(elements);
11164 int elements_length = elements->length();
11165 for (
int i = 0;
i < elements_length;
i++) {
11166 HValue* key_constant = Add<HConstant>(
i);
11168 Add<HLoadKeyed>(boilerplate_elements, key_constant,
11171 HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
11172 value_instruction, kind);
11181 HValue* object_elements,
11183 HInstruction* boilerplate_elements = Add<HConstant>(elements);
11184 int elements_length = elements->length();
11186 for (
int i = 0;
i < elements_length;
i++) {
11188 HValue* key_constant = Add<HConstant>(
i);
11189 if (value->IsJSObject()) {
11194 site_context->
ExitScope(current_site, value_object);
11195 Add<HStoreKeyed>(object_elements, key_constant, result, kind);
11198 Add<HLoadKeyed>(boilerplate_elements, key_constant,
11201 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind);
11207 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
11208 DCHECK(!HasStackOverflow());
11216 void HOptimizedGraphBuilder::VisitSuperReference(SuperReference* expr) {
11217 DCHECK(!HasStackOverflow());
11220 return Bailout(kSuperReference);
11227 AstVisitor::VisitDeclarations(declarations);
11235 Add<HDeclareGlobals>(array,
flags);
11241 void HOptimizedGraphBuilder::VisitVariableDeclaration(
11242 VariableDeclaration* declaration) {
11243 VariableProxy* proxy = declaration->proxy();
11245 Variable* variable = proxy->var();
11251 ?
isolate()->factory()->the_hole_value()
11252 :
isolate()->factory()->undefined_value(),
zone());
11263 HValue* value =
graph()->GetConstantHole();
11265 HStoreContextSlot* store = Add<HStoreContextSlot>(
11266 context, variable->
index(), HStoreContextSlot::kNoCheck, value);
11267 if (store->HasObservableSideEffects()) {
11273 return Bailout(kUnsupportedLookupSlotInDeclaration);
11278 void HOptimizedGraphBuilder::VisitFunctionDeclaration(
11279 FunctionDeclaration* declaration) {
11280 VariableProxy* proxy = declaration->proxy();
11281 Variable* variable = proxy->var();
11282 switch (variable->location()) {
11288 if (
function.is_null())
return SetStackOverflow();
11295 HValue* value =
Pop();
11301 HValue* value =
Pop();
11303 HStoreContextSlot* store = Add<HStoreContextSlot>(
11304 context, variable->index(), HStoreContextSlot::kNoCheck, value);
11305 if (store->HasObservableSideEffects()) {
11311 return Bailout(kUnsupportedLookupSlotInDeclaration);
11316 void HOptimizedGraphBuilder::VisitModuleDeclaration(
11317 ModuleDeclaration* declaration) {
11322 void HOptimizedGraphBuilder::VisitImportDeclaration(
11323 ImportDeclaration* declaration) {
11328 void HOptimizedGraphBuilder::VisitExportDeclaration(
11329 ExportDeclaration* declaration) {
11334 void HOptimizedGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) {
11339 void HOptimizedGraphBuilder::VisitModuleVariable(ModuleVariable* module) {
11344 void HOptimizedGraphBuilder::VisitModulePath(ModulePath* module) {
11349 void HOptimizedGraphBuilder::VisitModuleUrl(ModuleUrl* module) {
11354 void HOptimizedGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) {
11361 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) {
11362 DCHECK(call->arguments()->length() == 1);
11364 HValue* value =
Pop();
11365 HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value);
11370 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
11371 DCHECK(call->arguments()->length() == 1);
11373 HValue* value =
Pop();
11374 HHasInstanceTypeAndBranch* result =
11375 New<HHasInstanceTypeAndBranch>(value,
11382 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) {
11383 DCHECK(call->arguments()->length() == 1);
11385 HValue* value =
Pop();
11386 HHasInstanceTypeAndBranch* result =
11392 void HOptimizedGraphBuilder::GenerateIsMinusZero(CallRuntime* call) {
11393 DCHECK(call->arguments()->length() == 1);
11395 HValue* value =
Pop();
11396 HCompareMinusZeroAndBranch* result = New<HCompareMinusZeroAndBranch>(value);
11401 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
11402 DCHECK(call->arguments()->length() == 1);
11404 HValue* value =
Pop();
11405 HHasCachedArrayIndexAndBranch* result =
11406 New<HHasCachedArrayIndexAndBranch>(value);
11411 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) {
11412 DCHECK(call->arguments()->length() == 1);
11414 HValue* value =
Pop();
11415 HHasInstanceTypeAndBranch* result =
11421 void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
11422 DCHECK(call->arguments()->length() == 1);
11424 HValue* value =
Pop();
11425 HHasInstanceTypeAndBranch* result =
11431 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) {
11432 DCHECK(call->arguments()->length() == 1);
11434 HValue* value =
Pop();
11435 HIsObjectAndBranch* result = New<HIsObjectAndBranch>(value);
11440 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
11441 return Bailout(kInlinedRuntimeFunctionIsNonNegativeSmi);
11445 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
11446 DCHECK(call->arguments()->length() == 1);
11448 HValue* value =
Pop();
11449 HIsUndetectableAndBranch* result = New<HIsUndetectableAndBranch>(value);
11454 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
11455 CallRuntime* call) {
11456 return Bailout(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf);
11461 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
11462 DCHECK(call->arguments()->length() == 0);
11466 ?
graph()->GetConstantTrue()
11467 :
graph()->GetConstantFalse();
11477 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
11478 DCHECK(call->arguments()->length() == 0);
11479 HInstruction* result =
NULL;
11481 HInstruction* elements = Add<HArgumentsElements>(
false);
11482 result = New<HArgumentsLength>(elements);
11486 arguments_environment()->parameter_count() - 1;
11487 result = New<HConstant>(argument_count);
11493 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
11494 DCHECK(call->arguments()->length() == 1);
11496 HValue* index =
Pop();
11497 HInstruction* result =
NULL;
11499 HInstruction* elements = Add<HArgumentsElements>(
false);
11500 HInstruction* length = Add<HArgumentsLength>(elements);
11501 HInstruction* checked_index = Add<HBoundsCheck>(index, length);
11502 result = New<HAccessArgumentsAt>(elements, length, checked_index);
11507 HInstruction* elements =
function_state()->arguments_elements();
11509 arguments_environment()->parameter_count() - 1;
11510 HInstruction* length = Add<HConstant>(argument_count);
11511 HInstruction* checked_key = Add<HBoundsCheck>(index, length);
11512 result = New<HAccessArgumentsAt>(elements, length, checked_key);
11519 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) {
11522 return Bailout(kInlinedRuntimeFunctionClassOf);
11526 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) {
11527 DCHECK(call->arguments()->length() == 1);
11529 HValue*
object =
Pop();
11531 IfBuilder if_objectisvalue(
this);
11532 HValue* objectisvalue = if_objectisvalue.If<HHasInstanceTypeAndBranch>(
11534 if_objectisvalue.Then();
11537 Push(Add<HLoadNamedField>(
11538 object, objectisvalue,
11539 HObjectAccess::ForObservableJSObjectOffset(
11543 if_objectisvalue.Else();
11549 if_objectisvalue.End();
11554 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) {
11555 DCHECK(call->arguments()->length() == 2);
11557 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value()));
11559 HValue* date =
Pop();
11560 HDateField* result = New<HDateField>(date, index);
11565 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
11566 CallRuntime* call) {
11567 DCHECK(call->arguments()->length() == 3);
11571 HValue*
string =
Pop();
11572 HValue* value =
Pop();
11573 HValue* index =
Pop();
11581 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
11582 CallRuntime* call) {
11583 DCHECK(call->arguments()->length() == 3);
11587 HValue*
string =
Pop();
11588 HValue* value =
Pop();
11589 HValue* index =
Pop();
11597 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
11598 DCHECK(call->arguments()->length() == 2);
11601 HValue* value =
Pop();
11602 HValue*
object =
Pop();
11605 IfBuilder if_objectisvalue(
this);
11606 if_objectisvalue.If<HHasInstanceTypeAndBranch>(object,
JS_VALUE_TYPE);
11607 if_objectisvalue.Then();
11610 Add<HStoreNamedField>(
object,
11618 if_objectisvalue.Else();
11626 if_objectisvalue.End();
11635 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
11636 DCHECK(call->arguments()->length() == 2);
11639 HValue* index =
Pop();
11640 HValue*
string =
Pop();
11647 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
11648 DCHECK(call->arguments()->length() == 1);
11650 HValue* char_code =
Pop();
11651 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
11657 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
11658 DCHECK(call->arguments()->length() == 2);
11661 HValue* index =
Pop();
11662 HValue*
string =
Pop();
11665 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
11671 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
11672 DCHECK(call->arguments()->length() == 2);
11675 HValue* right =
Pop();
11676 HValue* left =
Pop();
11677 HCompareObjectEqAndBranch* result =
11678 New<HCompareObjectEqAndBranch>(left, right);
11684 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
11685 DCHECK_EQ(2, call->arguments()->length());
11688 HValue* right =
Pop();
11689 HValue* left =
Pop();
11690 HInstruction* result = NewUncasted<HStringAdd>(left, right);
11696 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
11697 DCHECK_EQ(3, call->arguments()->length());
11700 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3);
11706 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) {
11707 DCHECK_EQ(2, call->arguments()->length());
11710 HCallStub* result = New<HCallStub>(CodeStub::StringCompare, 2);
11716 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
11717 DCHECK_EQ(4, call->arguments()->length());
11720 HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4);
11725 void HOptimizedGraphBuilder::GenerateDoubleLo(CallRuntime* call) {
11726 DCHECK_EQ(1, call->arguments()->length());
11728 HValue* value =
Pop();
11729 HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::LOW);
11734 void HOptimizedGraphBuilder::GenerateDoubleHi(CallRuntime* call) {
11735 DCHECK_EQ(1, call->arguments()->length());
11737 HValue* value =
Pop();
11738 HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::HIGH);
11743 void HOptimizedGraphBuilder::GenerateConstructDouble(CallRuntime* call) {
11744 DCHECK_EQ(2, call->arguments()->length());
11747 HValue*
lo =
Pop();
11748 HValue*
hi =
Pop();
11749 HInstruction* result = NewUncasted<HConstructDouble>(
hi,
lo);
11755 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
11756 DCHECK_EQ(3, call->arguments()->length());
11760 HValue* input =
Pop();
11761 HValue* index =
Pop();
11762 HValue* length =
Pop();
11769 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
11770 return Bailout(kInlinedRuntimeFunctionGetFromCache);
11775 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
11776 DCHECK_EQ(1, call->arguments()->length());
11778 HValue* number =
Pop();
11785 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) {
11787 int arg_count = call->arguments()->length() - 1;
11792 HValue*
function =
Pop();
11796 IfBuilder if_is_jsfunction(
this);
11797 if_is_jsfunction.If<HHasInstanceTypeAndBranch>(
function,
JS_FUNCTION_TYPE);
11799 if_is_jsfunction.Then();
11801 HInstruction* invoke_result =
11802 Add<HInvokeFunction>(
function, arg_count);
11804 Push(invoke_result);
11809 if_is_jsfunction.Else();
11811 HInstruction* call_result =
11812 Add<HCallFunction>(
function, arg_count);
11818 if_is_jsfunction.End();
11831 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) {
11832 DCHECK_EQ(2, call->arguments()->length());
11835 HValue* right =
Pop();
11836 HValue* left =
Pop();
11837 HInstruction* result = NewUncasted<HPower>(left, right);
11842 void HOptimizedGraphBuilder::GenerateMathLogRT(CallRuntime* call) {
11843 DCHECK(call->arguments()->length() == 1);
11845 HValue* value =
Pop();
11846 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathLog);
11851 void HOptimizedGraphBuilder::GenerateMathSqrtRT(CallRuntime* call) {
11852 DCHECK(call->arguments()->length() == 1);
11854 HValue* value =
Pop();
11855 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt);
11860 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
11861 DCHECK(call->arguments()->length() == 1);
11863 HValue* value =
Pop();
11864 HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value);
11869 void HOptimizedGraphBuilder::GenerateFastOneByteArrayJoin(CallRuntime* call) {
11870 return Bailout(kInlinedRuntimeFunctionFastOneByteArrayJoin);
11875 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) {
11876 return Bailout(kInlinedRuntimeFunctionGeneratorNext);
11880 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) {
11881 return Bailout(kInlinedRuntimeFunctionGeneratorThrow);
11885 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
11886 CallRuntime* call) {
11887 Add<HDebugBreak>();
11892 void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) {
11893 DCHECK(call->arguments()->length() == 0);
11895 Add<HConstant>(ExternalReference::debug_is_active_address(
isolate()));
11896 HValue* value = Add<HLoadNamedField>(
11897 ref,
static_cast<HValue*
>(
NULL), HObjectAccess::ForExternalUInteger8());
11902 #undef CHECK_BAILOUT
11906 HEnvironment::HEnvironment(HEnvironment* outer,
11908 Handle<JSFunction> closure,
11910 : closure_(closure),
11913 parameter_count_(0),
11914 specials_count_(1),
11920 ast_id_(BailoutId::
None()),
11923 Initialize(declaration_scope->num_parameters() + 1,
11924 declaration_scope->num_stack_slots(), 0);
11928 HEnvironment::HEnvironment(Zone* zone,
int parameter_count)
11929 : values_(0, zone),
11931 parameter_count_(parameter_count),
11932 specials_count_(1),
11938 ast_id_(BailoutId::
None()),
11940 Initialize(parameter_count, 0, 0);
11944 HEnvironment::HEnvironment(
const HEnvironment* other, Zone* zone)
11945 : values_(0, zone),
11947 parameter_count_(0),
11948 specials_count_(0),
11954 ast_id_(other->ast_id()),
11960 HEnvironment::HEnvironment(HEnvironment* outer,
11961 Handle<JSFunction> closure,
11965 : closure_(closure),
11966 values_(arguments, zone),
11967 frame_type_(frame_type),
11968 parameter_count_(arguments),
11969 specials_count_(0),
11975 ast_id_(BailoutId::
None()),
11980 void HEnvironment::Initialize(
int parameter_count,
11982 int stack_height) {
11983 parameter_count_ = parameter_count;
11984 local_count_ = local_count;
11987 int total = parameter_count + specials_count_ + local_count + stack_height;
11988 values_.Initialize(total + 4, zone());
11989 for (
int i = 0;
i < total; ++
i) values_.Add(
NULL, zone());
11993 void HEnvironment::Initialize(
const HEnvironment* other) {
11994 closure_ = other->closure();
11995 values_.AddAll(other->values_, zone());
11996 assigned_variables_.Union(other->assigned_variables_, zone());
11997 frame_type_ = other->frame_type_;
11998 parameter_count_ = other->parameter_count_;
11999 local_count_ = other->local_count_;
12000 if (other->outer_ !=
NULL) outer_ = other->outer_->Copy();
12001 entry_ = other->entry_;
12002 pop_count_ = other->pop_count_;
12003 push_count_ = other->push_count_;
12004 specials_count_ = other->specials_count_;
12005 ast_id_ = other->ast_id_;
12009 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
12010 DCHECK(!block->IsLoopHeader());
12011 DCHECK(values_.length() == other->values_.length());
12013 int length = values_.length();
12014 for (
int i = 0;
i < length; ++
i) {
12015 HValue* value = values_[
i];
12016 if (value !=
NULL && value->IsPhi() && value->block() == block) {
12018 HPhi* phi = HPhi::cast(value);
12020 DCHECK(phi->merged_index() ==
i || !phi->HasMergedIndex());
12021 DCHECK(phi->OperandCount() == block->predecessors()->length());
12022 phi->AddInput(other->values_[
i]);
12023 }
else if (values_[
i] != other->values_[
i]) {
12026 HPhi* phi = block->AddNewPhi(
i);
12027 HValue* old_value = values_[
i];
12028 for (
int j = 0; j < block->predecessors()->length(); j++) {
12029 phi->AddInput(old_value);
12031 phi->AddInput(other->values_[
i]);
12032 this->values_[
i] = phi;
12038 void HEnvironment::Bind(
int index, HValue* value) {
12040 assigned_variables_.Add(index, zone());
12041 values_[index] = value;
12045 bool HEnvironment::HasExpressionAt(
int index)
const {
12046 return index >= parameter_count_ + specials_count_ + local_count_;
12050 bool HEnvironment::ExpressionStackIsEmpty()
const {
12051 DCHECK(length() >= first_expression_index());
12052 return length() == first_expression_index();
12056 void HEnvironment::SetExpressionStackAt(
int index_from_top, HValue* value) {
12057 int count = index_from_top + 1;
12058 int index = values_.length() - count;
12059 DCHECK(HasExpressionAt(index));
12062 if (push_count_ < count) {
12064 pop_count_ += (count - push_count_);
12065 push_count_ = count;
12067 values_[index] = value;
12071 void HEnvironment::Drop(
int count) {
12072 for (
int i = 0;
i < count; ++
i) {
12078 HEnvironment* HEnvironment::Copy()
const {
12079 return new(zone()) HEnvironment(
this, zone());
12083 HEnvironment* HEnvironment::CopyWithoutHistory()
const {
12084 HEnvironment* result = Copy();
12085 result->ClearHistory();
12090 HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header)
const {
12091 HEnvironment* new_env = Copy();
12092 for (
int i = 0;
i < values_.length(); ++
i) {
12093 HPhi* phi = loop_header->AddNewPhi(
i);
12094 phi->AddInput(values_[
i]);
12095 new_env->values_[
i] = phi;
12097 new_env->ClearHistory();
12102 HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
12103 Handle<JSFunction> target,
12105 int arguments)
const {
12106 HEnvironment* new_env =
12107 new(zone()) HEnvironment(outer, target, frame_type,
12108 arguments + 1, zone());
12109 for (
int i = 0;
i <= arguments; ++
i) {
12110 new_env->Push(ExpressionStackAt(arguments -
i));
12112 new_env->ClearHistory();
12117 HEnvironment* HEnvironment::CopyForInlining(
12118 Handle<JSFunction> target,
12120 FunctionLiteral*
function,
12121 HConstant* undefined,
12126 int arity =
function->scope()->num_parameters();
12128 HEnvironment* outer = Copy();
12129 outer->Drop(arguments + 1);
12130 outer->ClearHistory();
12136 outer = CreateStubEnvironment(outer, target,
JS_CONSTRUCT, arguments);
12140 outer = CreateStubEnvironment(outer, target,
JS_GETTER, arguments);
12144 outer = CreateStubEnvironment(outer, target,
JS_SETTER, arguments);
12147 if (arity != arguments) {
12152 HEnvironment* inner =
12153 new(zone()) HEnvironment(outer, function->scope(), target, zone());
12155 for (
int i = 0;
i <= arity; ++
i) {
12156 HValue* push = (
i <= arguments) ?
12157 ExpressionStackAt(arguments -
i) : undefined;
12158 inner->SetValueAt(
i, push);
12160 inner->SetValueAt(arity + 1, context());
12161 for (
int i = arity + 2;
i < inner->length(); ++
i) {
12162 inner->SetValueAt(
i, undefined);
12171 for (
int i = 0;
i < env.length();
i++) {
12172 if (
i == 0) os <<
"parameters\n";
12173 if (
i == env.parameter_count()) os <<
"specials\n";
12174 if (
i == env.parameter_count() + env.specials_count()) os <<
"locals\n";
12175 if (
i == env.parameter_count() + env.specials_count() + env.local_count()) {
12176 os <<
"expressions\n";
12178 HValue* val = env.values()->at(
i);
12191 void HTracer::TraceCompilation(CompilationInfo* info) {
12192 Tag tag(
this,
"compilation");
12193 if (info->IsOptimizing()) {
12195 PrintStringProperty(
"name",
name->ToCString().get());
12197 trace_.Add(
"method \"%s:%d\"\n",
12198 name->ToCString().get(),
12199 info->optimization_id());
12201 CodeStub::Major major_key = info->code_stub()->MajorKey();
12202 PrintStringProperty(
"name", CodeStub::MajorName(major_key,
false));
12203 PrintStringProperty(
"method",
"stub");
12205 PrintLongProperty(
"date",
12210 void HTracer::TraceLithium(
const char*
name, LChunk* chunk) {
12211 DCHECK(!chunk->isolate()->concurrent_recompilation_enabled());
12218 void HTracer::TraceHydrogen(
const char*
name, HGraph* graph) {
12219 DCHECK(!graph->isolate()->concurrent_recompilation_enabled());
12227 Tag tag(
this,
"cfg");
12228 PrintStringProperty(
"name",
name);
12229 const ZoneList<HBasicBlock*>* blocks = graph->blocks();
12230 for (
int i = 0;
i < blocks->length();
i++) {
12231 HBasicBlock* current = blocks->at(
i);
12232 Tag block_tag(
this,
"block");
12233 PrintBlockProperty(
"name", current->block_id());
12234 PrintIntProperty(
"from_bci", -1);
12235 PrintIntProperty(
"to_bci", -1);
12237 if (!current->predecessors()->is_empty()) {
12239 trace_.Add(
"predecessors");
12240 for (
int j = 0; j < current->predecessors()->length(); ++j) {
12241 trace_.Add(
" \"B%d\"", current->predecessors()->at(j)->block_id());
12245 PrintEmptyProperty(
"predecessors");
12248 if (current->end()->SuccessorCount() == 0) {
12249 PrintEmptyProperty(
"successors");
12252 trace_.Add(
"successors");
12253 for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
12254 trace_.Add(
" \"B%d\"", it.Current()->block_id());
12259 PrintEmptyProperty(
"xhandlers");
12263 trace_.Add(
"flags");
12264 if (current->IsLoopSuccessorDominator()) {
12265 trace_.Add(
" \"dom-loop-succ\"");
12267 if (current->IsUnreachable()) {
12268 trace_.Add(
" \"dead\"");
12270 if (current->is_osr_entry()) {
12271 trace_.Add(
" \"osr\"");
12276 if (current->dominator() !=
NULL) {
12277 PrintBlockProperty(
"dominator", current->dominator()->block_id());
12280 PrintIntProperty(
"loop_depth", current->LoopNestingDepth());
12282 if (chunk !=
NULL) {
12283 int first_index = current->first_instruction_index();
12284 int last_index = current->last_instruction_index();
12294 Tag states_tag(
this,
"states");
12295 Tag locals_tag(
this,
"locals");
12296 int total = current->phis()->length();
12297 PrintIntProperty(
"size", current->phis()->length());
12298 PrintStringProperty(
"method",
"None");
12299 for (
int j = 0; j < total; ++j) {
12300 HPhi* phi = current->phis()->at(j);
12303 os << phi->merged_index() <<
" " << NameOf(phi) <<
" " << *phi <<
"\n";
12304 trace_.Add(os.c_str());
12309 Tag HIR_tag(
this,
"HIR");
12310 for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
12311 HInstruction* instruction = it.Current();
12312 int uses = instruction->UseCount();
12315 os <<
"0 " << uses <<
" " << NameOf(instruction) <<
" " << *instruction;
12316 if (FLAG_hydrogen_track_positions &&
12317 instruction->has_position() &&
12318 instruction->position().raw() != 0) {
12319 const HSourcePosition pos = instruction->position();
12321 if (pos.inlining_id() != 0) os << pos.inlining_id() <<
"_";
12322 os << pos.position();
12325 trace_.Add(os.c_str());
12330 if (chunk !=
NULL) {
12331 Tag LIR_tag(
this,
"LIR");
12332 int first_index = current->first_instruction_index();
12333 int last_index = current->last_instruction_index();
12334 if (first_index != -1 && last_index != -1) {
12335 const ZoneList<LInstruction*>* instructions = chunk->instructions();
12336 for (
int i = first_index;
i <= last_index; ++
i) {
12337 LInstruction* linstr = instructions->at(
i);
12338 if (linstr !=
NULL) {
12342 linstr->PrintTo(&trace_);
12344 os <<
" [hir:" << NameOf(linstr->hydrogen_value()) <<
"] <|@\n";
12345 trace_.Add(os.c_str());
12354 void HTracer::TraceLiveRanges(
const char*
name, LAllocator* allocator) {
12355 Tag tag(
this,
"intervals");
12356 PrintStringProperty(
"name",
name);
12358 const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
12359 for (
int i = 0;
i < fixed_d->length(); ++
i) {
12360 TraceLiveRange(fixed_d->at(
i),
"fixed", allocator->zone());
12363 const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
12364 for (
int i = 0;
i < fixed->length(); ++
i) {
12365 TraceLiveRange(fixed->at(
i),
"fixed", allocator->zone());
12368 const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
12369 for (
int i = 0;
i < live_ranges->length(); ++
i) {
12370 TraceLiveRange(live_ranges->at(
i),
"object", allocator->zone());
12375 void HTracer::TraceLiveRange(LiveRange* range,
const char* type,
12377 if (range !=
NULL && !range->IsEmpty()) {
12379 trace_.Add(
"%d %s", range->id(), type);
12380 if (range->HasRegisterAssigned()) {
12381 LOperand* op = range->CreateAssignedOperand(zone);
12382 int assigned_reg = op->index();
12383 if (op->IsDoubleRegister()) {
12384 trace_.Add(
" \"%s\"",
12387 DCHECK(op->IsRegister());
12390 }
else if (range->IsSpilled()) {
12391 LOperand* op = range->TopLevel()->GetSpillOperand();
12392 if (op->IsDoubleStackSlot()) {
12393 trace_.Add(
" \"double_stack:%d\"", op->index());
12395 DCHECK(op->IsStackSlot());
12396 trace_.Add(
" \"stack:%d\"", op->index());
12399 int parent_index = -1;
12400 if (range->IsChild()) {
12401 parent_index = range->parent()->id();
12403 parent_index = range->id();
12405 LOperand* op = range->FirstHint();
12406 int hint_index = -1;
12407 if (op !=
NULL && op->IsUnallocated()) {
12410 trace_.Add(
" %d %d", parent_index, hint_index);
12411 UseInterval* cur_interval = range->first_interval();
12412 while (cur_interval !=
NULL && range->Covers(cur_interval->start())) {
12413 trace_.Add(
" [%d, %d[",
12414 cur_interval->start().Value(),
12415 cur_interval->end().Value());
12416 cur_interval = cur_interval->next();
12419 UsePosition* current_pos = range->first_pos();
12420 while (current_pos !=
NULL) {
12421 if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
12422 trace_.Add(
" %d M", current_pos->pos().Value());
12424 current_pos = current_pos->next();
12427 trace_.Add(
" \"\"\n");
12432 void HTracer::FlushToFile() {
12433 AppendChars(filename_.start(), trace_.ToCString().get(), trace_.length(),
12439 void HStatistics::Initialize(CompilationInfo* info) {
12440 if (info->shared_info().is_null())
return;
12441 source_size_ += info->shared_info()->SourceSize();
12445 void HStatistics::Print(
const char* stats_name) {
12448 "----------------------------------------"
12449 "----------------------------------------\n"
12450 "--- %s timing results:\n"
12451 "----------------------------------------"
12452 "----------------------------------------\n",
12454 base::TimeDelta sum;
12455 for (
int i = 0;
i < times_.length(); ++
i) {
12459 for (
int i = 0;
i < names_.length(); ++
i) {
12461 double ms = times_[
i].InMillisecondsF();
12462 double percent = times_[
i].PercentOf(sum);
12463 PrintF(
" %8.3f ms / %4.1f %% ", ms, percent);
12465 unsigned size = sizes_[
i];
12466 double size_percent =
static_cast<double>(
size) * 100 / total_size_;
12467 PrintF(
" %9u bytes / %4.1f %%\n",
size, size_percent);
12471 "----------------------------------------"
12472 "----------------------------------------\n");
12473 base::TimeDelta total = create_graph_ + optimize_graph_ + generate_code_;
12474 PrintF(
"%33s %8.3f ms / %4.1f %% \n",
"Create graph",
12475 create_graph_.InMillisecondsF(), create_graph_.PercentOf(total));
12476 PrintF(
"%33s %8.3f ms / %4.1f %% \n",
"Optimize graph",
12477 optimize_graph_.InMillisecondsF(), optimize_graph_.PercentOf(total));
12478 PrintF(
"%33s %8.3f ms / %4.1f %% \n",
"Generate and install code",
12479 generate_code_.InMillisecondsF(), generate_code_.PercentOf(total));
12481 "----------------------------------------"
12482 "----------------------------------------\n");
12483 PrintF(
"%33s %8.3f ms %9u bytes\n",
"Total",
12484 total.InMillisecondsF(), total_size_);
12485 PrintF(
"%33s (%.1f times slower than full code gen)\n",
"",
12486 total.TimesOf(full_code_gen_));
12488 double source_size_in_kb =
static_cast<double>(source_size_) / 1024;
12489 double normalized_time = source_size_in_kb > 0
12490 ? total.InMillisecondsF() / source_size_in_kb
12492 double normalized_size_in_kb = source_size_in_kb > 0
12493 ? total_size_ / 1024 / source_size_in_kb
12495 PrintF(
"%33s %8.3f ms %7.3f kB allocated\n",
12496 "Average per kB source", normalized_time, normalized_size_in_kb);
12500 void HStatistics::SaveTiming(
const char*
name, base::TimeDelta time,
12502 total_size_ +=
size;
12503 for (
int i = 0;
i < names_.length(); ++
i) {
12504 if (strcmp(names_[
i],
name) == 0) {
12517 if (ShouldProduceTraceOutput()) {
12518 isolate()->GetHTracer()->TraceHydrogen(
name(),
graph_);
An object reference managed by the v8 garbage collector.
static double nan_value()
static double TimeCurrentMillis()
Handle< AllocationSite > current()
void ExitScope(Handle< AllocationSite > scope_site, Handle< JSObject > object)
Handle< AllocationSite > EnterNewScope()
static AllocationSiteMode GetMode(ElementsKind boilerplate_elements_kind)
static void AddDependentCompilationInfo(Handle< AllocationSite > site, Reason reason, CompilationInfo *info)
virtual void ReturnValue(HValue *value)=0
virtual void ReturnControl(HControlInstruction *instr, BailoutId ast_id)=0
HOptimizedGraphBuilder * owner() const
AstContext(HOptimizedGraphBuilder *owner, Expression::Context kind)
virtual void ReturnContinuation(HIfContinuation *continuation, BailoutId ast_id)=0
HOptimizedGraphBuilder * owner_
virtual void ReturnInstruction(HInstruction *instr, BailoutId ast_id)=0
static void Run(CompilationInfo *info)
static BailoutId Declarations()
static BailoutId FunctionEntry()
static Builtins::JavaScript TokenToJSBuiltin(Token::Value op)
int GetEnvironmentLength() const
void AbortOptimization(BailoutReason reason)
void RetryOptimization(BailoutReason reason)
bool has_global_object() const
void set_this_has_uses(bool has_no_uses)
FunctionLiteral * function() const
void SetAstValueFactory(AstValueFactory *ast_value_factory, bool owned=true)
Handle< JSFunction > closure() const
Isolate * isolate() const
Handle< SharedFunctionInfo > shared_info() const
static bool IsCompileTimeValue(Expression *expression)
static bool EnsureDeoptimizationSupport(CompilationInfo *info)
static Handle< SharedFunctionInfo > BuildFunctionInfo(FunctionLiteral *node, Handle< Script > script, CompilationInfo *outer)
static const int kMinLength
@ kInitialMapChangedGroup
static const int kEnumCacheBridgeIndicesCacheIndex
static const int kEnumCacheBridgeCacheIndex
virtual KeyedAccessStoreMode GetStoreMode()
virtual bool IsMonomorphic()
virtual bool IsPropertyName() const
virtual SmallMapList * GetReceiverTypes()
static const int kAlignedSize
static const int kHeaderSize
static double hole_nan_as_double()
FunctionSorter(int index=0, int ticks=0, int size=0)
static const int kBuiltinsOffset
void set_observed_input_representation(int index, Representation rep)
virtual void initialize_output_representation(Representation observed)
void set_observed_input_representation(Representation left, Representation right)
void SetOperandPositions(Zone *zone, HSourcePosition left_pos, HSourcePosition right_pos)
void FinishExitWithHardDeoptimization(const char *reason)
HEnvironment * environment() const
HValue * BuildAllocateArrayFromLength(JSArrayBuilder *array_builder, HValue *length_argument)
HValue * BuildCheckHeapObject(HValue *object)
HValue * BuildStringAdd(HValue *left, HValue *right, HAllocationMode allocation_mode)
static const int kElementLoopUnrollThreshold
HStoreNamedField * AddStoreMapConstant(HValue *object, Handle< Map > map)
void set_current_block(HBasicBlock *block)
HInstruction * BuildUncheckedMonomorphicElementAccess(HValue *checked_object, HValue *key, HValue *val, bool is_js_array, ElementsKind elements_kind, PropertyAccessType access_type, LoadKeyedHoleMode load_mode, KeyedAccessStoreMode store_mode)
void SetSourcePosition(int position)
HValue * AddLoadJSBuiltin(Builtins::JavaScript builtin)
void AddSimulate(BailoutId id, RemovableSimulate removable=FIXED_SIMULATE)
void GotoNoSimulate(HBasicBlock *from, HBasicBlock *target)
HSourcePosition source_position()
HLoadNamedField * AddLoadElements(HValue *object, HValue *dependency=NULL)
void BuildArrayBufferViewInitialization(HValue *obj, HValue *buffer, HValue *byte_offset, HValue *byte_length)
virtual HValue * context()=0
HAllocate * BuildAllocate(HValue *object_size, HType type, InstanceType instance_type, HAllocationMode allocation_mode)
HInstruction * BuildCheckPrototypeMaps(Handle< JSObject > prototype, Handle< JSObject > holder)
HValue * BuildRegExpConstructResult(HValue *length, HValue *index, HValue *input)
void set_scope(Scope *scope)
HValue * BuildNumberToString(HValue *object, Type *type)
HInstruction * AddLoadStringInstanceType(HValue *string)
HSourcePosition ScriptPositionToSourcePosition(int position)
void Goto(HBasicBlock *from, HBasicBlock *target, FunctionState *state=NULL, bool add_simulate=true)
HInstruction * AddElementAccess(HValue *elements, HValue *checked_key, HValue *val, HValue *dependency, ElementsKind elements_kind, PropertyAccessType access_type, LoadKeyedHoleMode load_mode=NEVER_RETURN_HOLE)
HBasicBlock * CreateBasicBlock(HEnvironment *env)
HValue * BuildBinaryOperation(Token::Value op, HValue *left, HValue *right, Type *left_type, Type *right_type, Type *result_type, Maybe< int > fixed_right_arg, HAllocationMode allocation_mode)
HLoadNamedField * AddLoadArrayLength(HValue *object, ElementsKind kind, HValue *dependency=NULL)
Isolate * isolate() const
HValue * EnforceNumberType(HValue *number, Type *expected)
HInstruction * AddInstruction(HInstruction *instr)
void FinishExitCurrentBlock(HControlInstruction *instruction)
HInstruction * BuildConstantMapCheck(Handle< JSObject > constant)
HBasicBlock * CreateLoopHeaderBlock()
void BuildCompareNil(HValue *value, Type *type, HIfContinuation *continuation)
HValue * BuildCopyElementsOnWrite(HValue *object, HValue *elements, ElementsKind kind, HValue *length)
HValue * TruncateToNumber(HValue *value, Type **expected)
HValue * BuildCheckString(HValue *string)
CompilationInfo * top_info()
bool MatchRotateRight(HValue *left, HValue *right, HValue **operand, HValue **shift_amount)
HInstruction * AddLoadStringLength(HValue *string)
HValue * BuildObjectSizeAlignment(HValue *unaligned_size, int header_size)
HBasicBlock * current_block() const
void AddLeaveInlined(HBasicBlock *block, HValue *return_value, FunctionState *state)
void BuildInitializeElementsHeader(HValue *elements, ElementsKind kind, HValue *capacity)
void FinishCurrentBlock(HControlInstruction *last)
HValue * BuildWrapReceiver(HValue *object, HValue *function)
void set_operand_position(Zone *zone, int index, HSourcePosition pos)
void InsertAfter(HInstruction *previous)
bool LookupInPrototypes()
void GeneralizeRepresentation(Representation r)
SmallMapList * field_maps()
Handle< JSFunction > accessor()
bool CanAccessAsMonomorphic(SmallMapList *types)
Handle< String > name() const
void LoadFieldMaps(Handle< Map > map)
bool CanAccessMonomorphic()
bool LoadResult(Handle< Map > map)
Handle< Object > constant()
Handle< JSObject > holder()
Handle< Object > constant_
bool IsTransition() const
bool IsCompatible(PropertyAccessInfo *other)
Handle< JSFunction > accessor_
Handle< Map > transition()
Handle< JSObject > api_holder_
bool GetJSObjectFieldAccess(HObjectAccess *access)
static const InlineFunctionGenerator kInlineFunctionGenerators[]
bool TryInlineBuiltinMethodCall(Call *expr, HValue *receiver, Handle< Map > receiver_map)
PushBeforeSimulateBehavior
@ NO_PUSH_BEFORE_SIMULATE
HBasicBlock * BuildLoopEntry()
HInstruction * BuildFastLiteral(Handle< JSObject > boilerplate_object, AllocationSiteUsageContext *site_context)
static const int kUnlimitedMaxInlinedNodes
bool TryInlineApiMethodCall(Call *expr, HValue *receiver, SmallMapList *receiver_types)
static const int kMaxStorePolymorphism
void HandleLiteralCompareTypeof(CompareOperation *expr, Expression *sub_expr, Handle< String > check)
void VisitForControl(Expression *expr, HBasicBlock *true_block, HBasicBlock *false_block)
HValue * BuildBinaryOperation(BinaryOperation *expr, HValue *left, HValue *right, PushBeforeSimulateBehavior push_sim_result)
HBasicBlock * CreateLoop(IterationStatement *statement, HBasicBlock *loop_entry, HBasicBlock *body_exit, HBasicBlock *loop_successor, HBasicBlock *break_block)
HInstruction * BuildIncrement(bool returns_original_input, CountOperation *expr)
HInstruction * BuildNamedAccess(PropertyAccessType access, BailoutId ast_id, BailoutId reutrn_id, Expression *expr, HValue *object, Handle< String > name, HValue *value, bool is_uninitialized=false)
HValue * BuildAllocateFixedTypedArray(ExternalArrayType array_type, size_t element_size, ElementsKind fixed_elements_kind, HValue *byte_length, HValue *length)
HInstruction * NewArgumentAdaptorCall(HValue *fun, HValue *context, int argument_count, HValue *expected_param_count)
void VisitNot(UnaryOperation *expr)
HInstruction * BuildMonomorphicAccess(PropertyAccessInfo *info, HValue *object, HValue *checked_object, HValue *value, BailoutId ast_id, BailoutId return_id, bool can_inline_accessor=true)
void HandleLiteralCompareNil(CompareOperation *expr, Expression *sub_expr, NilValue nil)
void(HOptimizedGraphBuilder::* InlineFunctionGenerator)(CallRuntime *call)
HBasicBlock * CreateJoin(HBasicBlock *first, HBasicBlock *second, BailoutId join_id)
void ClearInlinedTestContext()
TestContext * inlined_test_context() const
HCheckMaps * AddCheckMap(HValue *object, Handle< Map > map)
void VisitComma(BinaryOperation *expr)
void BuildEmitFixedArray(Handle< FixedArrayBase > elements, ElementsKind kind, HValue *object_elements, AllocationSiteUsageContext *site_context)
void VisitForTypeOf(Expression *expr)
HValue * BuildArrayIndexOf(HValue *receiver, HValue *search_element, ElementsKind kind, ArrayIndexOfMode mode)
AstContext * call_context() const
HInstruction * BuildStringCharCodeAt(HValue *string, HValue *index)
static const int kMaxCallPolymorphism
HOptimizedGraphBuilder(CompilationInfo *info)
void BuildInitElementsInObjectHeader(Handle< JSObject > boilerplate_object, HInstruction *object, HInstruction *object_elements)
HInstruction * BuildNamedGeneric(PropertyAccessType access, Expression *expr, HValue *object, Handle< String > name, HValue *value, bool is_uninitialized=false)
void HandleGlobalVariableAssignment(Variable *var, HValue *value, BailoutId ast_id)
friend class FunctionState
BreakAndContinueScope * break_scope() const
FunctionState initial_function_state_
bool TryInline(Handle< JSFunction > target, int arguments_count, HValue *implicit_return_value, BailoutId ast_id, BailoutId return_id, InliningKind inlining_kind, HSourcePosition position)
void VisitExpressions(ZoneList< Expression * > *exprs)
Type * ToType(Handle< Map > map)
bool IsCallArrayInlineable(int argument_count, Handle< AllocationSite > site)
AstContext * ast_context() const
HValue * BuildAllocateExternalElements(ExternalArrayType array_type, bool is_zero_byte_offset, HValue *buffer, HValue *byte_offset, HValue *length)
void BuildArrayCall(Expression *expr, int arguments_count, HValue *function, Handle< AllocationSite > cell)
bool TryInlineApply(Handle< JSFunction > function, Call *expr, int arguments_count)
bool TryInlineApiFunctionCall(Call *expr, HValue *receiver)
static const int kMaxLoadPolymorphism
CompilationInfo * current_info() const
bool TryArgumentsAccess(Property *expr)
void BuildEmitFixedDoubleArray(Handle< FixedArrayBase > elements, ElementsKind kind, HValue *object_elements)
HInstruction * NewPlainFunctionCall(HValue *fun, int argument_count, bool pass_argument_count)
Handle< JSFunction > array_function()
bool TryInlineConstruct(CallNew *expr, HValue *implicit_return_value)
HInstruction * BuildCallConstantFunction(Handle< JSFunction > target, int argument_count)
void SetUpScope(Scope *scope)
void PushArgumentsFromEnvironment(int count)
virtual void VisitStatements(ZoneList< Statement * > *statements) OVERRIDE
void HandleCompoundAssignment(Assignment *expr)
bool TryHandleArrayCall(Call *expr, HValue *function)
bool TryCallApply(Call *expr)
HValue * ImplicitReceiverFor(HValue *function, Handle< JSFunction > target)
bool TryInlineSetter(Handle< JSFunction > setter, Handle< Map > receiver_map, BailoutId id, BailoutId assignment_id, HValue *implicit_return_value)
void VisitDeclarations(ZoneList< Declaration * > *declarations)
bool TryInlineApiGetter(Handle< JSFunction > function, Handle< Map > receiver_map, BailoutId ast_id)
static const int kUnlimitedMaxInlinedNodesCumulative
GlobalPropertyAccess LookupGlobalProperty(Variable *var, LookupIterator *it, PropertyAccessType access_type)
void BindIfLive(Variable *var, HValue *value)
void set_ast_context(AstContext *context)
static const int kMaxFastLiteralProperties
HValue * HandleKeyedElementAccess(HValue *obj, HValue *key, HValue *val, Expression *expr, BailoutId ast_id, BailoutId return_id, PropertyAccessType access_type, bool *has_side_effects)
bool TryInlineCall(Call *expr)
FunctionState * function_state_
virtual bool BuildGraph() OVERRIDE
ZoneList< Handle< Object > > globals_
HValue * BuildContextChainWalk(Variable *var)
StrictMode function_strict_mode()
bool TryHandleArrayCallNew(CallNew *expr, HValue *function)
FunctionState * function_state() const
HInstruction * BuildMonomorphicElementAccess(HValue *object, HValue *key, HValue *val, HValue *dependency, Handle< Map > map, PropertyAccessType access_type, KeyedAccessStoreMode store_mode)
void VisitDelete(UnaryOperation *expr)
HControlInstruction * BuildCompareInstruction(Token::Value op, HValue *left, HValue *right, Type *left_type, Type *right_type, Type *combined_type, HSourcePosition left_position, HSourcePosition right_position, PushBeforeSimulateBehavior push_sim_result, BailoutId bailout_id)
void VisitArithmeticExpression(BinaryOperation *expr)
void BuildLoad(Property *property, BailoutId ast_id)
HBasicBlock * function_return() const
LoadKeyedHoleMode BuildKeyedHoleMode(Handle< Map > map)
bool TryInlineGetter(Handle< JSFunction > getter, Handle< Map > receiver_map, BailoutId ast_id, BailoutId return_id)
bool TryInlineApiSetter(Handle< JSFunction > function, Handle< Map > receiver_map, BailoutId ast_id)
void BuildStoreForEffect(Expression *expression, Property *prop, BailoutId ast_id, BailoutId return_id, HValue *object, HValue *key, HValue *value)
void BuildEmitInObjectProperties(Handle< JSObject > boilerplate_object, HInstruction *object, AllocationSiteUsageContext *site_context, PretenureFlag pretenure_flag)
HValue * LookupAndMakeLive(Variable *var)
void VisitLogicalExpression(BinaryOperation *expr)
void HandlePolymorphicCallNamed(Call *expr, HValue *receiver, SmallMapList *types, Handle< String > name)
HInstruction * BuildStoreNamedField(PropertyAccessInfo *info, HValue *checked_object, HValue *value)
HInstruction * TryBuildConsolidatedElementLoad(HValue *object, HValue *key, HValue *val, SmallMapList *maps)
HInstruction * BuildKeyedGeneric(PropertyAccessType access_type, Expression *expr, HValue *object, HValue *key, HValue *value)
void TraceInline(Handle< JSFunction > target, Handle< JSFunction > caller, const char *failure_reason)
HValue * HandlePolymorphicElementAccess(Expression *expr, HValue *object, HValue *key, HValue *val, SmallMapList *maps, PropertyAccessType access_type, KeyedAccessStoreMode store_mode, bool *has_side_effects)
void VisitVoid(UnaryOperation *expr)
int InliningAstSize(Handle< JSFunction > target)
void HandlePolymorphicNamedFieldAccess(PropertyAccessType access_type, Expression *expr, BailoutId ast_id, BailoutId return_id, HValue *object, HValue *value, SmallMapList *types, Handle< String > name)
bool TryInlineBuiltinFunctionCall(Call *expr)
bool TryInlineApiCall(Handle< JSFunction > function, HValue *receiver, SmallMapList *receiver_maps, int argc, BailoutId ast_id, ApiCallType call_type)
void VisitLoopBody(IterationStatement *stmt, HBasicBlock *loop_entry)
static const int kUnlimitedMaxInlinedSourceSize
HOsrBuilder * osr() const
HInstruction * PreProcessCall(Instruction *call)
HInstruction * BuildLoadNamedField(PropertyAccessInfo *info, HValue *checked_object)
void VisitForEffect(Expression *expr)
HInstruction * BuildThisFunction()
void BuildInlinedCallArray(Expression *expression, int argument_count, Handle< AllocationSite > site)
void VisitForValue(Expression *expr, ArgumentsAllowedFlag flag=ARGUMENTS_NOT_ALLOWED)
void PushLoad(Property *property, HValue *object, HValue *key)
static const int kMaxFastLiteralDepth
void VisitTypeof(UnaryOperation *expr)
void HandlePropertyAssignment(Assignment *expr)
void BuildEmitElements(Handle< JSObject > boilerplate_object, Handle< FixedArrayBase > elements, HValue *object_elements, AllocationSiteUsageContext *site_context)
void Bind(Variable *var, HValue *value)
HBasicBlock * JoinContinue(IterationStatement *statement, HBasicBlock *exit_block, HBasicBlock *continue_block)
void EnsureArgumentsArePushedForAccess()
void BuildEmitObjectHeader(Handle< JSObject > boilerplate_object, HInstruction *object)
void Bailout(BailoutReason reason)
void BuildStore(Expression *expression, Property *prop, BailoutId ast_id, BailoutId return_id, bool is_uninitialized=false)
void AddCheckPrototypeMaps(Handle< JSObject > holder, Handle< Map > receiver_map)
HBasicBlock * BuildOsrLoopEntry(IterationStatement *statement)
bool HasOsrEntryAt(IterationStatement *statement)
static HSourcePosition Unknown()
static HValue * cast(HValue *value)
bool Equals(HValue *other)
void ClearAllSideEffects()
bool HasObservableSideEffects() const
void set_type(HType new_type)
HBasicBlock * block() const
int32_t GetInteger32Constant()
void ChangeRepresentation(Representation r)
bool EqualsInteger32Constant(int32_t value)
bool HasMonomorphicJSObjectType()
void ClearDependsOnFlag(GVNFlag f)
void CopyFlag(Flag f, HValue *other)
bool IsInteger32Constant()
virtual Handle< Map > GetMonomorphicJSObjectMap()
bool CheckFlag(Flag f) const
@ kHasNoObservableSideEffects
@ kFlexibleRepresentation
static Handle< T > cast(Handle< S > that)
static Handle< T > null()
static const int kMapOffset
bool InNewSpace(Object *object)
static JSFunction * GetRootConstructor(TypeClass *type, Context *native_context)
Handle< Context > native_context()
bool has_pending_exception()
virtual BailoutId ContinueId() const =0
virtual BailoutId StackCheckId() const =0
static bool IsReadOnlyLengthDescriptor(Handle< Map > jsarray_map)
static int OffsetOfFunctionWithId(Builtins::JavaScript id)
static Handle< Object > GetDataProperty(Handle< JSObject > object, Handle< Name > key)
static bool TryMigrateInstance(Handle< JSObject > instance)
static const int kPropertiesOffset
static MUST_USE_RESULT MaybeHandle< JSObject > DeepWalk(Handle< JSObject > object, AllocationSiteCreationContext *site_context)
static const int kElementsOffset
static const int kValueOffset
static LUnallocated * cast(LOperand *op)
int virtual_register() const
static LifetimePosition FromInstructionIndex(int index)
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
bool Contains(const T &elm) const
static Handle< Map > AsElementsKind(Handle< Map > map, ElementsKind kind)
static void AddDependentCompilationInfo(Handle< Map > map, DependentCode::DependencyGroup group, CompilationInfo *info)
static bool IsValidElementsTransition(ElementsKind from_kind, ElementsKind to_kind)
PostorderProcessor * Backtrack(Zone *zone, ZoneList< HBasicBlock * > *order)
HLoopInformation * loop()
PostorderProcessor * SetupSuccessorsOfLoopMember(HBasicBlock *block, HLoopInformation *loop, HBasicBlock *loop_header)
PostorderProcessor * SetupLoopMembers(Zone *zone, HBasicBlock *block, HLoopInformation *loop, HBasicBlock *loop_header)
HBasicBlock * loop_header_
PostorderProcessor * PerformNonBacktrackingStep(Zone *zone, ZoneList< HBasicBlock * > *order)
PostorderProcessor * child_
HBasicBlock * AdvanceSuccessors()
PostorderProcessor * Pop(Zone *zone, ZoneList< HBasicBlock * > *order)
PostorderProcessor * PerformStep(Zone *zone, ZoneList< HBasicBlock * > *order)
PostorderProcessor * Push(Zone *zone)
HSuccessorIterator successor_iterator
static PostorderProcessor * CreateEntryProcessor(Zone *zone, HBasicBlock *block)
PostorderProcessor * father_
PostorderProcessor * parent()
void InitializeSuccessors()
@ SUCCESSORS_OF_LOOP_HEADER
HBasicBlock * AdvanceLoopMembers()
HBasicBlock * loop_header()
PostorderProcessor(PostorderProcessor *father)
PostorderProcessor * child()
void InitializeLoopMembers()
PostorderProcessor * SetupSuccessors(Zone *zone, HBasicBlock *block, HBasicBlock *loop_header)
void ClosePostorder(ZoneList< HBasicBlock * > *order, Zone *zone)
static void AddDependentCompilationInfo(Handle< PropertyCell > cell, CompilationInfo *info)
A class to uniformly access the prototype of any Object and walk its prototype chain.
bool IsAtEnd(WhereToEnd where_to_end=END_AT_NULL) const
Object * GetCurrent() const
static Representation FromType(Type *type)
static Representation Double()
static Representation Smi()
static Representation Integer32()
static Representation Tagged()
static const Function * FunctionForId(FunctionId id)
static void ArrayIdToTypeAndSize(int array_id, ExternalArrayType *type, ElementsKind *external_elements_kind, ElementsKind *fixed_elements_kind, size_t *element_size)
static MUST_USE_RESULT MaybeHandle< Object > CreateArrayLiteralBoilerplate(Isolate *isolate, Handle< FixedArray > literals, Handle< FixedArray > elements)
int num_heap_slots() const
bool is_global_scope() const
static bool Analyze(CompilationInfo *info)
int num_parameters() const
VariableDeclaration * function() const
int ContextChainLength(Scope *scope)
bool HasIllegalRedeclaration() const
bool is_eval_scope() const
bool is_function_scope() const
ZoneList< Declaration * > * declarations()
Scope * DeclarationScope()
Variable * arguments() const
Handle< ScopeInfo > GetScopeInfo()
static const int kDontAdaptArgumentsSentinel
static const int kMaxValue
static Smi * FromInt(int value)
static bool IsValid(intptr_t value)
virtual bool IsJump() const
static Handle< String > Flatten(Handle< String > string, PretenureFlag pretenure=NOT_TENURED)
bool Equals(String *other)
static bool IsEqualityOp(Value op)
Iterator< i::Map > Classes()
static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region *reg)
static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region *reg)
bool Maybe(TypeImpl *that)
Handle< String > name() const
bool binding_needs_init() const
VariableMode mode() const
bool IsStackAllocated() const
Location location() const
bool IsContextSlot() const
bool IsUnallocated() const
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes to(mksnapshot only)") DEFINE_STRING(raw_context_file
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions true
enable harmony numeric literals(0o77, 0b11)") DEFINE_BOOL(harmony_object_literals
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define STRING_TYPE(NAME, size, name, Name)
#define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value)
#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize)
#define CHECK_ALIVE(call)
#define CHECK_BAILOUT(call)
#define CHECK_ALIVE_OR_RETURN(call, value)
#define DEFINE_IS_CONSTANT(Name, name)
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)
#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value)
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define STATIC_ASSERT(test)
static int Push(SpecialRPOStackFrame *stack, int depth, BasicBlock *child, int unvisited)
static void Trace(const char *msg,...)
Matcher< Node * > IsLoad(const Matcher< LoadRepresentation > &rep_matcher, const Matcher< Node * > &base_matcher, const Matcher< Node * > &index_matcher, const Matcher< Node * > &effect_matcher)
bool IsFastHoleyElementsKind(ElementsKind kind)
const uint32_t kStringEncodingMask
@ DONT_TRACK_ALLOCATION_SITE
bool IsExternalArrayElementsKind(ElementsKind kind)
PerThreadAssertScopeDebugOnly< HEAP_ALLOCATION_ASSERT, false > DisallowHeapAllocation
static bool IsFastLiteral(Handle< JSObject > boilerplate, int max_depth, int *max_properties)
TypeImpl< ZoneTypeConfig > Type
static LifetimePosition Min(LifetimePosition a, LifetimePosition b)
static bool IsClassOfTest(CompareOperation *expr)
bool IsLexicalVariableMode(VariableMode mode)
bool IsFastSmiOrObjectElementsKind(ElementsKind kind)
static bool AreStringTypes(SmallMapList *types)
bool IsDeclaredVariableMode(VariableMode mode)
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind)
static bool IsAllocationInlineable(Handle< JSFunction > constructor)
@ STORE_TO_INITIALIZED_ENTRY
@ STORE_AND_GROW_NO_TRANSITION
@ STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS
@ STORE_NO_TRANSITION_HANDLE_COW
bool IsHoleyElementsKind(ElementsKind kind)
OStream & endl(OStream &os)
static bool CanInlinePropertyAccess(Type *type)
PerThreadAssertScopeDebugOnly< HANDLE_DEREFERENCE_ASSERT, true > AllowHandleDereference
@ FIXED_DOUBLE_ARRAY_TYPE
@ CONS_ONE_BYTE_STRING_TYPE
@ MUTABLE_HEAP_NUMBER_TYPE
@ JS_BUILTINS_OBJECT_TYPE
@ FAST_HOLEY_DOUBLE_ELEMENTS
@ SLOPPY_ARGUMENTS_ELEMENTS
@ FAST_HOLEY_SMI_ELEMENTS
@ EXTERNAL_UINT32_ELEMENTS
@ EXTERNAL_UINT8_CLAMPED_ELEMENTS
bool IsSimpleMapChangeTransition(ElementsKind from_kind, ElementsKind to_kind)
bool IsFastDoubleElementsKind(ElementsKind kind)
Handle< T > handle(T *t, Isolate *isolate)
const uint32_t kOneByteStringTag
int ElementsKindToShiftSize(ElementsKind elements_kind)
int AppendChars(const char *filename, const char *str, int size, bool verbose)
const intptr_t kObjectAlignmentMask
bool CanBeZero(HValue *right)
static bool IsGrowStoreMode(KeyedAccessStoreMode store_mode)
const intptr_t kObjectAlignment
bool IsFastPackedElementsKind(ElementsKind kind)
bool operator<(const Handle< Map > &lhs, const Handle< Map > &rhs)
OStream & operator<<(OStream &os, const BasicBlockProfiler &p)
ElementsKind GetHoleyElementsKind(ElementsKind packed_kind)
AllocationSiteOverrideMode
@ DISABLE_ALLOCATION_SITES
const uint32_t kStringRepresentationMask
static const int kNotInlinable
bool IsFastElementsKind(ElementsKind kind)
void PrintF(const char *format,...)
bool IsDictionaryElementsKind(ElementsKind kind)
const uint32_t kOneByteDataHintMask
static bool ComputeReceiverTypes(Expression *expr, HValue *receiver, SmallMapList **t, Zone *zone)
kFeedbackVectorOffset flag
static bool NeedsWrappingFor(Type *type, Handle< JSFunction > target)
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
const uint32_t kIsNotInternalizedMask
const uint32_t kOneByteDataHintTag
bool IsFixedTypedArrayElementsKind(ElementsKind kind)
static bool ShiftAmountsAllowReplaceByRotate(HValue *sa, HValue *const32_minus_sa)
static Handle< Map > TypedArrayMap(Isolate *isolate, ExternalArrayType array_type, ElementsKind target_kind)
static bool IsLiteralCompareBool(Isolate *isolate, HValue *left, Token::Value op, HValue *right)
bool IsFastSmiElementsKind(ElementsKind kind)
ElementsKind GetInitialFastElementsKind()
bool IsFastObjectElementsKind(ElementsKind kind)
PerThreadAssertScopeDebugOnly< DEFERRED_HANDLE_DEREFERENCE_ASSERT, true > AllowDeferredHandleDereference
Debugger support for the V8 JavaScript engine.
Handle< Boolean > False(Isolate *isolate)
Handle< Boolean > True(Isolate *isolate)
Handle< Primitive > Null(Isolate *isolate)
static Handle< Value > Throw(Isolate *isolate, const char *message)
Handle< Primitive > Undefined(Isolate *isolate)
#define INLINE_OPTIMIZED_FUNCTION_LIST(F)
#define INLINE_FUNCTION_LIST(F)
A simple Maybe type, representing an object which may or may not have a value.
static const char * AllocationIndexToString(int index)
static const char * AllocationIndexToString(int index)
#define STATIC_CHAR_VECTOR(x)