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());
44 stream->Add(
"%s ", this->
Mnemonic());
65 if (
i > 0) stream->Add(
" ");
80 void LLabel::PrintDataTo(StringStream* stream) {
82 LLabel* rep = replacement();
84 stream->Add(
" Dead block replaced with B%d", rep->block_id());
90 for (
int i = 0;
i < 4;
i++) {
101 for (
int i = 0;
i < 4;
i++) {
111 const char* LArithmeticD::Mnemonic()
const {
117 case Token::MOD:
return "mod-d";
125 const char* LArithmeticT::Mnemonic()
const {
130 case Token::MOD:
return "mod-t";
132 case Token::BIT_AND:
return "bit-and-t";
133 case Token::BIT_OR:
return "bit-or-t";
134 case Token::BIT_XOR:
return "bit-xor-t";
136 case Token::SHL:
return "shl-t";
137 case Token::SAR:
return "sar-t";
138 case Token::SHR:
return "shr-t";
146 bool LGoto::HasInterestingComment(LCodeGen* gen)
const {
147 return !gen->IsNextEmittedBlock(block_id());
151 void LGoto::PrintDataTo(StringStream* stream) {
152 stream->Add(
"B%d", block_id());
156 void LBranch::PrintDataTo(StringStream* stream) {
157 stream->Add(
"B%d | B%d on ", true_block_id(), false_block_id());
158 value()->PrintTo(stream);
162 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
164 left()->PrintTo(stream);
166 right()->PrintTo(stream);
167 stream->Add(
" then B%d else B%d", true_block_id(), false_block_id());
171 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
172 stream->Add(
"if is_object(");
173 value()->PrintTo(stream);
174 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
178 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
179 stream->Add(
"if is_string(");
180 value()->PrintTo(stream);
181 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
185 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
186 stream->Add(
"if is_smi(");
187 value()->PrintTo(stream);
188 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
192 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
193 stream->Add(
"if is_undetectable(");
194 value()->PrintTo(stream);
195 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
199 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
200 stream->Add(
"if string_compare(");
201 left()->PrintTo(stream);
202 right()->PrintTo(stream);
203 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
207 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
208 stream->Add(
"if has_instance_type(");
209 value()->PrintTo(stream);
210 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
214 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
215 stream->Add(
"if has_cached_array_index(");
216 value()->PrintTo(stream);
217 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
221 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
222 stream->Add(
"if class_of_test(");
223 value()->PrintTo(stream);
224 stream->Add(
", \"%o\") then B%d else B%d",
225 *hydrogen()->class_name(),
231 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
232 stream->Add(
"if typeof ");
233 value()->PrintTo(stream);
234 stream->Add(
" == \"%s\" then B%d else B%d",
235 hydrogen()->type_literal()->ToCString().get(),
236 true_block_id(), false_block_id());
240 void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
242 function()->PrintTo(stream);
243 stream->Add(
".code_entry = ");
244 code_object()->PrintTo(stream);
248 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
250 base_object()->PrintTo(stream);
252 offset()->PrintTo(stream);
256 void LCallJSFunction::PrintDataTo(StringStream* stream) {
258 function()->PrintTo(stream);
259 stream->Add(
"#%d / ", arity());
263 void LCallWithDescriptor::PrintDataTo(StringStream* stream) {
264 for (
int i = 0;
i < InputCount();
i++) {
265 InputAt(
i)->PrintTo(stream);
268 stream->Add(
"#%d / ", arity());
272 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
273 context()->PrintTo(stream);
274 stream->Add(
"[%d]", slot_index());
278 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
279 context()->PrintTo(stream);
280 stream->Add(
"[%d] <- ", slot_index());
281 value()->PrintTo(stream);
285 void LInvokeFunction::PrintDataTo(StringStream* stream) {
287 function()->PrintTo(stream);
288 stream->Add(
" #%d / ", arity());
292 void LCallNew::PrintDataTo(StringStream* stream) {
294 constructor()->PrintTo(stream);
295 stream->Add(
" #%d / ", arity());
299 void LCallNewArray::PrintDataTo(StringStream* stream) {
301 constructor()->PrintTo(stream);
302 stream->Add(
" #%d / ", arity());
308 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
309 arguments()->PrintTo(stream);
310 stream->Add(
" length ");
311 length()->PrintTo(stream);
312 stream->Add(
" index ");
313 index()->PrintTo(stream);
317 void LStoreNamedField::PrintDataTo(StringStream* stream) {
318 object()->PrintTo(stream);
320 os << hydrogen()->access() <<
" <- ";
321 stream->Add(os.c_str());
322 value()->PrintTo(stream);
326 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
327 object()->PrintTo(stream);
329 stream->Add(String::cast(*
name())->ToCString().get());
331 value()->PrintTo(stream);
339 if (hydrogen()->IsDehoisted()) {
351 if (hydrogen()->IsDehoisted()) {
354 stream->Add(
"] <- ");
358 DCHECK(hydrogen()->IsConstantHoleStore() &&
359 hydrogen()->
value()->representation().IsDouble());
360 stream->Add(
"<the hole(nan)>");
367 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
368 object()->PrintTo(stream);
370 key()->PrintTo(stream);
371 stream->Add(
"] <- ");
372 value()->PrintTo(stream);
376 void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
377 object()->PrintTo(stream);
378 stream->Add(
" %p -> %p", *original_map(), *transitioned_map());
382 int LPlatformChunk::GetNextSpillIndex(
RegisterKind kind) {
385 return spill_slot_count_++;
389 LOperand* LPlatformChunk::GetNextSpillSlot(
RegisterKind kind) {
390 int index = GetNextSpillIndex(kind);
392 return LDoubleStackSlot::Create(index, zone());
395 return LStackSlot::Create(index, zone());
400 LPlatformChunk* LChunkBuilder::Build() {
402 chunk_ =
new(zone()) LPlatformChunk(info(), graph());
403 LPhase phase(
"L_Building chunk", chunk_);
408 if (graph()->has_osr()) {
409 for (
int i = graph()->osr()->UnoptimizedFrameSlots();
i > 0;
i--) {
414 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
415 for (
int i = 0;
i < blocks->length();
i++) {
416 HBasicBlock* next =
NULL;
417 if (i < blocks->length() - 1) next = blocks->at(
i + 1);
418 DoBasicBlock(blocks->at(
i), next);
419 if (is_aborted())
return NULL;
426 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
438 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
439 return Use(value, ToUnallocated(fixed_register));
443 LOperand* LChunkBuilder::UseFixedDouble(HValue* value,
DoubleRegister reg) {
444 return Use(value, ToUnallocated(reg));
448 LOperand* LChunkBuilder::UseRegister(HValue* value) {
453 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
460 LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
465 LOperand* LChunkBuilder::Use(HValue* value) {
470 LOperand* LChunkBuilder::UseAtStart(HValue* value) {
476 LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
477 return value->IsConstant()
478 ? chunk_->DefineConstantOperand(HConstant::cast(value))
483 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
484 return value->IsConstant()
485 ? chunk_->DefineConstantOperand(HConstant::cast(value))
490 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
491 return value->IsConstant()
492 ? chunk_->DefineConstantOperand(HConstant::cast(value))
493 : UseRegister(value);
497 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
498 return value->IsConstant()
499 ? chunk_->DefineConstantOperand(HConstant::cast(value))
500 : UseRegisterAtStart(value);
504 LOperand* LChunkBuilder::UseConstant(HValue* value) {
505 return chunk_->DefineConstantOperand(HConstant::cast(value));
509 LOperand* LChunkBuilder::UseAny(HValue* value) {
510 return value->IsConstant()
511 ? chunk_->DefineConstantOperand(HConstant::cast(value))
516 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
517 if (value->EmitAtUses()) {
519 VisitInstruction(instr);
521 operand->set_virtual_register(value->id());
526 LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr,
527 LUnallocated* result) {
528 result->set_virtual_register(current_instruction_->id());
529 instr->set_result(result);
534 LInstruction* LChunkBuilder::DefineAsRegister(
535 LTemplateResultInstruction<1>* instr) {
541 LInstruction* LChunkBuilder::DefineAsSpilled(
542 LTemplateResultInstruction<1>* instr,
int index) {
548 LInstruction* LChunkBuilder::DefineSameAsFirst(
549 LTemplateResultInstruction<1>* instr) {
555 LInstruction* LChunkBuilder::DefineFixed(
556 LTemplateResultInstruction<1>* instr, Register reg) {
557 return Define(instr, ToUnallocated(reg));
561 LInstruction* LChunkBuilder::DefineFixedDouble(
563 return Define(instr, ToUnallocated(reg));
567 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
568 HEnvironment* hydrogen_env = current_block_->last_environment();
569 int argument_index_accumulator = 0;
570 ZoneList<HValue*> objects_to_materialize(0, zone());
572 &argument_index_accumulator,
573 &objects_to_materialize));
578 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
579 HInstruction* hinstr,
580 CanDeoptimize can_deoptimize) {
581 info()->MarkAsNonDeferredCalling();
586 instr = AssignPointerMap(instr);
592 bool needs_environment =
593 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
594 !hinstr->HasObservableSideEffects();
595 if (needs_environment && !instr->HasEnvironment()) {
596 instr = AssignEnvironment(instr);
598 instr->environment()->set_has_been_used();
605 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
606 DCHECK(!instr->HasPointerMap());
607 instr->set_pointer_map(
new(zone()) LPointerMap(zone()));
612 LUnallocated* LChunkBuilder::TempRegister() {
613 LUnallocated* operand =
615 int vreg = allocator_->GetVirtualRegister();
616 if (!allocator_->AllocationOk()) {
617 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
620 operand->set_virtual_register(vreg);
625 LUnallocated* LChunkBuilder::TempDoubleRegister() {
626 LUnallocated* operand =
628 int vreg = allocator_->GetVirtualRegister();
629 if (!allocator_->AllocationOk()) {
630 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
633 operand->set_virtual_register(vreg);
638 LOperand* LChunkBuilder::FixedTemp(Register reg) {
639 LUnallocated* operand = ToUnallocated(reg);
640 DCHECK(operand->HasFixedPolicy());
646 LUnallocated* operand = ToUnallocated(reg);
647 DCHECK(operand->HasFixedPolicy());
652 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
653 return new(zone()) LLabel(instr->block());
657 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
658 return DefineAsRegister(
new(zone()) LDummyUse(UseAny(instr->value())));
662 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
668 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
669 return AssignEnvironment(
new(zone()) LDeoptimize);
674 HBitwiseBinaryOperation* instr) {
675 if (instr->representation().IsSmiOrInteger32()) {
676 DCHECK(instr->left()->representation().Equals(instr->representation()));
677 DCHECK(instr->right()->representation().Equals(instr->representation()));
678 LOperand* left = UseRegisterAtStart(instr->left());
680 HValue* right_value = instr->right();
681 LOperand* right =
NULL;
682 int constant_value = 0;
683 bool does_deopt =
false;
684 if (right_value->IsConstant()) {
685 HConstant* constant = HConstant::cast(right_value);
686 right = chunk_->DefineConstantOperand(constant);
687 constant_value = constant->Integer32Value() & 0x1f;
690 if (instr->representation().IsSmi() && constant_value > 0) {
694 right = UseRegisterAtStart(right_value);
699 if (op == Token::SHR && constant_value == 0) {
700 if (FLAG_opt_safe_uint32_operations) {
707 LInstruction* result =
708 DefineAsRegister(
new(zone()) LShiftI(op, left, right, does_deopt));
709 return does_deopt ? AssignEnvironment(result) : result;
711 return DoArithmeticT(op, instr);
716 LInstruction* LChunkBuilder::DoArithmeticD(
Token::Value op,
717 HArithmeticBinaryOperation* instr) {
718 DCHECK(instr->representation().IsDouble());
719 DCHECK(instr->left()->representation().IsDouble());
720 DCHECK(instr->right()->representation().IsDouble());
721 if (op == Token::MOD) {
722 LOperand* left = UseFixedDouble(instr->left(),
d0);
723 LOperand* right = UseFixedDouble(instr->right(),
d1);
724 LArithmeticD* result =
new(zone()) LArithmeticD(op, left, right);
725 return MarkAsCall(DefineFixedDouble(result,
d0), instr);
727 LOperand* left = UseRegisterAtStart(instr->left());
728 LOperand* right = UseRegisterAtStart(instr->right());
729 LArithmeticD* result =
new(zone()) LArithmeticD(op, left, right);
730 return DefineAsRegister(result);
735 LInstruction* LChunkBuilder::DoArithmeticT(
Token::Value op,
736 HBinaryOperation* instr) {
737 HValue* left = instr->left();
738 HValue* right = instr->right();
739 DCHECK(left->representation().IsTagged());
740 DCHECK(right->representation().IsTagged());
741 LOperand* context = UseFixed(instr->context(),
cp);
742 LOperand* left_operand = UseFixed(left,
r1);
743 LOperand* right_operand = UseFixed(right,
r0);
744 LArithmeticT* result =
745 new(zone()) LArithmeticT(op, context, left_operand, right_operand);
746 return MarkAsCall(DefineFixed(result,
r0), instr);
750 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
752 current_block_ = block;
753 next_block_ = next_block;
754 if (block->IsStartBlock()) {
755 block->UpdateEnvironment(graph_->start_environment());
757 }
else if (block->predecessors()->length() == 1) {
760 DCHECK(block->phis()->length() == 0);
761 HBasicBlock* pred = block->predecessors()->at(0);
762 HEnvironment* last_environment = pred->last_environment();
765 if (pred->end()->SecondSuccessor() ==
NULL) {
766 DCHECK(pred->end()->FirstSuccessor() == block);
768 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
769 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
770 last_environment = last_environment->Copy();
773 block->UpdateEnvironment(last_environment);
774 DCHECK(pred->argument_count() >= 0);
775 argument_count_ = pred->argument_count();
778 HBasicBlock* pred = block->predecessors()->at(0);
780 HEnvironment* last_environment = pred->last_environment();
781 for (
int i = 0;
i < block->phis()->length(); ++
i) {
782 HPhi* phi = block->phis()->at(
i);
783 if (phi->HasMergedIndex()) {
784 last_environment->SetValueAt(phi->merged_index(), phi);
787 for (
int i = 0;
i < block->deleted_phis()->length(); ++
i) {
788 if (block->deleted_phis()->at(
i) < last_environment->length()) {
789 last_environment->SetValueAt(block->deleted_phis()->at(
i),
790 graph_->GetConstantUndefined());
793 block->UpdateEnvironment(last_environment);
795 argument_count_ = pred->argument_count();
797 HInstruction* current = block->first();
798 int start = chunk_->instructions()->length();
799 while (current !=
NULL && !is_aborted()) {
801 if (!current->EmitAtUses()) {
802 VisitInstruction(current);
804 current = current->next();
806 int end = chunk_->instructions()->length() - 1;
808 block->set_first_instruction_index(start);
809 block->set_last_instruction_index(end);
811 block->set_argument_count(argument_count_);
813 current_block_ =
NULL;
817 void LChunkBuilder::VisitInstruction(HInstruction* current) {
818 HInstruction* old_current = current_instruction_;
819 current_instruction_ = current;
821 LInstruction* instr =
NULL;
822 if (current->CanReplaceWithDummyUses()) {
823 if (current->OperandCount() == 0) {
824 instr = DefineAsRegister(
new(zone()) LDummy());
826 DCHECK(!current->OperandAt(0)->IsControlInstruction());
827 instr = DefineAsRegister(
new(zone())
828 LDummyUse(UseAny(current->OperandAt(0))));
830 for (
int i = 1;
i < current->OperandCount(); ++
i) {
831 if (current->OperandAt(
i)->IsControlInstruction())
continue;
832 LInstruction* dummy =
833 new(zone()) LDummyUse(UseAny(current->OperandAt(
i)));
834 dummy->set_hydrogen_value(current);
835 chunk_->AddInstruction(dummy, current_block_);
838 HBasicBlock* successor;
839 if (current->IsControlInstruction() &&
842 instr =
new(zone()) LGoto(successor);
844 instr = current->CompileToLithium(
this);
848 argument_count_ += current->argument_delta();
849 DCHECK(argument_count_ >= 0);
852 AddInstruction(instr, current);
855 current_instruction_ = old_current;
859 void LChunkBuilder::AddInstruction(LInstruction* instr,
860 HInstruction* hydrogen_val) {
863 instr->set_hydrogen_value(hydrogen_val);
876 if (!(instr->ClobbersRegisters() &&
877 instr->ClobbersDoubleRegisters(isolate()))) {
879 int used_at_start = 0;
880 for (UseIterator it(instr); !it.Done(); it.Advance()) {
882 if (operand->IsUsedAtStart()) ++used_at_start;
884 if (instr->Output() !=
NULL) {
887 for (TempIterator it(instr); !it.Done(); it.Advance()) {
889 if (operand->HasFixedPolicy()) ++fixed;
891 DCHECK(fixed == 0 || used_at_start == 0);
895 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
896 instr = AssignPointerMap(instr);
898 if (FLAG_stress_environments && !instr->HasEnvironment()) {
899 instr = AssignEnvironment(instr);
901 chunk_->AddInstruction(instr, current_block_);
903 if (instr->IsCall()) {
904 HValue* hydrogen_value_for_lazy_bailout = hydrogen_val;
905 LInstruction* instruction_needing_environment =
NULL;
906 if (hydrogen_val->HasObservableSideEffects()) {
907 HSimulate* sim = HSimulate::cast(hydrogen_val->next());
908 instruction_needing_environment = instr;
909 sim->ReplayEnvironment(current_block_->last_environment());
910 hydrogen_value_for_lazy_bailout = sim;
912 LInstruction* bailout = AssignEnvironment(
new(zone()) LLazyBailout());
913 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
914 chunk_->AddInstruction(bailout, current_block_);
915 if (instruction_needing_environment !=
NULL) {
918 instruction_needing_environment->
919 SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
925 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
926 return new(zone()) LGoto(instr->FirstSuccessor());
930 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
931 HValue* value = instr->value();
932 Representation r = value->representation();
933 HType type = value->type();
934 ToBooleanStub::Types expected = instr->expected_input_types();
937 bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() ||
938 type.IsJSArray() || type.IsHeapNumber() || type.IsString();
939 LInstruction* branch =
new(zone()) LBranch(UseRegister(value));
942 !expected.IsGeneric())) {
943 branch = AssignEnvironment(branch);
949 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
950 return new(zone()) LDebugBreak();
954 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
955 DCHECK(instr->value()->representation().IsTagged());
956 LOperand* value = UseRegisterAtStart(instr->value());
957 LOperand* temp = TempRegister();
958 return new(zone()) LCmpMapAndBranch(value, temp);
962 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) {
963 info()->MarkAsRequiresFrame();
964 LOperand* value = UseRegister(instr->value());
965 return DefineAsRegister(
new(zone()) LArgumentsLength(value));
969 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
970 info()->MarkAsRequiresFrame();
971 return DefineAsRegister(
new(zone()) LArgumentsElements);
975 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
976 LOperand* context = UseFixed(instr->context(),
cp);
977 LInstanceOf* result =
978 new(zone()) LInstanceOf(context, UseFixed(instr->left(),
r0),
979 UseFixed(instr->right(),
r1));
980 return MarkAsCall(DefineFixed(result,
r0), instr);
984 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
985 HInstanceOfKnownGlobal* instr) {
986 LInstanceOfKnownGlobal* result =
987 new(zone()) LInstanceOfKnownGlobal(
988 UseFixed(instr->context(),
cp),
989 UseFixed(instr->left(),
r0),
991 return MarkAsCall(DefineFixed(result,
r0), instr);
995 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
996 LOperand* receiver = UseRegisterAtStart(instr->receiver());
997 LOperand*
function = UseRegisterAtStart(instr->function());
998 LWrapReceiver* result =
new(zone()) LWrapReceiver(receiver,
function);
999 return AssignEnvironment(DefineAsRegister(result));
1003 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1004 LOperand*
function = UseFixed(instr->function(),
r1);
1005 LOperand* receiver = UseFixed(instr->receiver(),
r0);
1006 LOperand* length = UseFixed(instr->length(),
r2);
1007 LOperand* elements = UseFixed(instr->elements(),
r3);
1008 LApplyArguments* result =
new(zone()) LApplyArguments(
function,
1012 return MarkAsCall(DefineFixed(result,
r0), instr, CAN_DEOPTIMIZE_EAGERLY);
1016 LInstruction* LChunkBuilder::DoPushArguments(HPushArguments* instr) {
1017 int argc = instr->OperandCount();
1018 for (
int i = 0;
i < argc; ++
i) {
1019 LOperand* argument = Use(instr->argument(
i));
1020 AddInstruction(
new(zone()) LPushArgument(argument), instr);
1026 LInstruction* LChunkBuilder::DoStoreCodeEntry(
1027 HStoreCodeEntry* store_code_entry) {
1028 LOperand*
function = UseRegister(store_code_entry->function());
1029 LOperand* code_object = UseTempRegister(store_code_entry->code_object());
1030 return new(zone()) LStoreCodeEntry(
function, code_object);
1034 LInstruction* LChunkBuilder::DoInnerAllocatedObject(
1035 HInnerAllocatedObject* instr) {
1036 LOperand* base_object = UseRegisterAtStart(instr->base_object());
1037 LOperand* offset = UseRegisterOrConstantAtStart(instr->offset());
1038 return DefineAsRegister(
1039 new(zone()) LInnerAllocatedObject(base_object, offset));
1043 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
1044 return instr->HasNoUses()
1046 : DefineAsRegister(
new(zone()) LThisFunction);
1050 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1051 if (instr->HasNoUses())
return NULL;
1053 if (info()->IsStub()) {
1054 return DefineFixed(
new(zone()) LContext,
cp);
1057 return DefineAsRegister(
new(zone()) LContext);
1061 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1062 LOperand* context = UseFixed(instr->context(),
cp);
1063 return MarkAsCall(
new(zone()) LDeclareGlobals(context), instr);
1067 LInstruction* LChunkBuilder::DoCallJSFunction(
1068 HCallJSFunction* instr) {
1069 LOperand*
function = UseFixed(instr->function(),
r1);
1071 LCallJSFunction* result =
new(zone()) LCallJSFunction(
function);
1073 return MarkAsCall(DefineFixed(result,
r0), instr);
1077 LInstruction* LChunkBuilder::DoCallWithDescriptor(
1078 HCallWithDescriptor* instr) {
1079 CallInterfaceDescriptor descriptor = instr->descriptor();
1081 LOperand* target = UseRegisterOrConstantAtStart(instr->target());
1082 ZoneList<LOperand*> ops(instr->OperandCount(), zone());
1083 ops.Add(target, zone());
1084 for (
int i = 1;
i < instr->OperandCount();
i++) {
1086 UseFixed(instr->OperandAt(
i), descriptor.GetParameterRegister(
i - 1));
1087 ops.Add(op, zone());
1090 LCallWithDescriptor* result =
new(zone()) LCallWithDescriptor(
1091 descriptor, ops, zone());
1092 return MarkAsCall(DefineFixed(result,
r0), instr);
1096 LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
1097 HTailCallThroughMegamorphicCache* instr) {
1098 LOperand* context = UseFixed(instr->context(),
cp);
1099 LOperand* receiver_register =
1101 LOperand* name_register =
1104 return new (zone()) LTailCallThroughMegamorphicCache(
1105 context, receiver_register, name_register);
1109 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1110 LOperand* context = UseFixed(instr->context(),
cp);
1111 LOperand*
function = UseFixed(instr->function(),
r1);
1112 LInvokeFunction* result =
new(zone()) LInvokeFunction(context,
function);
1113 return MarkAsCall(DefineFixed(result,
r0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1117 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1118 switch (instr->op()) {
1120 return DoMathFloor(instr);
1122 return DoMathRound(instr);
1124 return DoMathFround(instr);
1126 return DoMathAbs(instr);
1128 return DoMathLog(instr);
1130 return DoMathExp(instr);
1132 return DoMathSqrt(instr);
1134 return DoMathPowHalf(instr);
1136 return DoMathClz32(instr);
1144 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
1145 LOperand* input = UseRegister(instr->value());
1146 LMathFloor* result =
new(zone()) LMathFloor(input);
1147 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1151 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
1152 LOperand* input = UseRegister(instr->value());
1153 LOperand* temp = TempDoubleRegister();
1154 LMathRound* result =
new(zone()) LMathRound(input, temp);
1155 return AssignEnvironment(DefineAsRegister(result));
1159 LInstruction* LChunkBuilder::DoMathFround(HUnaryMathOperation* instr) {
1160 LOperand* input = UseRegister(instr->value());
1161 LMathFround* result =
new (zone()) LMathFround(input);
1162 return DefineAsRegister(result);
1166 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1167 Representation r = instr->value()->representation();
1168 LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32())
1170 : UseFixed(instr->context(),
cp);
1171 LOperand* input = UseRegister(instr->value());
1172 LInstruction* result =
1173 DefineAsRegister(
new(zone()) LMathAbs(context, input));
1174 if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result);
1175 if (!r.IsDouble()) result = AssignEnvironment(result);
1180 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
1181 DCHECK(instr->representation().IsDouble());
1182 DCHECK(instr->value()->representation().IsDouble());
1183 LOperand* input = UseFixedDouble(instr->value(),
d0);
1184 return MarkAsCall(DefineFixedDouble(
new(zone()) LMathLog(input),
d0), instr);
1188 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
1189 LOperand* input = UseRegisterAtStart(instr->value());
1190 LMathClz32* result =
new(zone()) LMathClz32(input);
1191 return DefineAsRegister(result);
1195 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1196 DCHECK(instr->representation().IsDouble());
1197 DCHECK(instr->value()->representation().IsDouble());
1198 LOperand* input = UseRegister(instr->value());
1199 LOperand* temp1 = TempRegister();
1200 LOperand* temp2 = TempRegister();
1201 LOperand* double_temp = TempDoubleRegister();
1202 LMathExp* result =
new(zone()) LMathExp(input, double_temp, temp1, temp2);
1203 return DefineAsRegister(result);
1207 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
1208 LOperand* input = UseRegisterAtStart(instr->value());
1209 LMathSqrt* result =
new(zone()) LMathSqrt(input);
1210 return DefineAsRegister(result);
1214 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) {
1215 LOperand* input = UseRegisterAtStart(instr->value());
1216 LMathPowHalf* result =
new(zone()) LMathPowHalf(input);
1217 return DefineAsRegister(result);
1221 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1222 LOperand* context = UseFixed(instr->context(),
cp);
1223 LOperand* constructor = UseFixed(instr->constructor(),
r1);
1224 LCallNew* result =
new(zone()) LCallNew(context, constructor);
1225 return MarkAsCall(DefineFixed(result,
r0), instr);
1229 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1230 LOperand* context = UseFixed(instr->context(),
cp);
1231 LOperand* constructor = UseFixed(instr->constructor(),
r1);
1232 LCallNewArray* result =
new(zone()) LCallNewArray(context, constructor);
1233 return MarkAsCall(DefineFixed(result,
r0), instr);
1237 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1238 LOperand* context = UseFixed(instr->context(),
cp);
1239 LOperand*
function = UseFixed(instr->function(),
r1);
1240 LCallFunction* call =
new(zone()) LCallFunction(context,
function);
1241 return MarkAsCall(DefineFixed(call,
r0), instr);
1245 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1246 LOperand* context = UseFixed(instr->context(),
cp);
1247 return MarkAsCall(DefineFixed(
new(zone()) LCallRuntime(context),
r0), instr);
1251 LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1256 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1257 return DoShift(Token::SHR, instr);
1261 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1262 return DoShift(Token::SAR, instr);
1266 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1267 return DoShift(Token::SHL, instr);
1271 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1272 if (instr->representation().IsSmiOrInteger32()) {
1273 DCHECK(instr->left()->representation().Equals(instr->representation()));
1274 DCHECK(instr->right()->representation().Equals(instr->representation()));
1277 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1278 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1279 return DefineAsRegister(
new(zone()) LBitI(left, right));
1281 return DoArithmeticT(instr->op(), instr);
1286 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) {
1287 DCHECK(instr->representation().IsSmiOrInteger32());
1288 DCHECK(instr->left()->representation().Equals(instr->representation()));
1289 DCHECK(instr->right()->representation().Equals(instr->representation()));
1290 LOperand* dividend = UseRegister(instr->left());
1291 int32_t divisor = instr->right()->GetInteger32Constant();
1292 LInstruction* result = DefineAsRegister(
new(zone()) LDivByPowerOf2I(
1293 dividend, divisor));
1297 divisor != 1 && divisor != -1)) {
1298 result = AssignEnvironment(result);
1304 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) {
1305 DCHECK(instr->representation().IsInteger32());
1306 DCHECK(instr->left()->representation().Equals(instr->representation()));
1307 DCHECK(instr->right()->representation().Equals(instr->representation()));
1308 LOperand* dividend = UseRegister(instr->left());
1309 int32_t divisor = instr->right()->GetInteger32Constant();
1310 LInstruction* result = DefineAsRegister(
new(zone()) LDivByConstI(
1311 dividend, divisor));
1315 result = AssignEnvironment(result);
1321 LInstruction* LChunkBuilder::DoDivI(HDiv* instr) {
1322 DCHECK(instr->representation().IsSmiOrInteger32());
1323 DCHECK(instr->left()->representation().Equals(instr->representation()));
1324 DCHECK(instr->right()->representation().Equals(instr->representation()));
1325 LOperand* dividend = UseRegister(instr->left());
1326 LOperand* divisor = UseRegister(instr->right());
1329 LInstruction* result =
1330 DefineAsRegister(
new(zone()) LDivI(dividend, divisor, temp));
1336 (!instr->IsMathFloorOfDiv() &&
1338 result = AssignEnvironment(result);
1344 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1345 if (instr->representation().IsSmiOrInteger32()) {
1346 if (instr->RightIsPowerOf2()) {
1347 return DoDivByPowerOf2I(instr);
1348 }
else if (instr->right()->IsConstant()) {
1349 return DoDivByConstI(instr);
1351 return DoDivI(instr);
1353 }
else if (instr->representation().IsDouble()) {
1361 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
1362 LOperand* dividend = UseRegisterAtStart(instr->left());
1363 int32_t divisor = instr->right()->GetInteger32Constant();
1364 LInstruction* result = DefineAsRegister(
new(zone()) LFlooringDivByPowerOf2I(
1365 dividend, divisor));
1368 result = AssignEnvironment(result);
1374 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
1375 DCHECK(instr->representation().IsInteger32());
1376 DCHECK(instr->left()->representation().Equals(instr->representation()));
1377 DCHECK(instr->right()->representation().Equals(instr->representation()));
1378 LOperand* dividend = UseRegister(instr->left());
1379 int32_t divisor = instr->right()->GetInteger32Constant();
1383 NULL : TempRegister();
1384 LInstruction* result = DefineAsRegister(
1385 new(zone()) LFlooringDivByConstI(dividend, divisor, temp));
1388 result = AssignEnvironment(result);
1394 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) {
1395 DCHECK(instr->representation().IsSmiOrInteger32());
1396 DCHECK(instr->left()->representation().Equals(instr->representation()));
1397 DCHECK(instr->right()->representation().Equals(instr->representation()));
1398 LOperand* dividend = UseRegister(instr->left());
1399 LOperand* divisor = UseRegister(instr->right());
1402 LFlooringDivI* div =
new(zone()) LFlooringDivI(dividend, divisor, temp);
1403 return AssignEnvironment(DefineAsRegister(div));
1407 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1408 if (instr->RightIsPowerOf2()) {
1409 return DoFlooringDivByPowerOf2I(instr);
1410 }
else if (instr->right()->IsConstant()) {
1411 return DoFlooringDivByConstI(instr);
1413 return DoFlooringDivI(instr);
1418 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* 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 = UseRegisterAtStart(instr->left());
1423 int32_t divisor = instr->right()->GetInteger32Constant();
1424 LInstruction* result = DefineSameAsFirst(
new(zone()) LModByPowerOf2I(
1425 dividend, divisor));
1428 result = AssignEnvironment(result);
1434 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) {
1435 DCHECK(instr->representation().IsSmiOrInteger32());
1436 DCHECK(instr->left()->representation().Equals(instr->representation()));
1437 DCHECK(instr->right()->representation().Equals(instr->representation()));
1438 LOperand* dividend = UseRegister(instr->left());
1439 int32_t divisor = instr->right()->GetInteger32Constant();
1440 LInstruction* result = DefineAsRegister(
new(zone()) LModByConstI(
1441 dividend, divisor));
1443 result = AssignEnvironment(result);
1449 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
1450 DCHECK(instr->representation().IsSmiOrInteger32());
1451 DCHECK(instr->left()->representation().Equals(instr->representation()));
1452 DCHECK(instr->right()->representation().Equals(instr->representation()));
1453 LOperand* dividend = UseRegister(instr->left());
1454 LOperand* divisor = UseRegister(instr->right());
1459 LInstruction* result = DefineAsRegister(
new(zone()) LModI(
1460 dividend, divisor, temp, temp2));
1463 result = AssignEnvironment(result);
1469 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1470 if (instr->representation().IsSmiOrInteger32()) {
1471 if (instr->RightIsPowerOf2()) {
1472 return DoModByPowerOf2I(instr);
1473 }
else if (instr->right()->IsConstant()) {
1474 return DoModByConstI(instr);
1476 return DoModI(instr);
1478 }
else if (instr->representation().IsDouble()) {
1479 return DoArithmeticD(Token::MOD, instr);
1481 return DoArithmeticT(Token::MOD, instr);
1486 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1487 if (instr->representation().IsSmiOrInteger32()) {
1488 DCHECK(instr->left()->representation().Equals(instr->representation()));
1489 DCHECK(instr->right()->representation().Equals(instr->representation()));
1490 HValue* left = instr->BetterLeftOperand();
1491 HValue* right = instr->BetterRightOperand();
1497 if (right->IsConstant()) {
1498 HConstant* constant = HConstant::cast(right);
1499 int32_t constant_value = constant->Integer32Value();
1502 if (!can_overflow || ((constant_value >= -1) && (constant_value <= 1))) {
1503 left_op = UseRegisterAtStart(left);
1504 right_op = UseConstant(right);
1506 if (bailout_on_minus_zero) {
1507 left_op = UseRegister(left);
1509 left_op = UseRegisterAtStart(left);
1511 right_op = UseRegister(right);
1514 if (bailout_on_minus_zero) {
1515 left_op = UseRegister(left);
1517 left_op = UseRegisterAtStart(left);
1519 right_op = UseRegister(right);
1521 LMulI* mul =
new(zone()) LMulI(left_op, right_op);
1522 if (can_overflow || bailout_on_minus_zero) {
1523 AssignEnvironment(mul);
1525 return DefineAsRegister(mul);
1527 }
else if (instr->representation().IsDouble()) {
1528 if (instr->HasOneUse() && (instr->uses().value()->IsAdd() ||
1529 instr->uses().value()->IsSub())) {
1532 if (
use->IsAdd() && instr ==
use->left()) {
1537 if (instr ==
use->right() &&
use->IsAdd() && !
use->left()->IsMul()) {
1542 if (instr ==
use->right() &&
use->IsSub()) {
1556 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1557 if (instr->representation().IsSmiOrInteger32()) {
1558 DCHECK(instr->left()->representation().Equals(instr->representation()));
1559 DCHECK(instr->right()->representation().Equals(instr->representation()));
1561 if (instr->left()->IsConstant()) {
1563 return DoRSub(instr);
1566 LOperand* left = UseRegisterAtStart(instr->left());
1567 LOperand* right = UseOrConstantAtStart(instr->right());
1568 LSubI* sub =
new(zone()) LSubI(left, right);
1569 LInstruction* result = DefineAsRegister(sub);
1571 result = AssignEnvironment(result);
1574 }
else if (instr->representation().IsDouble()) {
1575 if (instr->right()->IsMul() && instr->right()->HasOneUse()) {
1576 return DoMultiplySub(instr->left(), HMul::cast(instr->right()));
1586 LInstruction* LChunkBuilder::DoRSub(HSub* instr) {
1587 DCHECK(instr->representation().IsSmiOrInteger32());
1588 DCHECK(instr->left()->representation().Equals(instr->representation()));
1589 DCHECK(instr->right()->representation().Equals(instr->representation()));
1593 LOperand* left = UseRegisterAtStart(instr->right());
1594 LOperand* right = UseOrConstantAtStart(instr->left());
1595 LRSubI* rsb =
new(zone()) LRSubI(left, right);
1596 LInstruction* result = DefineAsRegister(rsb);
1598 result = AssignEnvironment(result);
1604 LInstruction* LChunkBuilder::DoMultiplyAdd(HMul* mul, HValue* addend) {
1605 LOperand* multiplier_op = UseRegisterAtStart(mul->left());
1606 LOperand* multiplicand_op = UseRegisterAtStart(mul->right());
1607 LOperand* addend_op = UseRegisterAtStart(addend);
1608 return DefineSameAsFirst(
new(zone()) LMultiplyAddD(addend_op, multiplier_op,
1613 LInstruction* LChunkBuilder::DoMultiplySub(HValue* minuend, HMul* mul) {
1614 LOperand* minuend_op = UseRegisterAtStart(minuend);
1615 LOperand* multiplier_op = UseRegisterAtStart(mul->left());
1616 LOperand* multiplicand_op = UseRegisterAtStart(mul->right());
1618 return DefineSameAsFirst(
new(zone()) LMultiplySubD(minuend_op,
1624 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1625 if (instr->representation().IsSmiOrInteger32()) {
1626 DCHECK(instr->left()->representation().Equals(instr->representation()));
1627 DCHECK(instr->right()->representation().Equals(instr->representation()));
1628 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1629 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1630 LAddI* add =
new(zone()) LAddI(left, right);
1631 LInstruction* result = DefineAsRegister(add);
1633 result = AssignEnvironment(result);
1636 }
else if (instr->representation().IsExternal()) {
1637 DCHECK(instr->left()->representation().IsExternal());
1638 DCHECK(instr->right()->representation().IsInteger32());
1640 LOperand* left = UseRegisterAtStart(instr->left());
1641 LOperand* right = UseOrConstantAtStart(instr->right());
1642 LAddI* add =
new(zone()) LAddI(left, right);
1643 LInstruction* result = DefineAsRegister(add);
1645 }
else if (instr->representation().IsDouble()) {
1646 if (instr->left()->IsMul() && instr->left()->HasOneUse()) {
1647 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right());
1650 if (instr->right()->IsMul() && instr->right()->HasOneUse()) {
1651 DCHECK(!instr->left()->IsMul() || !instr->left()->HasOneUse());
1652 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left());
1662 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1663 LOperand* left =
NULL;
1664 LOperand* right =
NULL;
1665 if (instr->representation().IsSmiOrInteger32()) {
1666 DCHECK(instr->left()->representation().Equals(instr->representation()));
1667 DCHECK(instr->right()->representation().Equals(instr->representation()));
1668 left = UseRegisterAtStart(instr->BetterLeftOperand());
1669 right = UseOrConstantAtStart(instr->BetterRightOperand());
1671 DCHECK(instr->representation().IsDouble());
1672 DCHECK(instr->left()->representation().IsDouble());
1673 DCHECK(instr->right()->representation().IsDouble());
1674 left = UseRegisterAtStart(instr->left());
1675 right = UseRegisterAtStart(instr->right());
1677 return DefineAsRegister(
new(zone()) LMathMinMax(left, right));
1681 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1682 DCHECK(instr->representation().IsDouble());
1685 Representation exponent_type = instr->right()->representation();
1686 DCHECK(instr->left()->representation().IsDouble());
1687 LOperand* left = UseFixedDouble(instr->left(),
d0);
1689 exponent_type.IsDouble()
1690 ? UseFixedDouble(instr->right(),
d1)
1691 : UseFixed(instr->right(), MathPowTaggedDescriptor::exponent());
1692 LPower* result =
new(zone()) LPower(left, right);
1693 return MarkAsCall(DefineFixedDouble(result,
d2),
1695 CAN_DEOPTIMIZE_EAGERLY);
1699 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1700 DCHECK(instr->left()->representation().IsTagged());
1701 DCHECK(instr->right()->representation().IsTagged());
1702 LOperand* context = UseFixed(instr->context(),
cp);
1703 LOperand* left = UseFixed(instr->left(),
r1);
1704 LOperand* right = UseFixed(instr->right(),
r0);
1705 LCmpT* result =
new(zone()) LCmpT(context, left, right);
1706 return MarkAsCall(DefineFixed(result,
r0), instr);
1710 LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
1711 HCompareNumericAndBranch* instr) {
1712 Representation r = instr->representation();
1713 if (r.IsSmiOrInteger32()) {
1714 DCHECK(instr->left()->representation().Equals(r));
1715 DCHECK(instr->right()->representation().Equals(r));
1716 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1717 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
1718 return new(zone()) LCompareNumericAndBranch(left, right);
1721 DCHECK(instr->left()->representation().IsDouble());
1722 DCHECK(instr->right()->representation().IsDouble());
1723 LOperand* left = UseRegisterAtStart(instr->left());
1724 LOperand* right = UseRegisterAtStart(instr->right());
1725 return new(zone()) LCompareNumericAndBranch(left, right);
1730 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1731 HCompareObjectEqAndBranch* instr) {
1732 LOperand* left = UseRegisterAtStart(instr->left());
1733 LOperand* right = UseRegisterAtStart(instr->right());
1734 return new(zone()) LCmpObjectEqAndBranch(left, right);
1738 LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1739 HCompareHoleAndBranch* instr) {
1740 LOperand* value = UseRegisterAtStart(instr->value());
1741 return new(zone()) LCmpHoleAndBranch(value);
1745 LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
1746 HCompareMinusZeroAndBranch* instr) {
1747 LOperand* value = UseRegister(instr->value());
1748 LOperand* scratch = TempRegister();
1749 return new(zone()) LCompareMinusZeroAndBranch(value, scratch);
1753 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1754 DCHECK(instr->value()->representation().IsTagged());
1755 LOperand* value = UseRegisterAtStart(instr->value());
1756 LOperand* temp = TempRegister();
1757 return new(zone()) LIsObjectAndBranch(value, temp);
1761 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1762 DCHECK(instr->value()->representation().IsTagged());
1763 LOperand* value = UseRegisterAtStart(instr->value());
1764 LOperand* temp = TempRegister();
1765 return new(zone()) LIsStringAndBranch(value, temp);
1769 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1770 DCHECK(instr->value()->representation().IsTagged());
1771 return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1775 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1776 HIsUndetectableAndBranch* instr) {
1777 DCHECK(instr->value()->representation().IsTagged());
1778 LOperand* value = UseRegisterAtStart(instr->value());
1779 return new(zone()) LIsUndetectableAndBranch(value, TempRegister());
1783 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1784 HStringCompareAndBranch* instr) {
1785 DCHECK(instr->left()->representation().IsTagged());
1786 DCHECK(instr->right()->representation().IsTagged());
1787 LOperand* context = UseFixed(instr->context(),
cp);
1788 LOperand* left = UseFixed(instr->left(),
r1);
1789 LOperand* right = UseFixed(instr->right(),
r0);
1790 LStringCompareAndBranch* result =
1791 new(zone()) LStringCompareAndBranch(context, left, right);
1792 return MarkAsCall(result, instr);
1796 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1797 HHasInstanceTypeAndBranch* instr) {
1798 DCHECK(instr->value()->representation().IsTagged());
1799 LOperand* value = UseRegisterAtStart(instr->value());
1800 return new(zone()) LHasInstanceTypeAndBranch(value);
1804 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1805 HGetCachedArrayIndex* instr) {
1806 DCHECK(instr->value()->representation().IsTagged());
1807 LOperand* value = UseRegisterAtStart(instr->value());
1809 return DefineAsRegister(
new(zone()) LGetCachedArrayIndex(value));
1813 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1814 HHasCachedArrayIndexAndBranch* instr) {
1815 DCHECK(instr->value()->representation().IsTagged());
1816 return new(zone()) LHasCachedArrayIndexAndBranch(
1817 UseRegisterAtStart(instr->value()));
1821 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1822 HClassOfTestAndBranch* instr) {
1823 DCHECK(instr->value()->representation().IsTagged());
1824 LOperand* value = UseRegister(instr->value());
1825 return new(zone()) LClassOfTestAndBranch(value, TempRegister());
1829 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1830 LOperand*
map = UseRegisterAtStart(instr->value());
1831 return DefineAsRegister(
new(zone()) LMapEnumLength(
map));
1835 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1836 LOperand*
object = UseFixed(instr->value(),
r0);
1837 LDateField* result =
1838 new(zone()) LDateField(
object, FixedTemp(
r1), instr->index());
1839 return MarkAsCall(DefineFixed(result,
r0), instr, CAN_DEOPTIMIZE_EAGERLY);
1843 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
1844 LOperand*
string = UseRegisterAtStart(instr->string());
1845 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1846 return DefineAsRegister(
new(zone()) LSeqStringGetChar(
string, index));
1850 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1851 LOperand*
string = UseRegisterAtStart(instr->string());
1852 LOperand* index = FLAG_debug_code
1853 ? UseRegisterAtStart(instr->index())
1854 : UseRegisterOrConstantAtStart(instr->index());
1855 LOperand* value = UseRegisterAtStart(instr->value());
1856 LOperand* context = FLAG_debug_code ? UseFixed(instr->context(),
cp) :
NULL;
1857 return new(zone()) LSeqStringSetChar(context,
string, index, value);
1861 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1862 if (!FLAG_debug_code && instr->skip_check())
return NULL;
1863 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1864 LOperand* length = !index->IsConstantOperand()
1865 ? UseRegisterOrConstantAtStart(instr->length())
1866 : UseRegisterAtStart(instr->length());
1867 LInstruction* result =
new(zone()) LBoundsCheck(index, length);
1868 if (!FLAG_debug_code || !instr->skip_check()) {
1869 result = AssignEnvironment(result);
1875 LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
1876 HBoundsCheckBaseIndexInformation* instr) {
1882 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1889 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1894 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1902 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1903 Representation from = instr->from();
1904 Representation
to = instr->to();
1905 HValue* val = instr->value();
1907 if (
to.IsTagged()) {
1908 LOperand* value = UseRegister(val);
1909 return DefineSameAsFirst(
new(zone()) LDummyUse(value));
1913 if (from.IsTagged()) {
1914 if (
to.IsDouble()) {
1915 LOperand* value = UseRegister(val);
1916 LInstruction* result = DefineAsRegister(
new(zone()) LNumberUntagD(value));
1917 if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1919 }
else if (
to.IsSmi()) {
1920 LOperand* value = UseRegister(val);
1921 if (val->type().IsSmi()) {
1922 return DefineSameAsFirst(
new(zone()) LDummyUse(value));
1924 return AssignEnvironment(DefineSameAsFirst(
new(zone()) LCheckSmi(value)));
1927 if (val->type().IsSmi() || val->representation().IsSmi()) {
1928 LOperand* value = UseRegisterAtStart(val);
1929 return DefineAsRegister(
new(zone()) LSmiUntag(value,
false));
1931 LOperand* value = UseRegister(val);
1932 LOperand* temp1 = TempRegister();
1933 LOperand* temp2 = TempDoubleRegister();
1934 LInstruction* result =
1935 DefineSameAsFirst(
new(zone()) LTaggedToI(value, temp1, temp2));
1936 if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1940 }
else if (from.IsDouble()) {
1941 if (
to.IsTagged()) {
1942 info()->MarkAsDeferredCalling();
1943 LOperand* value = UseRegister(val);
1944 LOperand* temp1 = TempRegister();
1945 LOperand* temp2 = TempRegister();
1946 LUnallocated* result_temp = TempRegister();
1947 LNumberTagD* result =
new(zone()) LNumberTagD(value, temp1, temp2);
1948 return AssignPointerMap(Define(result, result_temp));
1949 }
else if (
to.IsSmi()) {
1950 LOperand* value = UseRegister(val);
1951 return AssignEnvironment(
1952 DefineAsRegister(
new(zone()) LDoubleToSmi(value)));
1955 LOperand* value = UseRegister(val);
1956 LInstruction* result = DefineAsRegister(
new(zone()) LDoubleToI(value));
1957 if (!instr->CanTruncateToInt32()) result = AssignEnvironment(result);
1960 }
else if (from.IsInteger32()) {
1961 info()->MarkAsDeferredCalling();
1962 if (
to.IsTagged()) {
1964 LOperand* value = UseRegisterAtStart(val);
1965 return DefineAsRegister(
new(zone()) LSmiTag(value));
1967 LOperand* value = UseRegisterAtStart(val);
1968 LOperand* temp1 = TempRegister();
1969 LOperand* temp2 = TempRegister();
1970 LNumberTagU* result =
new(zone()) LNumberTagU(value, temp1, temp2);
1971 return AssignPointerMap(DefineAsRegister(result));
1973 LOperand* value = UseRegisterAtStart(val);
1974 LOperand* temp1 = TempRegister();
1975 LOperand* temp2 = TempRegister();
1976 LNumberTagI* result =
new(zone()) LNumberTagI(value, temp1, temp2);
1977 return AssignPointerMap(DefineAsRegister(result));
1979 }
else if (
to.IsSmi()) {
1980 LOperand* value = UseRegister(val);
1981 LInstruction* result = DefineAsRegister(
new(zone()) LSmiTag(value));
1983 result = AssignEnvironment(result);
1989 return DefineAsRegister(
new(zone()) LUint32ToDouble(UseRegister(val)));
1991 return DefineAsRegister(
new(zone()) LInteger32ToDouble(Use(val)));
2000 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
2001 LOperand* value = UseRegisterAtStart(instr->value());
2002 LInstruction* result =
new(zone()) LCheckNonSmi(value);
2003 if (!instr->value()->type().IsHeapObject()) {
2004 result = AssignEnvironment(result);
2010 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
2011 LOperand* value = UseRegisterAtStart(instr->value());
2012 return AssignEnvironment(
new(zone()) LCheckSmi(value));
2016 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
2017 LOperand* value = UseRegisterAtStart(instr->value());
2018 LInstruction* result =
new(zone()) LCheckInstanceType(value);
2019 return AssignEnvironment(result);
2023 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
2024 LOperand* value = UseRegisterAtStart(instr->value());
2025 return AssignEnvironment(
new(zone()) LCheckValue(value));
2029 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
2030 if (instr->IsStabilityCheck())
return new(zone()) LCheckMaps;
2031 LOperand* value = UseRegisterAtStart(instr->value());
2032 LInstruction* result = AssignEnvironment(
new(zone()) LCheckMaps(value));
2033 if (instr->HasMigrationTarget()) {
2034 info()->MarkAsDeferredCalling();
2035 result = AssignPointerMap(result);
2041 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
2042 HValue* value = instr->value();
2043 Representation input_rep = value->representation();
2044 LOperand* reg = UseRegister(value);
2045 if (input_rep.IsDouble()) {
2046 return DefineAsRegister(
new(zone()) LClampDToUint8(reg));
2047 }
else if (input_rep.IsInteger32()) {
2048 return DefineAsRegister(
new(zone()) LClampIToUint8(reg));
2050 DCHECK(input_rep.IsSmiOrTagged());
2053 LClampTToUint8* result =
2054 new(zone()) LClampTToUint8(reg, TempDoubleRegister());
2055 return AssignEnvironment(DefineAsRegister(result));
2060 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) {
2061 HValue* value = instr->value();
2062 DCHECK(value->representation().IsDouble());
2063 return DefineAsRegister(
new(zone()) LDoubleBits(UseRegister(value)));
2067 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
2068 LOperand*
lo = UseRegister(instr->lo());
2069 LOperand*
hi = UseRegister(instr->hi());
2070 return DefineAsRegister(
new(zone()) LConstructDouble(
hi,
lo));
2074 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
2075 LOperand* context = info()->IsStub()
2076 ? UseFixed(instr->context(),
cp)
2078 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
2079 return new(zone()) LReturn(UseFixed(instr->value(),
r0), context,
2084 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
2085 Representation r = instr->representation();
2087 return DefineAsRegister(
new(zone()) LConstantS);
2088 }
else if (r.IsInteger32()) {
2089 return DefineAsRegister(
new(zone()) LConstantI);
2090 }
else if (r.IsDouble()) {
2091 return DefineAsRegister(
new(zone()) LConstantD);
2092 }
else if (r.IsExternal()) {
2093 return DefineAsRegister(
new(zone()) LConstantE);
2094 }
else if (r.IsTagged()) {
2095 return DefineAsRegister(
new(zone()) LConstantT);
2103 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
2104 LLoadGlobalCell* result =
new(zone()) LLoadGlobalCell;
2105 return instr->RequiresHoleCheck()
2106 ? AssignEnvironment(DefineAsRegister(result))
2107 : DefineAsRegister(result);
2111 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
2112 LOperand* context = UseFixed(instr->context(),
cp);
2113 LOperand* global_object =
2115 LOperand* vector =
NULL;
2116 if (FLAG_vector_ics) {
2119 LLoadGlobalGeneric* result =
2120 new(zone()) LLoadGlobalGeneric(context, global_object, vector);
2121 return MarkAsCall(DefineFixed(result,
r0), instr);
2125 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
2126 LOperand* value = UseRegister(instr->value());
2129 return instr->RequiresHoleCheck()
2130 ? AssignEnvironment(
new(zone()) LStoreGlobalCell(value, TempRegister()))
2131 : new(zone()) LStoreGlobalCell(value,
NULL);
2135 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
2136 LOperand* context = UseRegisterAtStart(instr->value());
2137 LInstruction* result =
2138 DefineAsRegister(
new(zone()) LLoadContextSlot(context));
2139 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
2140 result = AssignEnvironment(result);
2146 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
2149 if (instr->NeedsWriteBarrier()) {
2150 context = UseTempRegister(instr->context());
2151 value = UseTempRegister(instr->value());
2153 context = UseRegister(instr->context());
2154 value = UseRegister(instr->value());
2156 LInstruction* result =
new(zone()) LStoreContextSlot(context, value);
2157 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
2158 result = AssignEnvironment(result);
2164 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
2165 LOperand* obj = UseRegisterAtStart(instr->object());
2166 return DefineAsRegister(
new(zone()) LLoadNamedField(obj));
2170 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
2171 LOperand* context = UseFixed(instr->context(),
cp);
2174 LOperand* vector =
NULL;
2175 if (FLAG_vector_ics) {
2179 LInstruction* result =
2180 DefineFixed(
new(zone()) LLoadNamedGeneric(context,
object, vector),
r0);
2181 return MarkAsCall(result, instr);
2185 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
2186 HLoadFunctionPrototype* instr) {
2187 return AssignEnvironment(DefineAsRegister(
2188 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
2192 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
2193 return DefineAsRegister(
new(zone()) LLoadRoot);
2197 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
2198 DCHECK(instr->key()->representation().IsSmiOrInteger32());
2200 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
2201 LInstruction* result =
NULL;
2203 if (!instr->is_typed_elements()) {
2204 LOperand* obj =
NULL;
2205 if (instr->representation().IsDouble()) {
2206 obj = UseRegister(instr->elements());
2208 DCHECK(instr->representation().IsSmiOrTagged());
2209 obj = UseRegisterAtStart(instr->elements());
2211 result = DefineAsRegister(
new(zone()) LLoadKeyed(obj, key));
2214 (instr->representation().IsInteger32() &&
2216 (instr->representation().IsDouble() &&
2218 LOperand* backing_store = UseRegister(instr->elements());
2219 result = DefineAsRegister(
new(zone()) LLoadKeyed(backing_store, key));
2222 if ((instr->is_external() || instr->is_fixed_typed_array()) ?
2229 instr->RequiresHoleCheck()) {
2230 result = AssignEnvironment(result);
2236 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
2237 LOperand* context = UseFixed(instr->context(),
cp);
2241 LOperand* vector =
NULL;
2242 if (FLAG_vector_ics) {
2246 LInstruction* result =
2247 DefineFixed(
new(zone()) LLoadKeyedGeneric(context,
object, key, vector),
2249 return MarkAsCall(result, instr);
2253 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
2254 if (!instr->is_typed_elements()) {
2255 DCHECK(instr->elements()->representation().IsTagged());
2256 bool needs_write_barrier = instr->NeedsWriteBarrier();
2257 LOperand*
object =
NULL;
2258 LOperand* key =
NULL;
2259 LOperand* val =
NULL;
2261 if (instr->value()->representation().IsDouble()) {
2262 object = UseRegisterAtStart(instr->elements());
2263 val = UseRegister(instr->value());
2264 key = UseRegisterOrConstantAtStart(instr->key());
2266 DCHECK(instr->value()->representation().IsSmiOrTagged());
2267 if (needs_write_barrier) {
2268 object = UseTempRegister(instr->elements());
2269 val = UseTempRegister(instr->value());
2270 key = UseTempRegister(instr->key());
2272 object = UseRegisterAtStart(instr->elements());
2273 val = UseRegisterAtStart(instr->value());
2274 key = UseRegisterOrConstantAtStart(instr->key());
2278 return new(zone()) LStoreKeyed(
object, key, val);
2282 (instr->value()->representation().IsInteger32() &&
2284 (instr->value()->representation().IsDouble() &&
2286 DCHECK((instr->is_fixed_typed_array() &&
2287 instr->elements()->representation().IsTagged()) ||
2288 (instr->is_external() &&
2289 instr->elements()->representation().IsExternal()));
2290 LOperand* val = UseRegister(instr->value());
2291 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
2292 LOperand* backing_store = UseRegister(instr->elements());
2293 return new(zone()) LStoreKeyed(backing_store, key, val);
2297 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
2298 LOperand* context = UseFixed(instr->context(),
cp);
2304 DCHECK(instr->object()->representation().IsTagged());
2305 DCHECK(instr->key()->representation().IsTagged());
2306 DCHECK(instr->value()->representation().IsTagged());
2309 new(zone()) LStoreKeyedGeneric(context, obj, key, val), instr);
2313 LInstruction* LChunkBuilder::DoTransitionElementsKind(
2314 HTransitionElementsKind* instr) {
2316 LOperand*
object = UseRegister(instr->object());
2317 LOperand* new_map_reg = TempRegister();
2318 LTransitionElementsKind* result =
2319 new(zone()) LTransitionElementsKind(
object,
NULL, new_map_reg);
2322 LOperand*
object = UseFixed(instr->object(),
r0);
2323 LOperand* context = UseFixed(instr->context(),
cp);
2324 LTransitionElementsKind* result =
2325 new(zone()) LTransitionElementsKind(
object, context,
NULL);
2326 return MarkAsCall(result, instr);
2331 LInstruction* LChunkBuilder::DoTrapAllocationMemento(
2332 HTrapAllocationMemento* instr) {
2333 LOperand*
object = UseRegister(instr->object());
2334 LOperand* temp = TempRegister();
2335 LTrapAllocationMemento* result =
2336 new(zone()) LTrapAllocationMemento(
object, temp);
2337 return AssignEnvironment(result);
2341 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2342 bool is_in_object = instr->access().IsInobject();
2343 bool needs_write_barrier = instr->NeedsWriteBarrier();
2344 bool needs_write_barrier_for_map = instr->has_transition() &&
2345 instr->NeedsWriteBarrierForMap();
2348 if (needs_write_barrier) {
2350 ? UseRegister(instr->object())
2351 : UseTempRegister(instr->object());
2353 obj = needs_write_barrier_for_map
2354 ? UseRegister(instr->object())
2355 : UseRegisterAtStart(instr->object());
2359 if (needs_write_barrier) {
2360 val = UseTempRegister(instr->value());
2361 }
else if (instr->field_representation().IsDouble()) {
2362 val = UseRegisterAtStart(instr->value());
2364 val = UseRegister(instr->value());
2368 LOperand* temp = needs_write_barrier_for_map ? TempRegister() :
NULL;
2370 return new(zone()) LStoreNamedField(obj, val, temp);
2374 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2375 LOperand* context = UseFixed(instr->context(),
cp);
2380 LInstruction* result =
new(zone()) LStoreNamedGeneric(context, obj, val);
2381 return MarkAsCall(result, instr);
2385 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2386 LOperand* context = UseFixed(instr->context(),
cp);
2387 LOperand* left = UseFixed(instr->left(),
r1);
2388 LOperand* right = UseFixed(instr->right(),
r0);
2390 DefineFixed(
new(zone()) LStringAdd(context, left, right),
r0),
2395 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2396 LOperand*
string = UseTempRegister(instr->string());
2397 LOperand* index = UseTempRegister(instr->index());
2398 LOperand* context = UseAny(instr->context());
2399 LStringCharCodeAt* result =
2400 new(zone()) LStringCharCodeAt(context,
string, index);
2401 return AssignPointerMap(DefineAsRegister(result));
2405 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2406 LOperand* char_code = UseRegister(instr->value());
2407 LOperand* context = UseAny(instr->context());
2408 LStringCharFromCode* result =
2409 new(zone()) LStringCharFromCode(context, char_code);
2410 return AssignPointerMap(DefineAsRegister(result));
2414 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
2415 info()->MarkAsDeferredCalling();
2416 LOperand* context = UseAny(instr->context());
2417 LOperand*
size = UseRegisterOrConstant(instr->size());
2418 LOperand* temp1 = TempRegister();
2419 LOperand* temp2 = TempRegister();
2420 LAllocate* result =
new(zone()) LAllocate(context,
size, temp1, temp2);
2421 return AssignPointerMap(DefineAsRegister(result));
2425 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2426 LOperand* context = UseFixed(instr->context(),
cp);
2428 DefineFixed(
new(zone()) LRegExpLiteral(context),
r0), instr);
2432 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2433 LOperand* context = UseFixed(instr->context(),
cp);
2435 DefineFixed(
new(zone()) LFunctionLiteral(context),
r0), instr);
2439 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2440 DCHECK(argument_count_ == 0);
2441 allocator_->MarkAsOsrEntry();
2442 current_block_->last_environment()->set_ast_id(instr->ast_id());
2443 return AssignEnvironment(
new(zone()) LOsrEntry);
2447 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2448 LParameter* result =
new(zone()) LParameter;
2449 if (instr->kind() == HParameter::STACK_PARAMETER) {
2450 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2451 return DefineAsSpilled(result, spill_index);
2453 DCHECK(info()->IsStub());
2454 CallInterfaceDescriptor descriptor =
2455 info()->code_stub()->GetCallInterfaceDescriptor();
2456 int index =
static_cast<int>(instr->index());
2457 Register reg = descriptor.GetEnvironmentParameterRegister(index);
2458 return DefineFixed(result, reg);
2463 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2466 int env_index = instr->index();
2467 int spill_index = 0;
2468 if (instr->environment()->is_parameter_index(env_index)) {
2469 spill_index = chunk()->GetParameterStackSlot(env_index);
2471 spill_index = env_index - instr->environment()->first_local_index();
2473 Retry(kTooManySpillSlotsNeededForOSR);
2477 return DefineAsSpilled(
new(zone()) LUnknownOSRValue, spill_index);
2481 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2482 LOperand* context = UseFixed(instr->context(),
cp);
2483 return MarkAsCall(DefineFixed(
new(zone()) LCallStub(context),
r0), instr);
2487 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2496 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
2497 instr->ReplayEnvironment(current_block_->last_environment());
2504 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2505 info()->MarkAsRequiresFrame();
2506 LOperand* args = UseRegister(instr->arguments());
2507 LOperand* length = UseRegisterOrConstantAtStart(instr->length());
2508 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
2509 return DefineAsRegister(
new(zone()) LAccessArgumentsAt(args, length, index));
2513 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2514 LOperand*
object = UseFixed(instr->value(),
r0);
2515 LToFastProperties* result =
new(zone()) LToFastProperties(
object);
2516 return MarkAsCall(DefineFixed(result,
r0), instr);
2520 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2521 LOperand* context = UseFixed(instr->context(),
cp);
2522 LTypeof* result =
new(zone()) LTypeof(context, UseFixed(instr->value(),
r0));
2523 return MarkAsCall(DefineFixed(result,
r0), instr);
2527 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2528 return new(zone()) LTypeofIsAndBranch(UseRegister(instr->value()));
2532 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2533 HIsConstructCallAndBranch* instr) {
2534 return new(zone()) LIsConstructCallAndBranch(TempRegister());
2538 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2539 instr->ReplayEnvironment(current_block_->last_environment());
2544 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2545 if (instr->is_function_entry()) {
2546 LOperand* context = UseFixed(instr->context(),
cp);
2547 return MarkAsCall(
new(zone()) LStackCheck(context), instr);
2549 DCHECK(instr->is_backwards_branch());
2550 LOperand* context = UseAny(instr->context());
2551 return AssignEnvironment(
2552 AssignPointerMap(
new(zone()) LStackCheck(context)));
2557 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2558 HEnvironment* outer = current_block_->last_environment();
2559 outer->set_ast_id(instr->ReturnId());
2560 HConstant* undefined = graph()->GetConstantUndefined();
2561 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2562 instr->arguments_count(),
2565 instr->inlining_kind());
2567 if (instr->arguments_var() !=
NULL && instr->arguments_object()->IsLinked()) {
2568 inner->Bind(instr->arguments_var(), instr->arguments_object());
2570 inner->BindContext(instr->closure_context());
2571 inner->set_entry(instr);
2572 current_block_->UpdateEnvironment(inner);
2573 chunk_->AddInlinedClosure(instr->closure());
2578 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2579 LInstruction* pop =
NULL;
2581 HEnvironment* env = current_block_->last_environment();
2583 if (env->entry()->arguments_pushed()) {
2584 int argument_count = env->arguments_environment()->parameter_count();
2585 pop =
new(zone()) LDrop(argument_count);
2586 DCHECK(instr->argument_delta() == -argument_count);
2589 HEnvironment* outer = current_block_->last_environment()->
2590 DiscardInlined(
false);
2591 current_block_->UpdateEnvironment(outer);
2597 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2598 LOperand* context = UseFixed(instr->context(),
cp);
2599 LOperand*
object = UseFixed(instr->enumerable(),
r0);
2600 LForInPrepareMap* result =
new(zone()) LForInPrepareMap(context,
object);
2601 return MarkAsCall(DefineFixed(result,
r0), instr, CAN_DEOPTIMIZE_EAGERLY);
2605 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2606 LOperand*
map = UseRegister(instr->map());
2607 return AssignEnvironment(DefineAsRegister(
new(zone()) LForInCacheArray(
map)));
2611 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2612 LOperand* value = UseRegisterAtStart(instr->value());
2613 LOperand*
map = UseRegisterAtStart(instr->map());
2614 return AssignEnvironment(
new(zone()) LCheckMapValue(value,
map));
2618 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2619 LOperand*
object = UseRegister(instr->object());
2620 LOperand* index = UseTempRegister(instr->index());
2621 LLoadFieldByIndex* load =
new(zone()) LLoadFieldByIndex(
object, index);
2622 LInstruction* result = DefineSameAsFirst(load);
2623 return AssignPointerMap(result);
2627 LInstruction* LChunkBuilder::DoStoreFrameContext(HStoreFrameContext* instr) {
2628 LOperand* context = UseRegisterAtStart(instr->context());
2629 return new(zone()) LStoreFrameContext(context);
2633 LInstruction* LChunkBuilder::DoAllocateBlockContext(
2634 HAllocateBlockContext* instr) {
2635 LOperand* context = UseFixed(instr->context(),
cp);
2636 LOperand*
function = UseRegisterAtStart(instr->function());
2637 LAllocateBlockContext* result =
2638 new(zone()) LAllocateBlockContext(context,
function);
2639 return MarkAsCall(DefineFixed(result,
cp), instr);
static bool IsSupported(CpuFeature f)
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 PrintDataTo(StringStream *stream) OVERRIDE
uint32_t base_offset() const
void PrintTo(StringStream *stream)
void PrintDataTo(StringStream *stream) OVERRIDE
uint32_t base_offset() const
static LUnallocated * cast(LOperand *op)
@ MUST_HAVE_DOUBLE_REGISTER
static const int kMaxFixedSlotIndex
bool HasFixedPolicy() const
static const Register ReceiverRegister()
static const Register NameRegister()
static Representation Tagged()
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 use(in kBytes)") DEFINE_INT(max_stack_trace_source_length
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
#define DEFINE_COMPILE(type)
#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
#define DCHECK(condition)
bool IsDoubleOrFloatElementsKind(ElementsKind kind)
const LowDwVfpRegister d2
const LowDwVfpRegister d1
const LowDwVfpRegister d0
DwVfpRegister DoubleRegister
@ EXTERNAL_UINT32_ELEMENTS
bool IsSimpleMapChangeTransition(ElementsKind from_kind, ElementsKind to_kind)
const char * ElementsKindToString(ElementsKind kind)
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)