14 #define DEFINE_COMPILE(type) \
15 void L##type::CompileToNative(LCodeGen* generator) { \
16 generator->Do##type(this); \
22 void LInstruction::VerifyCall() {
30 for (UseIterator it(
this); !it.Done(); it.Advance()) {
32 DCHECK(operand->HasFixedPolicy() ||
33 operand->IsUsedAtStart());
37 DCHECK(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
43 void LLabel::PrintDataTo(StringStream* stream) {
45 LLabel* rep = replacement();
47 stream->Add(
" Dead block replaced with B%d", rep->block_id());
52 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
53 arguments()->PrintTo(stream);
54 stream->Add(
" length ");
55 length()->PrintTo(stream);
56 stream->Add(
" index ");
57 index()->PrintTo(stream);
61 void LBranch::PrintDataTo(StringStream* stream) {
62 stream->Add(
"B%d | B%d on ", true_block_id(), false_block_id());
63 value()->PrintTo(stream);
67 void LCallJSFunction::PrintDataTo(StringStream* stream) {
69 function()->PrintTo(stream);
70 stream->Add(
"#%d / ", arity());
74 void LCallWithDescriptor::PrintDataTo(StringStream* stream) {
75 for (
int i = 0;
i < InputCount();
i++) {
76 InputAt(
i)->PrintTo(stream);
79 stream->Add(
"#%d / ", arity());
83 void LCallNew::PrintDataTo(StringStream* stream) {
85 constructor()->PrintTo(stream);
86 stream->Add(
" #%d / ", arity());
90 void LCallNewArray::PrintDataTo(StringStream* stream) {
92 constructor()->PrintTo(stream);
93 stream->Add(
" #%d / ", arity());
99 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
100 stream->Add(
"if class_of_test(");
101 value()->PrintTo(stream);
102 stream->Add(
", \"%o\") then B%d else B%d",
103 *hydrogen()->class_name(),
109 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
111 left()->PrintTo(stream);
113 right()->PrintTo(stream);
114 stream->Add(
" then B%d else B%d", true_block_id(), false_block_id());
118 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
119 stream->Add(
"if has_cached_array_index(");
120 value()->PrintTo(stream);
121 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
125 bool LGoto::HasInterestingComment(LCodeGen* gen)
const {
126 return !gen->IsNextEmittedBlock(block_id());
130 void LGoto::PrintDataTo(StringStream* stream) {
131 stream->Add(
"B%d", block_id());
135 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
137 base_object()->PrintTo(stream);
139 offset()->PrintTo(stream);
143 void LInvokeFunction::PrintDataTo(StringStream* stream) {
145 function()->PrintTo(stream);
146 stream->Add(
" #%d / ", arity());
151 stream->Add(
"%s ", this->
Mnemonic());
172 if (
i > 0) stream->Add(
" ");
187 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
188 stream->Add(
"if has_instance_type(");
189 value()->PrintTo(stream);
190 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
194 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
195 stream->Add(
"if is_object(");
196 value()->PrintTo(stream);
197 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
201 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
202 stream->Add(
"if is_string(");
203 value()->PrintTo(stream);
204 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
208 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
209 stream->Add(
"if is_smi(");
210 value()->PrintTo(stream);
211 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
215 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
216 stream->Add(
"if typeof ");
217 value()->PrintTo(stream);
218 stream->Add(
" == \"%s\" then B%d else B%d",
219 hydrogen()->type_literal()->ToCString().get(),
220 true_block_id(), false_block_id());
224 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
225 stream->Add(
"if is_undetectable(");
226 value()->PrintTo(stream);
227 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
232 for (
int i = 0;
i < 4;
i++) {
243 for (
int i = 0;
i < 4;
i++) {
253 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
254 context()->PrintTo(stream);
255 stream->Add(
"[%d]", slot_index());
259 void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
261 function()->PrintTo(stream);
262 stream->Add(
".code_entry = ");
263 code_object()->PrintTo(stream);
267 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
268 context()->PrintTo(stream);
269 stream->Add(
"[%d] <- ", slot_index());
270 value()->PrintTo(stream);
274 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
275 object()->PrintTo(stream);
277 key()->PrintTo(stream);
278 stream->Add(
"] <- ");
279 value()->PrintTo(stream);
283 void LStoreNamedField::PrintDataTo(StringStream* stream) {
284 object()->PrintTo(stream);
286 os << hydrogen()->access();
287 stream->Add(os.c_str());
289 value()->PrintTo(stream);
293 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
294 object()->PrintTo(stream);
296 stream->Add(String::cast(*
name())->ToCString().get());
298 value()->PrintTo(stream);
302 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
303 stream->Add(
"if string_compare(");
304 left()->PrintTo(stream);
305 right()->PrintTo(stream);
306 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
310 void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
311 object()->PrintTo(stream);
312 stream->Add(
"%p -> %p", *original_map(), *transitioned_map());
318 value()->PrintTo(stream);
322 const char* LArithmeticD::Mnemonic()
const {
328 case Token::MOD:
return "mod-d";
336 const char* LArithmeticT::Mnemonic()
const {
341 case Token::MOD:
return "mod-t";
343 case Token::BIT_AND:
return "bit-and-t";
344 case Token::BIT_OR:
return "bit-or-t";
345 case Token::BIT_XOR:
return "bit-xor-t";
347 case Token::SHL:
return "shl-t";
348 case Token::SAR:
return "sar-t";
349 case Token::SHR:
return "shr-t";
357 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
369 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
370 if (value->EmitAtUses()) {
372 VisitInstruction(instr);
374 operand->set_virtual_register(value->id());
379 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
380 return Use(value, ToUnallocated(fixed_register));
384 LOperand* LChunkBuilder::UseFixedDouble(HValue* value,
386 return Use(value, ToUnallocated(fixed_register));
390 LOperand* LChunkBuilder::UseRegister(HValue* value) {
395 LOperand* LChunkBuilder::UseRegisterAndClobber(HValue* value) {
400 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
407 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
408 return value->IsConstant() ? UseConstant(value) : UseRegister(value);
412 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
413 return value->IsConstant() ? UseConstant(value) : UseRegisterAtStart(value);
417 LConstantOperand* LChunkBuilder::UseConstant(HValue* value) {
418 return chunk_->DefineConstantOperand(HConstant::cast(value));
422 LOperand* LChunkBuilder::UseAny(HValue* value) {
423 return value->IsConstant()
425 : Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
429 LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr,
430 LUnallocated* result) {
431 result->set_virtual_register(current_instruction_->id());
432 instr->set_result(result);
437 LInstruction* LChunkBuilder::DefineAsRegister(
438 LTemplateResultInstruction<1>* instr) {
444 LInstruction* LChunkBuilder::DefineAsSpilled(
445 LTemplateResultInstruction<1>* instr,
int index) {
451 LInstruction* LChunkBuilder::DefineSameAsFirst(
452 LTemplateResultInstruction<1>* instr) {
458 LInstruction* LChunkBuilder::DefineFixed(
459 LTemplateResultInstruction<1>* instr, Register reg) {
460 return Define(instr, ToUnallocated(reg));
464 LInstruction* LChunkBuilder::DefineFixedDouble(
466 return Define(instr, ToUnallocated(reg));
470 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
471 HInstruction* hinstr,
472 CanDeoptimize can_deoptimize) {
473 info()->MarkAsNonDeferredCalling();
478 instr = AssignPointerMap(instr);
484 bool needs_environment =
485 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
486 !hinstr->HasObservableSideEffects();
487 if (needs_environment && !instr->HasEnvironment()) {
488 instr = AssignEnvironment(instr);
490 instr->environment()->set_has_been_used();
497 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
498 DCHECK(!instr->HasPointerMap());
499 instr->set_pointer_map(
new(zone()) LPointerMap(zone()));
504 LUnallocated* LChunkBuilder::TempRegister() {
505 LUnallocated* operand =
507 int vreg = allocator_->GetVirtualRegister();
508 if (!allocator_->AllocationOk()) {
509 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
512 operand->set_virtual_register(vreg);
517 LUnallocated* LChunkBuilder::TempDoubleRegister() {
518 LUnallocated* operand =
520 int vreg = allocator_->GetVirtualRegister();
521 if (!allocator_->AllocationOk()) {
522 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
525 operand->set_virtual_register(vreg);
530 int LPlatformChunk::GetNextSpillIndex() {
531 return spill_slot_count_++;
535 LOperand* LPlatformChunk::GetNextSpillSlot(
RegisterKind kind) {
536 int index = GetNextSpillIndex();
538 return LDoubleStackSlot::Create(index, zone());
541 return LStackSlot::Create(index, zone());
546 LOperand* LChunkBuilder::FixedTemp(Register reg) {
547 LUnallocated* operand = ToUnallocated(reg);
548 DCHECK(operand->HasFixedPolicy());
554 LUnallocated* operand = ToUnallocated(reg);
555 DCHECK(operand->HasFixedPolicy());
560 LPlatformChunk* LChunkBuilder::Build() {
562 chunk_ =
new(zone()) LPlatformChunk(info_, graph_);
563 LPhase phase(
"L_Building chunk", chunk_);
568 if (graph()->has_osr()) {
571 for (
int i = graph()->osr()->UnoptimizedFrameSlots();
i > 0;
i--) {
572 chunk_->GetNextSpillIndex();
576 const ZoneList<HBasicBlock*>* blocks = graph_->blocks();
577 for (
int i = 0;
i < blocks->length();
i++) {
578 DoBasicBlock(blocks->at(
i));
579 if (is_aborted())
return NULL;
586 void LChunkBuilder::DoBasicBlock(HBasicBlock* block) {
588 current_block_ = block;
590 if (block->IsStartBlock()) {
591 block->UpdateEnvironment(graph_->start_environment());
593 }
else if (block->predecessors()->length() == 1) {
596 DCHECK(block->phis()->length() == 0);
597 HBasicBlock* pred = block->predecessors()->at(0);
598 HEnvironment* last_environment = pred->last_environment();
602 if (pred->end()->SecondSuccessor() ==
NULL) {
603 DCHECK(pred->end()->FirstSuccessor() == block);
605 if ((pred->end()->FirstSuccessor()->block_id() > block->block_id()) ||
606 (pred->end()->SecondSuccessor()->block_id() > block->block_id())) {
607 last_environment = last_environment->Copy();
610 block->UpdateEnvironment(last_environment);
611 DCHECK(pred->argument_count() >= 0);
612 argument_count_ = pred->argument_count();
615 HBasicBlock* pred = block->predecessors()->at(0);
617 HEnvironment* last_environment = pred->last_environment();
618 for (
int i = 0;
i < block->phis()->length(); ++
i) {
619 HPhi* phi = block->phis()->at(
i);
620 if (phi->HasMergedIndex()) {
621 last_environment->SetValueAt(phi->merged_index(), phi);
624 for (
int i = 0;
i < block->deleted_phis()->length(); ++
i) {
625 if (block->deleted_phis()->at(
i) < last_environment->length()) {
626 last_environment->SetValueAt(block->deleted_phis()->at(
i),
627 graph_->GetConstantUndefined());
630 block->UpdateEnvironment(last_environment);
632 argument_count_ = pred->argument_count();
636 HInstruction* current = block->first();
637 int start = chunk_->instructions()->length();
638 while ((current !=
NULL) && !is_aborted()) {
640 if (!current->EmitAtUses()) {
641 VisitInstruction(current);
643 current = current->next();
645 int end = chunk_->instructions()->length() - 1;
647 block->set_first_instruction_index(start);
648 block->set_last_instruction_index(end);
650 block->set_argument_count(argument_count_);
651 current_block_ =
NULL;
655 void LChunkBuilder::VisitInstruction(HInstruction* current) {
656 HInstruction* old_current = current_instruction_;
657 current_instruction_ = current;
659 LInstruction* instr =
NULL;
660 if (current->CanReplaceWithDummyUses()) {
661 if (current->OperandCount() == 0) {
662 instr = DefineAsRegister(
new(zone()) LDummy());
664 DCHECK(!current->OperandAt(0)->IsControlInstruction());
665 instr = DefineAsRegister(
new(zone())
666 LDummyUse(UseAny(current->OperandAt(0))));
668 for (
int i = 1;
i < current->OperandCount(); ++
i) {
669 if (current->OperandAt(
i)->IsControlInstruction())
continue;
670 LInstruction* dummy =
671 new(zone()) LDummyUse(UseAny(current->OperandAt(
i)));
672 dummy->set_hydrogen_value(current);
673 chunk_->AddInstruction(dummy, current_block_);
676 HBasicBlock* successor;
677 if (current->IsControlInstruction() &&
680 instr =
new(zone()) LGoto(successor);
682 instr = current->CompileToLithium(
this);
686 argument_count_ += current->argument_delta();
687 DCHECK(argument_count_ >= 0);
690 AddInstruction(instr, current);
693 current_instruction_ = old_current;
697 void LChunkBuilder::AddInstruction(LInstruction* instr,
698 HInstruction* hydrogen_val) {
701 instr->set_hydrogen_value(hydrogen_val);
714 if (!(instr->ClobbersRegisters() &&
715 instr->ClobbersDoubleRegisters(isolate()))) {
717 int used_at_start = 0;
718 for (UseIterator it(instr); !it.Done(); it.Advance()) {
720 if (operand->IsUsedAtStart()) ++used_at_start;
722 if (instr->Output() !=
NULL) {
725 for (TempIterator it(instr); !it.Done(); it.Advance()) {
727 if (operand->HasFixedPolicy()) ++fixed;
729 DCHECK(fixed == 0 || used_at_start == 0);
733 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
734 instr = AssignPointerMap(instr);
736 if (FLAG_stress_environments && !instr->HasEnvironment()) {
737 instr = AssignEnvironment(instr);
739 chunk_->AddInstruction(instr, current_block_);
741 if (instr->IsCall()) {
742 HValue* hydrogen_value_for_lazy_bailout = hydrogen_val;
743 LInstruction* instruction_needing_environment =
NULL;
744 if (hydrogen_val->HasObservableSideEffects()) {
745 HSimulate* sim = HSimulate::cast(hydrogen_val->next());
746 instruction_needing_environment = instr;
747 sim->ReplayEnvironment(current_block_->last_environment());
748 hydrogen_value_for_lazy_bailout = sim;
750 LInstruction* bailout = AssignEnvironment(
new(zone()) LLazyBailout());
751 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
752 chunk_->AddInstruction(bailout, current_block_);
753 if (instruction_needing_environment !=
NULL) {
756 instruction_needing_environment->
757 SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
763 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
764 HEnvironment* hydrogen_env = current_block_->last_environment();
765 int argument_index_accumulator = 0;
766 ZoneList<HValue*> objects_to_materialize(0, zone());
768 &argument_index_accumulator,
769 &objects_to_materialize));
774 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
781 LInstruction* LChunkBuilder::DoArithmeticD(
Token::Value op,
782 HArithmeticBinaryOperation* instr) {
783 DCHECK(instr->representation().IsDouble());
784 DCHECK(instr->left()->representation().IsDouble());
785 DCHECK(instr->right()->representation().IsDouble());
787 if (op == Token::MOD) {
788 LOperand* left = UseFixedDouble(instr->left(),
d0);
789 LOperand* right = UseFixedDouble(instr->right(),
d1);
790 LArithmeticD* result =
new(zone()) LArithmeticD(Token::MOD, left, right);
791 return MarkAsCall(DefineFixedDouble(result,
d0), instr);
793 LOperand* left = UseRegisterAtStart(instr->left());
794 LOperand* right = UseRegisterAtStart(instr->right());
795 LArithmeticD* result =
new(zone()) LArithmeticD(op, left, right);
796 return DefineAsRegister(result);
801 LInstruction* LChunkBuilder::DoArithmeticT(
Token::Value op,
802 HBinaryOperation* instr) {
804 (op ==
Token::DIV) || (op == Token::MOD) || (op == Token::SHR) ||
805 (op == Token::SHL) || (op == Token::SAR) || (op ==
Token::ROR) ||
806 (op == Token::BIT_OR) || (op == Token::BIT_AND) ||
807 (op == Token::BIT_XOR));
808 HValue* left = instr->left();
809 HValue* right = instr->right();
813 DCHECK(instr->representation().IsSmiOrTagged());
814 DCHECK(left->representation().IsSmiOrTagged());
815 DCHECK(right->representation().IsSmiOrTagged());
817 LOperand* context = UseFixed(instr->context(),
cp);
818 LOperand* left_operand = UseFixed(left, x1);
819 LOperand* right_operand = UseFixed(right, x0);
820 LArithmeticT* result =
821 new(zone()) LArithmeticT(op, context, left_operand, right_operand);
822 return MarkAsCall(DefineFixed(result, x0), instr);
826 LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
827 HBoundsCheckBaseIndexInformation* instr) {
833 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
834 info()->MarkAsRequiresFrame();
835 LOperand* args =
NULL;
836 LOperand* length =
NULL;
837 LOperand* index =
NULL;
839 if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
840 args = UseRegisterAtStart(instr->arguments());
841 length = UseConstant(instr->length());
842 index = UseConstant(instr->index());
844 args = UseRegister(instr->arguments());
845 length = UseRegisterAtStart(instr->length());
846 index = UseRegisterOrConstantAtStart(instr->index());
849 return DefineAsRegister(
new(zone()) LAccessArgumentsAt(args, length, index));
853 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
854 if (instr->representation().IsSmiOrInteger32()) {
855 DCHECK(instr->left()->representation().Equals(instr->representation()));
856 DCHECK(instr->right()->representation().Equals(instr->representation()));
858 LInstruction* shifted_operation = TryDoOpWithShiftedRightOperand(instr);
859 if (shifted_operation !=
NULL) {
860 return shifted_operation;
863 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
865 UseRegisterOrConstantAtStart(instr->BetterRightOperand());
866 LInstruction* result = instr->representation().IsSmi() ?
867 DefineAsRegister(
new(zone()) LAddS(left, right)) :
868 DefineAsRegister(new(zone()) LAddI(left, right));
870 result = AssignEnvironment(result);
873 }
else if (instr->representation().IsExternal()) {
874 DCHECK(instr->left()->representation().IsExternal());
875 DCHECK(instr->right()->representation().IsInteger32());
877 LOperand* left = UseRegisterAtStart(instr->left());
878 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
879 return DefineAsRegister(
new(zone()) LAddE(left, right));
880 }
else if (instr->representation().IsDouble()) {
883 DCHECK(instr->representation().IsTagged());
889 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
890 info()->MarkAsDeferredCalling();
891 LOperand* context = UseAny(instr->context());
892 LOperand*
size = UseRegisterOrConstant(instr->size());
893 LOperand* temp1 = TempRegister();
894 LOperand* temp2 = TempRegister();
895 LOperand* temp3 = instr->MustPrefillWithFiller() ? TempRegister() :
NULL;
896 LAllocate* result =
new(zone()) LAllocate(context,
size, temp1, temp2, temp3);
897 return AssignPointerMap(DefineAsRegister(result));
901 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
902 LOperand*
function = UseFixed(instr->function(), x1);
903 LOperand* receiver = UseFixed(instr->receiver(), x0);
904 LOperand* length = UseFixed(instr->length(), x2);
905 LOperand* elements = UseFixed(instr->elements(), x3);
906 LApplyArguments* result =
new(zone()) LApplyArguments(
function,
910 return MarkAsCall(DefineFixed(result, x0), instr, CAN_DEOPTIMIZE_EAGERLY);
914 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* instr) {
915 info()->MarkAsRequiresFrame();
916 LOperand* temp = instr->from_inlined() ?
NULL : TempRegister();
917 return DefineAsRegister(
new(zone()) LArgumentsElements(temp));
921 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) {
922 info()->MarkAsRequiresFrame();
923 LOperand* value = UseRegisterAtStart(instr->value());
924 return DefineAsRegister(
new(zone()) LArgumentsLength(value));
928 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
937 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
938 if (instr->representation().IsSmiOrInteger32()) {
939 DCHECK(instr->left()->representation().Equals(instr->representation()));
940 DCHECK(instr->right()->representation().Equals(instr->representation()));
943 LInstruction* shifted_operation = TryDoOpWithShiftedRightOperand(instr);
944 if (shifted_operation !=
NULL) {
945 return shifted_operation;
948 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
950 UseRegisterOrConstantAtStart(instr->BetterRightOperand());
951 return instr->representation().IsSmi() ?
952 DefineAsRegister(
new(zone()) LBitS(left, right)) :
953 DefineAsRegister(new(zone()) LBitI(left, right));
955 return DoArithmeticT(instr->op(), instr);
960 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
964 return new(zone()) LLabel(instr->block());
968 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
969 if (!FLAG_debug_code && instr->skip_check())
return NULL;
970 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
971 LOperand* length = !index->IsConstantOperand()
972 ? UseRegisterOrConstantAtStart(instr->length())
973 : UseRegisterAtStart(instr->length());
974 LInstruction* result =
new(zone()) LBoundsCheck(index, length);
975 if (!FLAG_debug_code || !instr->skip_check()) {
976 result = AssignEnvironment(result);
982 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
983 HValue* value = instr->value();
984 Representation r = value->representation();
985 HType type = value->type();
987 if (r.IsInteger32() || r.IsSmi() || r.IsDouble()) {
989 return new(zone()) LBranch(UseRegister(value),
NULL,
NULL);
992 if (type.IsBoolean() || type.IsSmi() || type.IsJSArray() ||
993 type.IsHeapNumber()) {
995 return new(zone()) LBranch(UseRegister(value),
NULL,
NULL);
998 if (type.IsString()) {
1000 return new(zone()) LBranch(UseRegister(value), TempRegister(),
NULL);
1003 ToBooleanStub::Types expected = instr->expected_input_types();
1004 bool needs_temps = expected.NeedsMap() || expected.IsEmpty();
1005 LOperand* temp1 = needs_temps ? TempRegister() :
NULL;
1006 LOperand* temp2 = needs_temps ? TempRegister() :
NULL;
1008 if (expected.IsGeneric() || expected.IsEmpty()) {
1012 return new(zone()) LBranch(UseRegister(value), temp1, temp2);
1014 return AssignEnvironment(
1015 new(zone()) LBranch(UseRegister(value), temp1, temp2));
1021 LInstruction* LChunkBuilder::DoCallJSFunction(
1022 HCallJSFunction* instr) {
1023 LOperand*
function = UseFixed(instr->function(), x1);
1025 LCallJSFunction* result =
new(zone()) LCallJSFunction(
function);
1027 return MarkAsCall(DefineFixed(result, x0), instr);
1031 LInstruction* LChunkBuilder::DoCallWithDescriptor(
1032 HCallWithDescriptor* instr) {
1033 CallInterfaceDescriptor descriptor = instr->descriptor();
1035 LOperand* target = UseRegisterOrConstantAtStart(instr->target());
1036 ZoneList<LOperand*> ops(instr->OperandCount(), zone());
1037 ops.Add(target, zone());
1038 for (
int i = 1;
i < instr->OperandCount();
i++) {
1040 UseFixed(instr->OperandAt(
i), descriptor.GetParameterRegister(
i - 1));
1041 ops.Add(op, zone());
1044 LCallWithDescriptor* result =
new(zone()) LCallWithDescriptor(descriptor,
1047 return MarkAsCall(DefineFixed(result, x0), instr);
1051 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1052 LOperand* context = UseFixed(instr->context(),
cp);
1053 LOperand*
function = UseFixed(instr->function(), x1);
1054 LCallFunction* call =
new(zone()) LCallFunction(context,
function);
1055 return MarkAsCall(DefineFixed(call, x0), instr);
1059 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1060 LOperand* context = UseFixed(instr->context(),
cp);
1062 LOperand* constructor = UseFixed(instr->constructor(), x1);
1063 LCallNew* result =
new(zone()) LCallNew(context, constructor);
1064 return MarkAsCall(DefineFixed(result, x0), instr);
1068 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1069 LOperand* context = UseFixed(instr->context(),
cp);
1071 LOperand* constructor = UseFixed(instr->constructor(), x1);
1072 LCallNewArray* result =
new(zone()) LCallNewArray(context, constructor);
1073 return MarkAsCall(DefineFixed(result, x0), instr);
1077 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1078 LOperand* context = UseFixed(instr->context(),
cp);
1079 return MarkAsCall(DefineFixed(
new(zone()) LCallRuntime(context), x0), instr);
1083 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
1084 LOperand* context = UseFixed(instr->context(),
cp);
1085 return MarkAsCall(DefineFixed(
new(zone()) LCallStub(context), x0), instr);
1089 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
1090 instr->ReplayEnvironment(current_block_->last_environment());
1097 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1098 Representation from = instr->from();
1099 Representation
to = instr->to();
1100 HValue* val = instr->value();
1102 if (
to.IsTagged()) {
1103 LOperand* value = UseRegister(val);
1104 return DefineSameAsFirst(
new(zone()) LDummyUse(value));
1108 if (from.IsTagged()) {
1109 if (
to.IsDouble()) {
1110 LOperand* value = UseRegister(val);
1111 LOperand* temp = TempRegister();
1112 LInstruction* result =
1113 DefineAsRegister(
new(zone()) LNumberUntagD(value, temp));
1114 if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1116 }
else if (
to.IsSmi()) {
1117 LOperand* value = UseRegister(val);
1118 if (val->type().IsSmi()) {
1119 return DefineSameAsFirst(
new(zone()) LDummyUse(value));
1121 return AssignEnvironment(DefineSameAsFirst(
new(zone()) LCheckSmi(value)));
1124 if (val->type().IsSmi() || val->representation().IsSmi()) {
1125 LOperand* value = UseRegisterAtStart(val);
1126 return DefineAsRegister(
new(zone()) LSmiUntag(value,
false));
1128 LOperand* value = UseRegister(val);
1129 LOperand* temp1 = TempRegister();
1130 LOperand* temp2 = instr->CanTruncateToInt32()
1131 ?
NULL : TempDoubleRegister();
1132 LInstruction* result =
1133 DefineAsRegister(
new(zone()) LTaggedToI(value, temp1, temp2));
1134 if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1138 }
else if (from.IsDouble()) {
1139 if (
to.IsTagged()) {
1140 info()->MarkAsDeferredCalling();
1141 LOperand* value = UseRegister(val);
1142 LOperand* temp1 = TempRegister();
1143 LOperand* temp2 = TempRegister();
1144 LNumberTagD* result =
new(zone()) LNumberTagD(value, temp1, temp2);
1145 return AssignPointerMap(DefineAsRegister(result));
1148 if (instr->CanTruncateToInt32()) {
1149 LOperand* value = UseRegister(val);
1150 return DefineAsRegister(
new(zone()) LTruncateDoubleToIntOrSmi(value));
1152 LOperand* value = UseRegister(val);
1153 LDoubleToIntOrSmi* result =
new(zone()) LDoubleToIntOrSmi(value);
1154 return AssignEnvironment(DefineAsRegister(result));
1157 }
else if (from.IsInteger32()) {
1158 info()->MarkAsDeferredCalling();
1159 if (
to.IsTagged()) {
1161 LOperand* value = UseRegister(val);
1162 LNumberTagU* result =
1163 new(zone()) LNumberTagU(value, TempRegister(), TempRegister());
1164 return AssignPointerMap(DefineAsRegister(result));
1168 LOperand* value = UseRegisterAtStart(val);
1169 return DefineAsRegister(
new(zone()) LSmiTag(value));
1171 }
else if (
to.IsSmi()) {
1172 LOperand* value = UseRegisterAtStart(val);
1173 LInstruction* result = DefineAsRegister(
new(zone()) LSmiTag(value));
1175 result = AssignEnvironment(result);
1181 return DefineAsRegister(
1182 new(zone()) LUint32ToDouble(UseRegisterAtStart(val)));
1184 return DefineAsRegister(
1185 new(zone()) LInteger32ToDouble(UseRegisterAtStart(val)));
1194 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
1195 LOperand* value = UseRegisterAtStart(instr->value());
1196 return AssignEnvironment(
new(zone()) LCheckValue(value));
1200 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1201 LOperand* value = UseRegisterAtStart(instr->value());
1202 LOperand* temp = TempRegister();
1203 LInstruction* result =
new(zone()) LCheckInstanceType(value, temp);
1204 return AssignEnvironment(result);
1208 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
1209 if (instr->IsStabilityCheck())
return new(zone()) LCheckMaps;
1210 LOperand* value = UseRegisterAtStart(instr->value());
1211 LOperand* temp = TempRegister();
1212 LInstruction* result = AssignEnvironment(
new(zone()) LCheckMaps(value, temp));
1213 if (instr->HasMigrationTarget()) {
1214 info()->MarkAsDeferredCalling();
1215 result = AssignPointerMap(result);
1221 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
1222 LOperand* value = UseRegisterAtStart(instr->value());
1223 LInstruction* result =
new(zone()) LCheckNonSmi(value);
1224 if (!instr->value()->type().IsHeapObject()) {
1225 result = AssignEnvironment(result);
1231 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1232 LOperand* value = UseRegisterAtStart(instr->value());
1233 return AssignEnvironment(
new(zone()) LCheckSmi(value));
1237 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1238 HValue* value = instr->value();
1239 Representation input_rep = value->representation();
1240 LOperand* reg = UseRegister(value);
1241 if (input_rep.IsDouble()) {
1242 return DefineAsRegister(
new(zone()) LClampDToUint8(reg));
1243 }
else if (input_rep.IsInteger32()) {
1244 return DefineAsRegister(
new(zone()) LClampIToUint8(reg));
1246 DCHECK(input_rep.IsSmiOrTagged());
1247 return AssignEnvironment(
1248 DefineAsRegister(
new(zone()) LClampTToUint8(reg,
1249 TempDoubleRegister())));
1254 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1255 HClassOfTestAndBranch* instr) {
1256 DCHECK(instr->value()->representation().IsTagged());
1257 LOperand* value = UseRegisterAtStart(instr->value());
1258 return new(zone()) LClassOfTestAndBranch(value,
1264 LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
1265 HCompareNumericAndBranch* instr) {
1266 Representation r = instr->representation();
1267 if (r.IsSmiOrInteger32()) {
1268 DCHECK(instr->left()->representation().Equals(r));
1269 DCHECK(instr->right()->representation().Equals(r));
1270 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1271 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
1272 return new(zone()) LCompareNumericAndBranch(left, right);
1275 DCHECK(instr->left()->representation().IsDouble());
1276 DCHECK(instr->right()->representation().IsDouble());
1277 if (instr->left()->IsConstant() && instr->right()->IsConstant()) {
1278 LOperand* left = UseConstant(instr->left());
1279 LOperand* right = UseConstant(instr->right());
1280 return new(zone()) LCompareNumericAndBranch(left, right);
1282 LOperand* left = UseRegisterAtStart(instr->left());
1283 LOperand* right = UseRegisterAtStart(instr->right());
1284 return new(zone()) LCompareNumericAndBranch(left, right);
1289 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1290 DCHECK(instr->left()->representation().IsTagged());
1291 DCHECK(instr->right()->representation().IsTagged());
1292 LOperand* context = UseFixed(instr->context(),
cp);
1293 LOperand* left = UseFixed(instr->left(), x1);
1294 LOperand* right = UseFixed(instr->right(), x0);
1295 LCmpT* result =
new(zone()) LCmpT(context, left, right);
1296 return MarkAsCall(DefineFixed(result, x0), instr);
1300 LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1301 HCompareHoleAndBranch* instr) {
1302 LOperand* value = UseRegister(instr->value());
1303 if (instr->representation().IsTagged()) {
1304 return new(zone()) LCmpHoleAndBranchT(value);
1306 LOperand* temp = TempRegister();
1307 return new(zone()) LCmpHoleAndBranchD(value, temp);
1312 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1313 HCompareObjectEqAndBranch* instr) {
1314 LOperand* left = UseRegisterAtStart(instr->left());
1315 LOperand* right = UseRegisterAtStart(instr->right());
1316 return new(zone()) LCmpObjectEqAndBranch(left, right);
1320 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
1321 DCHECK(instr->value()->representation().IsTagged());
1322 LOperand* value = UseRegisterAtStart(instr->value());
1323 LOperand* temp = TempRegister();
1324 return new(zone()) LCmpMapAndBranch(value, temp);
1328 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1329 Representation r = instr->representation();
1331 return DefineAsRegister(
new(zone()) LConstantS);
1332 }
else if (r.IsInteger32()) {
1333 return DefineAsRegister(
new(zone()) LConstantI);
1334 }
else if (r.IsDouble()) {
1335 return DefineAsRegister(
new(zone()) LConstantD);
1336 }
else if (r.IsExternal()) {
1337 return DefineAsRegister(
new(zone()) LConstantE);
1338 }
else if (r.IsTagged()) {
1339 return DefineAsRegister(
new(zone()) LConstantT);
1347 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1348 if (instr->HasNoUses())
return NULL;
1350 if (info()->IsStub()) {
1351 return DefineFixed(
new(zone()) LContext,
cp);
1354 return DefineAsRegister(
new(zone()) LContext);
1358 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1359 LOperand*
object = UseFixed(instr->value(), x0);
1360 LDateField* result =
new(zone()) LDateField(
object, instr->index());
1361 return MarkAsCall(DefineFixed(result, x0), instr, CAN_DEOPTIMIZE_EAGERLY);
1365 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
1366 return new(zone()) LDebugBreak();
1370 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1371 LOperand* context = UseFixed(instr->context(),
cp);
1372 return MarkAsCall(
new(zone()) LDeclareGlobals(context), instr);
1376 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
1377 return AssignEnvironment(
new(zone()) LDeoptimize);
1381 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) {
1382 DCHECK(instr->representation().IsInteger32());
1383 DCHECK(instr->left()->representation().Equals(instr->representation()));
1384 DCHECK(instr->right()->representation().Equals(instr->representation()));
1385 LOperand* dividend = UseRegister(instr->left());
1386 int32_t divisor = instr->right()->GetInteger32Constant();
1387 LInstruction* result = DefineAsRegister(
new(zone()) LDivByPowerOf2I(
1388 dividend, divisor));
1392 divisor != 1 && divisor != -1)) {
1393 result = AssignEnvironment(result);
1399 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) {
1400 DCHECK(instr->representation().IsInteger32());
1401 DCHECK(instr->left()->representation().Equals(instr->representation()));
1402 DCHECK(instr->right()->representation().Equals(instr->representation()));
1403 LOperand* dividend = UseRegister(instr->left());
1404 int32_t divisor = instr->right()->GetInteger32Constant();
1406 ?
NULL : TempRegister();
1407 LInstruction* result = DefineAsRegister(
new(zone()) LDivByConstI(
1408 dividend, divisor, temp));
1412 result = AssignEnvironment(result);
1418 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) {
1419 DCHECK(instr->representation().IsSmiOrInteger32());
1420 DCHECK(instr->left()->representation().Equals(instr->representation()));
1421 DCHECK(instr->right()->representation().Equals(instr->representation()));
1422 LOperand* dividend = UseRegister(instr->left());
1423 LOperand* divisor = UseRegister(instr->right());
1425 ?
NULL : TempRegister();
1426 LInstruction* result =
1427 DefineAsRegister(
new(zone()) LDivI(dividend, divisor, temp));
1429 result = AssignEnvironment(result);
1435 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1436 if (instr->representation().IsSmiOrInteger32()) {
1437 if (instr->RightIsPowerOf2()) {
1438 return DoDivByPowerOf2I(instr);
1439 }
else if (instr->right()->IsConstant()) {
1440 return DoDivByConstI(instr);
1442 return DoDivI(instr);
1444 }
else if (instr->representation().IsDouble()) {
1452 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
1453 return DefineAsRegister(
new(zone()) LDummyUse(UseAny(instr->value())));
1457 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
1458 HEnvironment* outer = current_block_->last_environment();
1459 outer->set_ast_id(instr->ReturnId());
1460 HConstant* undefined = graph()->GetConstantUndefined();
1461 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
1462 instr->arguments_count(),
1465 instr->inlining_kind());
1467 if ((instr->arguments_var() !=
NULL) &&
1468 instr->arguments_object()->IsLinked()) {
1469 inner->Bind(instr->arguments_var(), instr->arguments_object());
1471 inner->BindContext(instr->closure_context());
1472 inner->set_entry(instr);
1473 current_block_->UpdateEnvironment(inner);
1474 chunk_->AddInlinedClosure(instr->closure());
1479 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
1485 LInstruction* LChunkBuilder::DoForceRepresentation(
1486 HForceRepresentation* instr) {
1494 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
1495 LOperand* context = UseFixed(instr->context(),
cp);
1497 DefineFixed(
new(zone()) LFunctionLiteral(context), x0), instr);
1501 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1502 HGetCachedArrayIndex* instr) {
1503 DCHECK(instr->value()->representation().IsTagged());
1504 LOperand* value = UseRegisterAtStart(instr->value());
1505 return DefineAsRegister(
new(zone()) LGetCachedArrayIndex(value));
1509 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
1510 return new(zone()) LGoto(instr->FirstSuccessor());
1514 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1515 HHasCachedArrayIndexAndBranch* instr) {
1516 DCHECK(instr->value()->representation().IsTagged());
1517 return new(zone()) LHasCachedArrayIndexAndBranch(
1518 UseRegisterAtStart(instr->value()), TempRegister());
1522 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1523 HHasInstanceTypeAndBranch* instr) {
1524 DCHECK(instr->value()->representation().IsTagged());
1525 LOperand* value = UseRegisterAtStart(instr->value());
1526 return new(zone()) LHasInstanceTypeAndBranch(value, TempRegister());
1530 LInstruction* LChunkBuilder::DoInnerAllocatedObject(
1531 HInnerAllocatedObject* instr) {
1532 LOperand* base_object = UseRegisterAtStart(instr->base_object());
1533 LOperand* offset = UseRegisterOrConstantAtStart(instr->offset());
1534 return DefineAsRegister(
1535 new(zone()) LInnerAllocatedObject(base_object, offset));
1539 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
1540 LOperand* context = UseFixed(instr->context(),
cp);
1541 LInstanceOf* result =
new(zone()) LInstanceOf(
1545 return MarkAsCall(DefineFixed(result, x0), instr);
1549 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1550 HInstanceOfKnownGlobal* instr) {
1551 LInstanceOfKnownGlobal* result =
new(zone()) LInstanceOfKnownGlobal(
1552 UseFixed(instr->context(),
cp),
1554 return MarkAsCall(DefineFixed(result, x0), instr);
1558 LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
1559 HTailCallThroughMegamorphicCache* instr) {
1560 LOperand* context = UseFixed(instr->context(),
cp);
1561 LOperand* receiver_register =
1563 LOperand* name_register =
1566 return new (zone()) LTailCallThroughMegamorphicCache(
1567 context, receiver_register, name_register);
1571 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1572 LOperand* context = UseFixed(instr->context(),
cp);
1574 LOperand*
function = UseFixed(instr->function(), x1);
1575 LInvokeFunction* result =
new(zone()) LInvokeFunction(context,
function);
1576 return MarkAsCall(DefineFixed(result, x0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1580 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
1581 HIsConstructCallAndBranch* instr) {
1582 return new(zone()) LIsConstructCallAndBranch(TempRegister(), TempRegister());
1586 LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
1587 HCompareMinusZeroAndBranch* instr) {
1588 LOperand* value = UseRegister(instr->value());
1589 LOperand* scratch = TempRegister();
1590 return new(zone()) LCompareMinusZeroAndBranch(value, scratch);
1594 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1595 DCHECK(instr->value()->representation().IsTagged());
1596 LOperand* value = UseRegisterAtStart(instr->value());
1597 LOperand* temp1 = TempRegister();
1598 LOperand* temp2 = TempRegister();
1599 return new(zone()) LIsObjectAndBranch(value, temp1, temp2);
1603 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1604 DCHECK(instr->value()->representation().IsTagged());
1605 LOperand* value = UseRegisterAtStart(instr->value());
1606 LOperand* temp = TempRegister();
1607 return new(zone()) LIsStringAndBranch(value, temp);
1611 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1612 DCHECK(instr->value()->representation().IsTagged());
1613 return new(zone()) LIsSmiAndBranch(UseRegisterAtStart(instr->value()));
1617 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1618 HIsUndetectableAndBranch* instr) {
1619 DCHECK(instr->value()->representation().IsTagged());
1620 LOperand* value = UseRegisterAtStart(instr->value());
1621 return new(zone()) LIsUndetectableAndBranch(value, TempRegister());
1625 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
1626 LInstruction* pop =
NULL;
1627 HEnvironment* env = current_block_->last_environment();
1629 if (env->entry()->arguments_pushed()) {
1630 int argument_count = env->arguments_environment()->parameter_count();
1631 pop =
new(zone()) LDrop(argument_count);
1632 DCHECK(instr->argument_delta() == -argument_count);
1635 HEnvironment* outer =
1636 current_block_->last_environment()->DiscardInlined(
false);
1637 current_block_->UpdateEnvironment(outer);
1643 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1644 LOperand* context = UseRegisterAtStart(instr->value());
1645 LInstruction* result =
1646 DefineAsRegister(
new(zone()) LLoadContextSlot(context));
1647 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
1648 result = AssignEnvironment(result);
1654 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1655 HLoadFunctionPrototype* instr) {
1656 LOperand*
function = UseRegister(instr->function());
1657 LOperand* temp = TempRegister();
1658 return AssignEnvironment(DefineAsRegister(
1659 new(zone()) LLoadFunctionPrototype(
function, temp)));
1663 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
1664 LLoadGlobalCell* result =
new(zone()) LLoadGlobalCell();
1665 return instr->RequiresHoleCheck()
1666 ? AssignEnvironment(DefineAsRegister(result))
1667 : DefineAsRegister(result);
1671 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1672 LOperand* context = UseFixed(instr->context(),
cp);
1673 LOperand* global_object =
1675 LOperand* vector =
NULL;
1676 if (FLAG_vector_ics) {
1680 LLoadGlobalGeneric* result =
1681 new(zone()) LLoadGlobalGeneric(context, global_object, vector);
1682 return MarkAsCall(DefineFixed(result, x0), instr);
1686 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
1687 DCHECK(instr->key()->representation().IsSmiOrInteger32());
1689 LOperand* elements = UseRegister(instr->elements());
1690 LOperand* key = UseRegisterOrConstant(instr->key());
1692 if (!instr->is_typed_elements()) {
1693 if (instr->representation().IsDouble()) {
1694 LOperand* temp = (!instr->key()->IsConstant() ||
1695 instr->RequiresHoleCheck())
1699 LLoadKeyedFixedDouble* result =
1700 new(zone()) LLoadKeyedFixedDouble(elements, key, temp);
1701 return instr->RequiresHoleCheck()
1702 ? AssignEnvironment(DefineAsRegister(result))
1703 : DefineAsRegister(result);
1705 DCHECK(instr->representation().IsSmiOrTagged() ||
1706 instr->representation().IsInteger32());
1707 LOperand* temp = instr->key()->IsConstant() ?
NULL : TempRegister();
1708 LLoadKeyedFixed* result =
1709 new(zone()) LLoadKeyedFixed(elements, key, temp);
1710 return instr->RequiresHoleCheck()
1711 ? AssignEnvironment(DefineAsRegister(result))
1712 : DefineAsRegister(result);
1715 DCHECK((instr->representation().IsInteger32() &&
1717 (instr->representation().IsDouble() &&
1720 LOperand* temp = instr->key()->IsConstant() ?
NULL : TempRegister();
1721 LInstruction* result = DefineAsRegister(
1722 new(zone()) LLoadKeyedExternal(elements, key, temp));
1726 result = AssignEnvironment(result);
1733 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1734 LOperand* context = UseFixed(instr->context(),
cp);
1738 LOperand* vector =
NULL;
1739 if (FLAG_vector_ics) {
1743 LInstruction* result =
1744 DefineFixed(
new(zone()) LLoadKeyedGeneric(context,
object, key, vector),
1746 return MarkAsCall(result, instr);
1750 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1751 LOperand*
object = UseRegisterAtStart(instr->object());
1752 return DefineAsRegister(
new(zone()) LLoadNamedField(
object));
1756 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1757 LOperand* context = UseFixed(instr->context(),
cp);
1760 LOperand* vector =
NULL;
1761 if (FLAG_vector_ics) {
1765 LInstruction* result =
1766 DefineFixed(
new(zone()) LLoadNamedGeneric(context,
object, vector), x0);
1767 return MarkAsCall(result, instr);
1771 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
1772 return DefineAsRegister(
new(zone()) LLoadRoot);
1776 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1777 LOperand*
map = UseRegisterAtStart(instr->value());
1778 return DefineAsRegister(
new(zone()) LMapEnumLength(
map));
1782 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
1783 DCHECK(instr->representation().IsInteger32());
1784 DCHECK(instr->left()->representation().Equals(instr->representation()));
1785 DCHECK(instr->right()->representation().Equals(instr->representation()));
1786 LOperand* dividend = UseRegisterAtStart(instr->left());
1787 int32_t divisor = instr->right()->GetInteger32Constant();
1788 LInstruction* result = DefineAsRegister(
new(zone()) LFlooringDivByPowerOf2I(
1789 dividend, divisor));
1792 result = AssignEnvironment(result);
1798 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
1799 DCHECK(instr->representation().IsInteger32());
1800 DCHECK(instr->left()->representation().Equals(instr->representation()));
1801 DCHECK(instr->right()->representation().Equals(instr->representation()));
1802 LOperand* dividend = UseRegister(instr->left());
1803 int32_t divisor = instr->right()->GetInteger32Constant();
1807 NULL : TempRegister();
1808 LInstruction* result = DefineAsRegister(
1809 new(zone()) LFlooringDivByConstI(dividend, divisor, temp));
1812 result = AssignEnvironment(result);
1818 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) {
1819 LOperand* dividend = UseRegister(instr->left());
1820 LOperand* divisor = UseRegister(instr->right());
1821 LOperand* remainder = TempRegister();
1822 LInstruction* result =
1823 DefineAsRegister(
new(zone()) LFlooringDivI(dividend, divisor, remainder));
1824 return AssignEnvironment(result);
1828 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1829 if (instr->RightIsPowerOf2()) {
1830 return DoFlooringDivByPowerOf2I(instr);
1831 }
else if (instr->right()->IsConstant()) {
1832 return DoFlooringDivByConstI(instr);
1834 return DoFlooringDivI(instr);
1839 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1840 LOperand* left =
NULL;
1841 LOperand* right =
NULL;
1842 if (instr->representation().IsSmiOrInteger32()) {
1843 DCHECK(instr->left()->representation().Equals(instr->representation()));
1844 DCHECK(instr->right()->representation().Equals(instr->representation()));
1845 left = UseRegisterAtStart(instr->BetterLeftOperand());
1846 right = UseRegisterOrConstantAtStart(instr->BetterRightOperand());
1848 DCHECK(instr->representation().IsDouble());
1849 DCHECK(instr->left()->representation().IsDouble());
1850 DCHECK(instr->right()->representation().IsDouble());
1851 left = UseRegisterAtStart(instr->left());
1852 right = UseRegisterAtStart(instr->right());
1854 return DefineAsRegister(
new(zone()) LMathMinMax(left, right));
1858 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
1859 DCHECK(instr->representation().IsInteger32());
1860 DCHECK(instr->left()->representation().Equals(instr->representation()));
1861 DCHECK(instr->right()->representation().Equals(instr->representation()));
1862 LOperand* dividend = UseRegisterAtStart(instr->left());
1863 int32_t divisor = instr->right()->GetInteger32Constant();
1864 LInstruction* result = DefineSameAsFirst(
new(zone()) LModByPowerOf2I(
1865 dividend, divisor));
1868 result = AssignEnvironment(result);
1874 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) {
1875 DCHECK(instr->representation().IsInteger32());
1876 DCHECK(instr->left()->representation().Equals(instr->representation()));
1877 DCHECK(instr->right()->representation().Equals(instr->representation()));
1878 LOperand* dividend = UseRegister(instr->left());
1879 int32_t divisor = instr->right()->GetInteger32Constant();
1880 LOperand* temp = TempRegister();
1881 LInstruction* result = DefineAsRegister(
new(zone()) LModByConstI(
1882 dividend, divisor, temp));
1884 result = AssignEnvironment(result);
1890 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
1891 DCHECK(instr->representation().IsSmiOrInteger32());
1892 DCHECK(instr->left()->representation().Equals(instr->representation()));
1893 DCHECK(instr->right()->representation().Equals(instr->representation()));
1894 LOperand* dividend = UseRegister(instr->left());
1895 LOperand* divisor = UseRegister(instr->right());
1896 LInstruction* result = DefineAsRegister(
new(zone()) LModI(dividend, divisor));
1899 result = AssignEnvironment(result);
1905 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1906 if (instr->representation().IsSmiOrInteger32()) {
1907 if (instr->RightIsPowerOf2()) {
1908 return DoModByPowerOf2I(instr);
1909 }
else if (instr->right()->IsConstant()) {
1910 return DoModByConstI(instr);
1912 return DoModI(instr);
1914 }
else if (instr->representation().IsDouble()) {
1915 return DoArithmeticD(Token::MOD, instr);
1917 return DoArithmeticT(Token::MOD, instr);
1922 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1923 if (instr->representation().IsSmiOrInteger32()) {
1924 DCHECK(instr->left()->representation().Equals(instr->representation()));
1925 DCHECK(instr->right()->representation().Equals(instr->representation()));
1930 HValue* least_const = instr->BetterLeftOperand();
1931 HValue* most_const = instr->BetterRightOperand();
1939 if (most_const->IsConstant()) {
1940 int32_t constant = HConstant::cast(most_const)->Integer32Value();
1941 bool small_constant = (constant >= -1) && (constant <= 2);
1942 bool end_range_constant = (constant <= -
kMaxInt) || (constant ==
kMaxInt);
1945 if (!end_range_constant &&
1949 LConstantOperand* right = UseConstant(most_const);
1950 bool need_register =
1952 LOperand* left = need_register ? UseRegister(least_const)
1953 : UseRegisterAtStart(least_const);
1954 LInstruction* result =
1955 DefineAsRegister(
new(zone()) LMulConstIS(left, right));
1956 if ((bailout_on_minus_zero && constant <= 0) || can_overflow) {
1957 result = AssignEnvironment(result);
1965 LOperand* left = UseRegisterAtStart(least_const);
1966 LOperand* right = UseRegisterAtStart(most_const);
1967 LInstruction* result = instr->representation().IsSmi()
1968 ? DefineAsRegister(
new(zone()) LMulS(left, right))
1969 : DefineAsRegister(new(zone()) LMulI(left, right));
1970 if ((bailout_on_minus_zero && least_const != most_const) || can_overflow) {
1971 result = AssignEnvironment(result);
1974 }
else if (instr->representation().IsDouble()) {
1982 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
1983 DCHECK(argument_count_ == 0);
1984 allocator_->MarkAsOsrEntry();
1985 current_block_->last_environment()->set_ast_id(instr->ast_id());
1986 return AssignEnvironment(
new(zone()) LOsrEntry);
1990 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
1991 LParameter* result =
new(zone()) LParameter;
1992 if (instr->kind() == HParameter::STACK_PARAMETER) {
1993 int spill_index = chunk_->GetParameterStackSlot(instr->index());
1994 return DefineAsSpilled(result, spill_index);
1996 DCHECK(info()->IsStub());
1997 CallInterfaceDescriptor descriptor =
1998 info()->code_stub()->GetCallInterfaceDescriptor();
1999 int index =
static_cast<int>(instr->index());
2000 Register reg = descriptor.GetEnvironmentParameterRegister(index);
2001 return DefineFixed(result, reg);
2006 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
2007 DCHECK(instr->representation().IsDouble());
2010 Representation exponent_type = instr->right()->representation();
2011 DCHECK(instr->left()->representation().IsDouble());
2012 LOperand* left = UseFixedDouble(instr->left(),
d0);
2014 if (exponent_type.IsInteger32()) {
2016 }
else if (exponent_type.IsDouble()) {
2017 right = UseFixedDouble(instr->right(),
d1);
2021 LPower* result =
new(zone()) LPower(left, right);
2022 return MarkAsCall(DefineFixedDouble(result,
d0),
2024 CAN_DEOPTIMIZE_EAGERLY);
2028 LInstruction* LChunkBuilder::DoPushArguments(HPushArguments* instr) {
2029 int argc = instr->OperandCount();
2030 AddInstruction(
new(zone()) LPreparePushArguments(argc), instr);
2032 LPushArguments* push_args =
new(zone()) LPushArguments(zone());
2034 for (
int i = 0;
i < argc; ++
i) {
2035 if (push_args->ShouldSplitPush()) {
2036 AddInstruction(push_args, instr);
2037 push_args =
new(zone()) LPushArguments(zone());
2039 push_args->AddArgument(UseRegister(instr->argument(
i)));
2046 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2047 LOperand* context = UseFixed(instr->context(),
cp);
2049 DefineFixed(
new(zone()) LRegExpLiteral(context), x0), instr);
2053 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) {
2054 HValue* value = instr->value();
2055 DCHECK(value->representation().IsDouble());
2056 return DefineAsRegister(
new(zone()) LDoubleBits(UseRegister(value)));
2060 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
2061 LOperand*
lo = UseRegisterAndClobber(instr->lo());
2062 LOperand*
hi = UseRegister(instr->hi());
2063 return DefineAsRegister(
new(zone()) LConstructDouble(
hi,
lo));
2067 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
2068 LOperand* context = info()->IsStub()
2069 ? UseFixed(instr->context(),
cp)
2071 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
2072 return new(zone()) LReturn(UseFixed(instr->value(), x0), context,
2077 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
2078 LOperand*
string = UseRegisterAtStart(instr->string());
2079 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
2080 LOperand* temp = TempRegister();
2081 LSeqStringGetChar* result =
2082 new(zone()) LSeqStringGetChar(
string, index, temp);
2083 return DefineAsRegister(result);
2087 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
2088 LOperand*
string = UseRegister(instr->string());
2089 LOperand* index = FLAG_debug_code
2090 ? UseRegister(instr->index())
2091 : UseRegisterOrConstant(instr->index());
2092 LOperand* value = UseRegister(instr->value());
2093 LOperand* context = FLAG_debug_code ? UseFixed(instr->context(),
cp) :
NULL;
2094 LOperand* temp = TempRegister();
2095 LSeqStringSetChar* result =
2096 new(zone()) LSeqStringSetChar(context,
string, index, value, temp);
2097 return DefineAsRegister(result);
2101 HBitwiseBinaryOperation* LChunkBuilder::CanTransformToShiftedOp(HValue* val,
2103 if (!val->representation().IsInteger32())
return NULL;
2104 if (!(val->IsBitwise() || val->IsAdd() || val->IsSub()))
return NULL;
2107 HValue* hleft = hinstr->left();
2108 HValue* hright = hinstr->right();
2109 DCHECK(hleft->representation().Equals(hinstr->representation()));
2110 DCHECK(hright->representation().Equals(hinstr->representation()));
2112 if ((hright->IsConstant() &&
2113 LikelyFitsImmField(hinstr, HConstant::cast(hright)->Integer32Value())) ||
2114 (hinstr->IsCommutative() && hleft->IsConstant() &&
2115 LikelyFitsImmField(hinstr, HConstant::cast(hleft)->Integer32Value()))) {
2129 if (hright->IsBitwiseBinaryShift() &&
2135 }
else if (hinstr->IsCommutative() &&
2136 hleft->IsBitwiseBinaryShift() &&
2146 if ((JSShiftAmountFromHConstant(
shift->right()) == 0) &&
shift->IsShr()) {
2155 bool LChunkBuilder::ShiftCanBeOptimizedAway(HBitwiseBinaryOperation*
shift) {
2156 if (!
shift->representation().IsInteger32()) {
2159 for (HUseIterator it(
shift->uses()); !it.Done(); it.Advance()) {
2160 if (
shift != CanTransformToShiftedOp(it.value())) {
2168 LInstruction* LChunkBuilder::TryDoOpWithShiftedRightOperand(
2169 HBinaryOperation* instr) {
2171 HBitwiseBinaryOperation*
shift = CanTransformToShiftedOp(instr, &left);
2174 return DoShiftedBinaryOp(instr, left,
shift);
2180 LInstruction* LChunkBuilder::DoShiftedBinaryOp(
2181 HBinaryOperation* hinstr, HValue* hleft, HBitwiseBinaryOperation* hshift) {
2182 DCHECK(hshift->IsBitwiseBinaryShift());
2183 DCHECK(!hshift->IsShr() || (JSShiftAmountFromHConstant(hshift->right()) > 0));
2185 LTemplateResultInstruction<1>* res;
2186 LOperand* left = UseRegisterAtStart(hleft);
2187 LOperand* right = UseRegisterAtStart(hshift->left());
2188 LOperand* shift_amount = UseConstant(hshift->right());
2190 switch (hshift->opcode()) {
2191 case HValue::kShl: shift_op =
LSL;
break;
2192 case HValue::kShr: shift_op =
LSR;
break;
2193 case HValue::kSar: shift_op =
ASR;
break;
2197 if (hinstr->IsBitwise()) {
2198 res =
new(zone()) LBitI(left, right, shift_op, shift_amount);
2199 }
else if (hinstr->IsAdd()) {
2200 res =
new(zone()) LAddI(left, right, shift_op, shift_amount);
2203 res =
new(zone()) LSubI(left, right, shift_op, shift_amount);
2206 AssignEnvironment(res);
2208 return DefineAsRegister(res);
2213 HBitwiseBinaryOperation* instr) {
2214 if (instr->representation().IsTagged()) {
2215 return DoArithmeticT(op, instr);
2218 DCHECK(instr->representation().IsSmiOrInteger32());
2219 DCHECK(instr->left()->representation().Equals(instr->representation()));
2220 DCHECK(instr->right()->representation().Equals(instr->representation()));
2222 if (ShiftCanBeOptimizedAway(instr)) {
2226 LOperand* left = instr->representation().IsSmi()
2227 ? UseRegister(instr->left())
2228 : UseRegisterAtStart(instr->left());
2229 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
2233 bool right_can_be_zero = !instr->right()->IsConstant() ||
2234 (JSShiftAmountFromHConstant(instr->right()) == 0);
2235 bool can_deopt =
false;
2236 if ((op == Token::SHR) && right_can_be_zero) {
2237 if (FLAG_opt_safe_uint32_operations) {
2244 LInstruction* result;
2245 if (instr->representation().IsInteger32()) {
2246 result = DefineAsRegister(
new (zone()) LShiftI(op, left, right, can_deopt));
2248 DCHECK(instr->representation().IsSmi());
2249 result = DefineAsRegister(
new (zone()) LShiftS(op, left, right, can_deopt));
2252 return can_deopt ? AssignEnvironment(result) : result;
2256 LInstruction* LChunkBuilder::DoRor(HRor* instr) {
2261 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
2262 return DoShift(Token::SAR, instr);
2266 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
2267 return DoShift(Token::SHL, instr);
2271 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
2272 return DoShift(Token::SHR, instr);
2276 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2277 instr->ReplayEnvironment(current_block_->last_environment());
2282 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2283 if (instr->is_function_entry()) {
2284 LOperand* context = UseFixed(instr->context(),
cp);
2285 return MarkAsCall(
new(zone()) LStackCheck(context), instr);
2287 DCHECK(instr->is_backwards_branch());
2288 LOperand* context = UseAny(instr->context());
2289 return AssignEnvironment(
2290 AssignPointerMap(
new(zone()) LStackCheck(context)));
2295 LInstruction* LChunkBuilder::DoStoreCodeEntry(HStoreCodeEntry* instr) {
2296 LOperand*
function = UseRegister(instr->function());
2297 LOperand* code_object = UseRegisterAtStart(instr->code_object());
2298 LOperand* temp = TempRegister();
2299 return new(zone()) LStoreCodeEntry(
function, code_object, temp);
2303 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
2304 LOperand* temp = TempRegister();
2307 if (instr->NeedsWriteBarrier()) {
2310 context = UseRegisterAndClobber(instr->context());
2311 value = UseRegisterAndClobber(instr->value());
2313 context = UseRegister(instr->context());
2314 value = UseRegister(instr->value());
2316 LInstruction* result =
new(zone()) LStoreContextSlot(context, value, temp);
2317 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
2318 result = AssignEnvironment(result);
2324 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
2325 LOperand* value = UseRegister(instr->value());
2326 if (instr->RequiresHoleCheck()) {
2327 return AssignEnvironment(
new(zone()) LStoreGlobalCell(value,
2331 return new(zone()) LStoreGlobalCell(value, TempRegister(),
NULL);
2336 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
2337 LOperand* key = UseRegisterOrConstant(instr->key());
2338 LOperand* temp =
NULL;
2339 LOperand* elements =
NULL;
2340 LOperand* val =
NULL;
2342 if (!instr->is_typed_elements() &&
2343 instr->value()->representation().IsTagged() &&
2344 instr->NeedsWriteBarrier()) {
2346 elements = UseRegisterAndClobber(instr->elements());
2347 val = UseRegisterAndClobber(instr->value());
2348 temp = TempRegister();
2350 elements = UseRegister(instr->elements());
2351 val = UseRegister(instr->value());
2352 temp = instr->key()->IsConstant() ?
NULL : TempRegister();
2355 if (instr->is_typed_elements()) {
2356 DCHECK((instr->value()->representation().IsInteger32() &&
2358 (instr->value()->representation().IsDouble() &&
2360 DCHECK((instr->is_fixed_typed_array() &&
2361 instr->elements()->representation().IsTagged()) ||
2362 (instr->is_external() &&
2363 instr->elements()->representation().IsExternal()));
2364 return new(zone()) LStoreKeyedExternal(elements, key, val, temp);
2366 }
else if (instr->value()->representation().IsDouble()) {
2367 DCHECK(instr->elements()->representation().IsTagged());
2368 return new(zone()) LStoreKeyedFixedDouble(elements, key, val, temp);
2371 DCHECK(instr->elements()->representation().IsTagged());
2372 DCHECK(instr->value()->representation().IsSmiOrTagged() ||
2373 instr->value()->representation().IsInteger32());
2374 return new(zone()) LStoreKeyedFixed(elements, key, val, temp);
2379 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
2380 LOperand* context = UseFixed(instr->context(),
cp);
2386 DCHECK(instr->object()->representation().IsTagged());
2387 DCHECK(instr->key()->representation().IsTagged());
2388 DCHECK(instr->value()->representation().IsTagged());
2391 new(zone()) LStoreKeyedGeneric(context,
object, key, value), instr);
2395 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2399 LOperand*
object = UseRegister(instr->object());
2401 LOperand* temp0 =
NULL;
2402 LOperand* temp1 =
NULL;
2404 if (instr->access().IsExternalMemory() ||
2405 instr->field_representation().IsDouble()) {
2406 value = UseRegister(instr->value());
2407 }
else if (instr->NeedsWriteBarrier()) {
2408 value = UseRegisterAndClobber(instr->value());
2409 temp0 = TempRegister();
2410 temp1 = TempRegister();
2411 }
else if (instr->NeedsWriteBarrierForMap()) {
2412 value = UseRegister(instr->value());
2413 temp0 = TempRegister();
2414 temp1 = TempRegister();
2416 value = UseRegister(instr->value());
2417 temp0 = TempRegister();
2420 return new(zone()) LStoreNamedField(
object, value, temp0, temp1);
2424 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2425 LOperand* context = UseFixed(instr->context(),
cp);
2430 LInstruction* result =
new(zone()) LStoreNamedGeneric(context,
object, value);
2431 return MarkAsCall(result, instr);
2435 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2436 LOperand* context = UseFixed(instr->context(),
cp);
2437 LOperand* left = UseFixed(instr->left(), x1);
2438 LOperand* right = UseFixed(instr->right(), x0);
2440 LStringAdd* result =
new(zone()) LStringAdd(context, left, right);
2441 return MarkAsCall(DefineFixed(result, x0), instr);
2445 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2446 LOperand*
string = UseRegisterAndClobber(instr->string());
2447 LOperand* index = UseRegisterAndClobber(instr->index());
2448 LOperand* context = UseAny(instr->context());
2449 LStringCharCodeAt* result =
2450 new(zone()) LStringCharCodeAt(context,
string, index);
2451 return AssignPointerMap(DefineAsRegister(result));
2455 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2456 LOperand* char_code = UseRegister(instr->value());
2457 LOperand* context = UseAny(instr->context());
2458 LStringCharFromCode* result =
2459 new(zone()) LStringCharFromCode(context, char_code);
2460 return AssignPointerMap(DefineAsRegister(result));
2464 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
2465 HStringCompareAndBranch* instr) {
2466 DCHECK(instr->left()->representation().IsTagged());
2467 DCHECK(instr->right()->representation().IsTagged());
2468 LOperand* context = UseFixed(instr->context(),
cp);
2469 LOperand* left = UseFixed(instr->left(), x1);
2470 LOperand* right = UseFixed(instr->right(), x0);
2471 LStringCompareAndBranch* result =
2472 new(zone()) LStringCompareAndBranch(context, left, right);
2473 return MarkAsCall(result, instr);
2477 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
2478 if (instr->representation().IsSmiOrInteger32()) {
2479 DCHECK(instr->left()->representation().Equals(instr->representation()));
2480 DCHECK(instr->right()->representation().Equals(instr->representation()));
2482 LInstruction* shifted_operation = TryDoOpWithShiftedRightOperand(instr);
2483 if (shifted_operation !=
NULL) {
2484 return shifted_operation;
2488 if (instr->left()->IsConstant() &&
2489 (HConstant::cast(instr->left())->Integer32Value() == 0)) {
2490 left = UseConstant(instr->left());
2492 left = UseRegisterAtStart(instr->left());
2494 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
2495 LInstruction* result = instr->representation().IsSmi() ?
2496 DefineAsRegister(
new(zone()) LSubS(left, right)) :
2497 DefineAsRegister(new(zone()) LSubI(left, right));
2499 result = AssignEnvironment(result);
2502 }
else if (instr->representation().IsDouble()) {
2510 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
2511 if (instr->HasNoUses()) {
2514 return DefineAsRegister(
new(zone()) LThisFunction);
2519 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2520 LOperand*
object = UseFixed(instr->value(), x0);
2521 LToFastProperties* result =
new(zone()) LToFastProperties(
object);
2522 return MarkAsCall(DefineFixed(result, x0), instr);
2526 LInstruction* LChunkBuilder::DoTransitionElementsKind(
2527 HTransitionElementsKind* instr) {
2529 LOperand*
object = UseRegister(instr->object());
2530 LTransitionElementsKind* result =
2531 new(zone()) LTransitionElementsKind(
object,
NULL,
2532 TempRegister(), TempRegister());
2535 LOperand*
object = UseFixed(instr->object(), x0);
2536 LOperand* context = UseFixed(instr->context(),
cp);
2537 LTransitionElementsKind* result =
2538 new(zone()) LTransitionElementsKind(
object, context,
NULL,
NULL);
2539 return MarkAsCall(result, instr);
2544 LInstruction* LChunkBuilder::DoTrapAllocationMemento(
2545 HTrapAllocationMemento* instr) {
2546 LOperand*
object = UseRegister(instr->object());
2547 LOperand* temp1 = TempRegister();
2548 LOperand* temp2 = TempRegister();
2549 LTrapAllocationMemento* result =
2550 new(zone()) LTrapAllocationMemento(
object, temp1, temp2);
2551 return AssignEnvironment(result);
2555 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2556 LOperand* context = UseFixed(instr->context(),
cp);
2562 new(zone()) LTypeof(context, UseRegisterAtStart(instr->value()));
2563 return MarkAsCall(DefineFixed(result, x0), instr);
2567 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2570 LOperand* temp1 = TempRegister();
2571 LOperand* temp2 = TempRegister();
2573 return new(zone()) LTypeofIsAndBranch(
2574 UseRegister(instr->value()), temp1, temp2);
2578 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
2579 switch (instr->op()) {
2581 Representation r = instr->representation();
2585 LOperand* context = UseFixed(instr->context(),
cp);
2586 LOperand* input = UseRegister(instr->value());
2587 LOperand* temp1 = TempRegister();
2588 LOperand* temp2 = TempRegister();
2589 LOperand* temp3 = TempRegister();
2590 LInstruction* result = DefineAsRegister(
2591 new(zone()) LMathAbsTagged(context, input, temp1, temp2, temp3));
2592 return AssignEnvironment(AssignPointerMap(result));
2594 LOperand* input = UseRegisterAtStart(instr->value());
2595 LInstruction* result = DefineAsRegister(
new(zone()) LMathAbs(input));
2596 if (!r.IsDouble()) result = AssignEnvironment(result);
2601 DCHECK(instr->representation().IsDouble());
2602 DCHECK(instr->value()->representation().IsDouble());
2603 LOperand* input = UseRegister(instr->value());
2604 LOperand* double_temp1 = TempDoubleRegister();
2605 LOperand* temp1 = TempRegister();
2606 LOperand* temp2 = TempRegister();
2607 LOperand* temp3 = TempRegister();
2608 LMathExp* result =
new(zone()) LMathExp(input, double_temp1,
2609 temp1, temp2, temp3);
2610 return DefineAsRegister(result);
2613 DCHECK(instr->value()->representation().IsDouble());
2614 LOperand* input = UseRegisterAtStart(instr->value());
2615 if (instr->representation().IsInteger32()) {
2616 LMathFloorI* result =
new(zone()) LMathFloorI(input);
2617 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2619 DCHECK(instr->representation().IsDouble());
2620 LMathFloorD* result =
new(zone()) LMathFloorD(input);
2621 return DefineAsRegister(result);
2625 DCHECK(instr->representation().IsDouble());
2626 DCHECK(instr->value()->representation().IsDouble());
2627 LOperand* input = UseFixedDouble(instr->value(),
d0);
2628 LMathLog* result =
new(zone()) LMathLog(input);
2629 return MarkAsCall(DefineFixedDouble(result,
d0), instr);
2632 DCHECK(instr->representation().IsDouble());
2633 DCHECK(instr->value()->representation().IsDouble());
2634 LOperand* input = UseRegister(instr->value());
2635 return DefineAsRegister(
new(zone()) LMathPowHalf(input));
2638 DCHECK(instr->value()->representation().IsDouble());
2639 LOperand* input = UseRegister(instr->value());
2640 if (instr->representation().IsInteger32()) {
2641 LOperand* temp = TempDoubleRegister();
2642 LMathRoundI* result =
new(zone()) LMathRoundI(input, temp);
2643 return AssignEnvironment(DefineAsRegister(result));
2645 DCHECK(instr->representation().IsDouble());
2646 LMathRoundD* result =
new(zone()) LMathRoundD(input);
2647 return DefineAsRegister(result);
2651 DCHECK(instr->value()->representation().IsDouble());
2652 LOperand* input = UseRegister(instr->value());
2653 LMathFround* result =
new (zone()) LMathFround(input);
2654 return DefineAsRegister(result);
2657 DCHECK(instr->representation().IsDouble());
2658 DCHECK(instr->value()->representation().IsDouble());
2659 LOperand* input = UseRegisterAtStart(instr->value());
2660 return DefineAsRegister(
new(zone()) LMathSqrt(input));
2663 DCHECK(instr->representation().IsInteger32());
2664 DCHECK(instr->value()->representation().IsInteger32());
2665 LOperand* input = UseRegisterAtStart(instr->value());
2666 return DefineAsRegister(
new(zone()) LMathClz32(input));
2675 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2678 int env_index = instr->index();
2679 int spill_index = 0;
2680 if (instr->environment()->is_parameter_index(env_index)) {
2681 spill_index = chunk_->GetParameterStackSlot(env_index);
2683 spill_index = env_index - instr->environment()->first_local_index();
2685 Retry(kTooManySpillSlotsNeededForOSR);
2689 return DefineAsSpilled(
new(zone()) LUnknownOSRValue, spill_index);
2693 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
2698 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2699 LOperand* context = UseFixed(instr->context(),
cp);
2702 LOperand*
object = UseFixed(instr->enumerable(), x0);
2703 LForInPrepareMap* result =
new(zone()) LForInPrepareMap(context,
object);
2704 return MarkAsCall(DefineFixed(result, x0), instr, CAN_DEOPTIMIZE_EAGERLY);
2708 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2709 LOperand*
map = UseRegister(instr->map());
2710 return AssignEnvironment(DefineAsRegister(
new(zone()) LForInCacheArray(
map)));
2714 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2715 LOperand* value = UseRegisterAtStart(instr->value());
2716 LOperand*
map = UseRegister(instr->map());
2717 LOperand* temp = TempRegister();
2718 return AssignEnvironment(
new(zone()) LCheckMapValue(value,
map, temp));
2722 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2723 LOperand*
object = UseRegisterAtStart(instr->object());
2724 LOperand* index = UseRegisterAndClobber(instr->index());
2725 LLoadFieldByIndex* load =
new(zone()) LLoadFieldByIndex(
object, index);
2726 LInstruction* result = DefineSameAsFirst(load);
2727 return AssignPointerMap(result);
2731 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
2732 LOperand* receiver = UseRegister(instr->receiver());
2733 LOperand*
function = UseRegister(instr->function());
2734 LWrapReceiver* result =
new(zone()) LWrapReceiver(receiver,
function);
2735 return AssignEnvironment(DefineAsRegister(result));
2739 LInstruction* LChunkBuilder::DoStoreFrameContext(HStoreFrameContext* instr) {
2740 LOperand* context = UseRegisterAtStart(instr->context());
2741 return new(zone()) LStoreFrameContext(context);
2745 LInstruction* LChunkBuilder::DoAllocateBlockContext(
2746 HAllocateBlockContext* instr) {
2747 LOperand* context = UseFixed(instr->context(),
cp);
2748 LOperand*
function = UseRegisterAtStart(instr->function());
2749 LAllocateBlockContext* result =
2750 new(zone()) LAllocateBlockContext(context,
function);
2751 return MarkAsCall(DefineFixed(result,
cp), instr);
static HValue * cast(HValue *value)
@ kAllUsesTruncatingToInt32
virtual void PrintDataTo(StringStream *stream) OVERRIDE
LParallelMove * parallel_moves_[LAST_INNER_POSITION+1]
virtual int InputCount()=0
virtual bool HasResult() const =0
friend class TempIterator
bool HasPointerMap() const
virtual const char * Mnemonic() const =0
virtual void PrintTo(StringStream *stream)
LEnvironment * environment() const
virtual LOperand * InputAt(int i)=0
virtual void PrintDataTo(StringStream *stream)
virtual LOperand * result() const =0
bool HasEnvironment() const
virtual void PrintOutputOperandTo(StringStream *stream)
LPointerMap * pointer_map() const
void PrintTo(StringStream *stream)
static LUnallocated * cast(LOperand *op)
@ MUST_HAVE_DOUBLE_REGISTER
static const int kMaxFixedSlotIndex
bool HasFixedPolicy() const
void PrintDataTo(StringStream *stream) OVERRIDE
static const Register ReceiverRegister()
static const Register NameRegister()
static const Register exponent()
static const Register exponent()
static Representation Tagged()
static const int kMaxValue
static const int kMinValue
static const Register ReceiverRegister()
static const Register NameRegister()
static const Register ValueRegister()
static const char * String(Value tok)
static const Register VectorRegister()
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 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
enable harmony numeric enable harmony object literal extensions Optimize object Array shift
#define DEFINE_COMPILE(type)
#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
#define DCHECK(condition)
bool IsPowerOfTwo32(uint32_t value)
bool IsDoubleOrFloatElementsKind(ElementsKind kind)
const LowDwVfpRegister d1
const LowDwVfpRegister d0
DwVfpRegister DoubleRegister
@ EXTERNAL_UINT32_ELEMENTS
bool IsSimpleMapChangeTransition(ElementsKind from_kind, ElementsKind to_kind)
const char * ElementsKindToString(ElementsKind kind)
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
Debugger support for the V8 JavaScript engine.
static i::Handle< i::Context > CreateEnvironment(i::Isolate *isolate, v8::ExtensionConfiguration *extensions, v8::Handle< ObjectTemplate > global_template, v8::Handle< Value > maybe_global_proxy)
static int ToAllocationIndex(DwVfpRegister reg)
static int ToAllocationIndex(Register reg)