16 #define DEFINE_COMPILE(type) \
17 void L##type::CompileToNative(LCodeGen* generator) { \
18 generator->Do##type(this); \
25 void LInstruction::VerifyCall() {
33 for (UseIterator it(
this); !it.Done(); it.Advance()) {
35 DCHECK(operand->HasFixedPolicy() ||
36 operand->IsUsedAtStart());
40 DCHECK(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
54 if (op !=
NULL && op->IsDoubleRegister()) {
65 if (op !=
NULL && op->IsDoubleRegister()) {
66 if (cgen->ToX87Register(op).is(reg))
return true;
74 stream->Add(
"%s ", this->
Mnemonic());
95 if (
i > 0) stream->Add(
" ");
110 void LLabel::PrintDataTo(StringStream* stream) {
112 LLabel* rep = replacement();
114 stream->Add(
" Dead block replaced with B%d", rep->block_id());
120 for (
int i = 0;
i < 4;
i++) {
131 for (
int i = 0;
i < 4;
i++) {
141 const char* LArithmeticD::Mnemonic()
const {
147 case Token::MOD:
return "mod-d";
155 const char* LArithmeticT::Mnemonic()
const {
160 case Token::MOD:
return "mod-t";
162 case Token::BIT_AND:
return "bit-and-t";
163 case Token::BIT_OR:
return "bit-or-t";
164 case Token::BIT_XOR:
return "bit-xor-t";
166 case Token::SHL:
return "sal-t";
167 case Token::SAR:
return "sar-t";
168 case Token::SHR:
return "shr-t";
176 bool LGoto::HasInterestingComment(LCodeGen* gen)
const {
177 return !gen->IsNextEmittedBlock(block_id());
181 void LGoto::PrintDataTo(StringStream* stream) {
182 stream->Add(
"B%d", block_id());
186 void LBranch::PrintDataTo(StringStream* stream) {
187 stream->Add(
"B%d | B%d on ", true_block_id(), false_block_id());
188 value()->PrintTo(stream);
192 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
194 left()->PrintTo(stream);
196 right()->PrintTo(stream);
197 stream->Add(
" then B%d else B%d", true_block_id(), false_block_id());
201 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
202 stream->Add(
"if is_object(");
203 value()->PrintTo(stream);
204 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
208 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
209 stream->Add(
"if is_string(");
210 value()->PrintTo(stream);
211 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
215 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
216 stream->Add(
"if is_smi(");
217 value()->PrintTo(stream);
218 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
222 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
223 stream->Add(
"if is_undetectable(");
224 value()->PrintTo(stream);
225 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
229 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
230 stream->Add(
"if string_compare(");
231 left()->PrintTo(stream);
232 right()->PrintTo(stream);
233 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
237 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
238 stream->Add(
"if has_instance_type(");
239 value()->PrintTo(stream);
240 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
244 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
245 stream->Add(
"if has_cached_array_index(");
246 value()->PrintTo(stream);
247 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
251 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
252 stream->Add(
"if class_of_test(");
253 value()->PrintTo(stream);
254 stream->Add(
", \"%o\") then B%d else B%d",
255 *hydrogen()->class_name(),
261 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
262 stream->Add(
"if typeof ");
263 value()->PrintTo(stream);
264 stream->Add(
" == \"%s\" then B%d else B%d",
265 hydrogen()->type_literal()->ToCString().get(),
266 true_block_id(), false_block_id());
270 void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
272 function()->PrintTo(stream);
273 stream->Add(
".code_entry = ");
274 code_object()->PrintTo(stream);
278 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
280 base_object()->PrintTo(stream);
282 offset()->PrintTo(stream);
286 void LCallJSFunction::PrintDataTo(StringStream* stream) {
288 function()->PrintTo(stream);
289 stream->Add(
"#%d / ", arity());
293 void LCallWithDescriptor::PrintDataTo(StringStream* stream) {
294 for (
int i = 0;
i < InputCount();
i++) {
295 InputAt(
i)->PrintTo(stream);
298 stream->Add(
"#%d / ", arity());
302 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
303 context()->PrintTo(stream);
304 stream->Add(
"[%d]", slot_index());
308 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
309 context()->PrintTo(stream);
310 stream->Add(
"[%d] <- ", slot_index());
311 value()->PrintTo(stream);
315 void LInvokeFunction::PrintDataTo(StringStream* stream) {
317 context()->PrintTo(stream);
319 function()->PrintTo(stream);
320 stream->Add(
" #%d / ", arity());
324 void LCallNew::PrintDataTo(StringStream* stream) {
326 context()->PrintTo(stream);
328 constructor()->PrintTo(stream);
329 stream->Add(
" #%d / ", arity());
333 void LCallNewArray::PrintDataTo(StringStream* stream) {
335 context()->PrintTo(stream);
337 constructor()->PrintTo(stream);
338 stream->Add(
" #%d / ", arity());
344 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
345 arguments()->PrintTo(stream);
347 stream->Add(
" length ");
348 length()->PrintTo(stream);
350 stream->Add(
" index ");
351 index()->PrintTo(stream);
355 int LPlatformChunk::GetNextSpillIndex(
RegisterKind kind) {
359 spill_slot_count_ |= 1;
362 return spill_slot_count_++;
366 LOperand* LPlatformChunk::GetNextSpillSlot(
RegisterKind kind) {
367 int index = GetNextSpillIndex(kind);
369 return LDoubleStackSlot::Create(index, zone());
372 return LStackSlot::Create(index, zone());
377 void LStoreNamedField::PrintDataTo(StringStream* stream) {
378 object()->PrintTo(stream);
380 os << hydrogen()->access() <<
" <- ";
381 stream->Add(os.c_str());
382 value()->PrintTo(stream);
386 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
387 object()->PrintTo(stream);
389 stream->Add(String::cast(*
name())->ToCString().get());
391 value()->PrintTo(stream);
399 if (hydrogen()->IsDehoisted()) {
411 if (hydrogen()->IsDehoisted()) {
414 stream->Add(
"] <- ");
418 DCHECK(hydrogen()->IsConstantHoleStore() &&
419 hydrogen()->
value()->representation().IsDouble());
420 stream->Add(
"<the hole(nan)>");
427 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
428 object()->PrintTo(stream);
430 key()->PrintTo(stream);
431 stream->Add(
"] <- ");
432 value()->PrintTo(stream);
436 void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
437 object()->PrintTo(stream);
438 stream->Add(
" %p -> %p", *original_map(), *transitioned_map());
442 LPlatformChunk* LChunkBuilder::Build() {
444 chunk_ =
new(zone()) LPlatformChunk(info(), graph());
445 LPhase phase(
"L_Building chunk", chunk_);
449 if (info()->IsOptimizing()) {
452 USE(alignment_state_index);
457 if (graph()->has_osr()) {
458 for (
int i = graph()->osr()->UnoptimizedFrameSlots();
i > 0;
i--) {
463 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
464 for (
int i = 0;
i < blocks->length();
i++) {
465 HBasicBlock* next =
NULL;
466 if (i < blocks->length() - 1) next = blocks->at(
i + 1);
467 DoBasicBlock(blocks->at(
i), next);
468 if (is_aborted())
return NULL;
475 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
481 LUnallocated* LChunkBuilder::ToUnallocated(X87Register reg) {
487 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
488 return Use(value, ToUnallocated(fixed_register));
492 LOperand* LChunkBuilder::UseRegister(HValue* value) {
497 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
504 LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
509 LOperand* LChunkBuilder::Use(HValue* value) {
514 LOperand* LChunkBuilder::UseAtStart(HValue* value) {
520 static inline bool CanBeImmediateConstant(HValue* value) {
521 return value->IsConstant() && HConstant::cast(value)->NotInNewSpace();
525 LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
526 return CanBeImmediateConstant(value)
527 ? chunk_->DefineConstantOperand(HConstant::cast(value))
532 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
533 return CanBeImmediateConstant(value)
534 ? chunk_->DefineConstantOperand(HConstant::cast(value))
539 LOperand* LChunkBuilder::UseFixedOrConstant(HValue* value,
540 Register fixed_register) {
541 return CanBeImmediateConstant(value)
542 ? chunk_->DefineConstantOperand(HConstant::cast(value))
543 : UseFixed(value, fixed_register);
547 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
548 return CanBeImmediateConstant(value)
549 ? chunk_->DefineConstantOperand(HConstant::cast(value))
550 : UseRegister(value);
554 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
555 return CanBeImmediateConstant(value)
556 ? chunk_->DefineConstantOperand(HConstant::cast(value))
557 : UseRegisterAtStart(value);
561 LOperand* LChunkBuilder::UseConstant(HValue* value) {
562 return chunk_->DefineConstantOperand(HConstant::cast(value));
566 LOperand* LChunkBuilder::UseAny(HValue* value) {
567 return value->IsConstant()
568 ? chunk_->DefineConstantOperand(HConstant::cast(value))
573 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
574 if (value->EmitAtUses()) {
576 VisitInstruction(instr);
578 operand->set_virtual_register(value->id());
583 LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr,
584 LUnallocated* result) {
585 result->set_virtual_register(current_instruction_->id());
586 instr->set_result(result);
591 LInstruction* LChunkBuilder::DefineAsRegister(
592 LTemplateResultInstruction<1>* instr) {
598 LInstruction* LChunkBuilder::DefineAsSpilled(
599 LTemplateResultInstruction<1>* instr,
606 LInstruction* LChunkBuilder::DefineSameAsFirst(
607 LTemplateResultInstruction<1>* instr) {
613 LInstruction* LChunkBuilder::DefineFixed(LTemplateResultInstruction<1>* instr,
615 return Define(instr, ToUnallocated(reg));
619 LInstruction* LChunkBuilder::DefineFixed(LTemplateResultInstruction<1>* instr,
621 return Define(instr, ToUnallocated(reg));
625 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
626 HEnvironment* hydrogen_env = current_block_->last_environment();
627 int argument_index_accumulator = 0;
628 ZoneList<HValue*> objects_to_materialize(0, zone());
630 &argument_index_accumulator,
631 &objects_to_materialize));
636 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
637 HInstruction* hinstr,
638 CanDeoptimize can_deoptimize) {
639 info()->MarkAsNonDeferredCalling();
645 instr = AssignPointerMap(instr);
651 bool needs_environment =
652 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
653 !hinstr->HasObservableSideEffects();
654 if (needs_environment && !instr->HasEnvironment()) {
655 instr = AssignEnvironment(instr);
657 instr->environment()->set_has_been_used();
664 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
665 DCHECK(!instr->HasPointerMap());
666 instr->set_pointer_map(
new(zone()) LPointerMap(zone()));
671 LUnallocated* LChunkBuilder::TempRegister() {
672 LUnallocated* operand =
674 int vreg = allocator_->GetVirtualRegister();
675 if (!allocator_->AllocationOk()) {
676 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
679 operand->set_virtual_register(vreg);
684 LOperand* LChunkBuilder::FixedTemp(Register reg) {
685 LUnallocated* operand = ToUnallocated(reg);
686 DCHECK(operand->HasFixedPolicy());
691 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
692 return new(zone()) LLabel(instr->block());
696 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
697 return DefineAsRegister(
new(zone()) LDummyUse(UseAny(instr->value())));
701 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
707 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
708 return AssignEnvironment(
new(zone()) LDeoptimize);
713 HBitwiseBinaryOperation* instr) {
714 if (instr->representation().IsSmiOrInteger32()) {
715 DCHECK(instr->left()->representation().Equals(instr->representation()));
716 DCHECK(instr->right()->representation().Equals(instr->representation()));
717 LOperand* left = UseRegisterAtStart(instr->left());
719 HValue* right_value = instr->right();
720 LOperand* right =
NULL;
721 int constant_value = 0;
722 bool does_deopt =
false;
723 if (right_value->IsConstant()) {
724 HConstant* constant = HConstant::cast(right_value);
725 right = chunk_->DefineConstantOperand(constant);
726 constant_value = constant->Integer32Value() & 0x1f;
729 if (instr->representation().IsSmi() && constant_value > 0) {
733 right = UseFixed(right_value,
ecx);
738 if (op == Token::SHR && constant_value == 0) {
739 if (FLAG_opt_safe_uint32_operations) {
746 LInstruction* result =
747 DefineSameAsFirst(
new(zone()) LShiftI(op, left, right, does_deopt));
748 return does_deopt ? AssignEnvironment(result) : result;
750 return DoArithmeticT(op, instr);
755 LInstruction* LChunkBuilder::DoArithmeticD(
Token::Value op,
756 HArithmeticBinaryOperation* instr) {
757 DCHECK(instr->representation().IsDouble());
758 DCHECK(instr->left()->representation().IsDouble());
759 DCHECK(instr->right()->representation().IsDouble());
760 if (op == Token::MOD) {
761 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
762 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
763 LArithmeticD* result =
new(zone()) LArithmeticD(op, left, right);
764 return MarkAsCall(DefineSameAsFirst(result), instr);
766 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
767 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
768 LArithmeticD* result =
new(zone()) LArithmeticD(op, left, right);
769 return DefineSameAsFirst(result);
774 LInstruction* LChunkBuilder::DoArithmeticT(
Token::Value op,
775 HBinaryOperation* instr) {
776 HValue* left = instr->left();
777 HValue* right = instr->right();
778 DCHECK(left->representation().IsTagged());
779 DCHECK(right->representation().IsTagged());
780 LOperand* context = UseFixed(instr->context(),
esi);
781 LOperand* left_operand = UseFixed(left,
edx);
782 LOperand* right_operand = UseFixed(right,
eax);
783 LArithmeticT* result =
784 new(zone()) LArithmeticT(op, context, left_operand, right_operand);
785 return MarkAsCall(DefineFixed(result,
eax), instr);
789 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
791 current_block_ = block;
792 next_block_ = next_block;
793 if (block->IsStartBlock()) {
794 block->UpdateEnvironment(graph_->start_environment());
796 }
else if (block->predecessors()->length() == 1) {
799 DCHECK(block->phis()->length() == 0);
800 HBasicBlock* pred = block->predecessors()->at(0);
801 HEnvironment* last_environment = pred->last_environment();
804 if (pred->end()->SecondSuccessor() ==
NULL) {
805 DCHECK(pred->end()->FirstSuccessor() == block);
807 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
808 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
809 last_environment = last_environment->Copy();
812 block->UpdateEnvironment(last_environment);
813 DCHECK(pred->argument_count() >= 0);
814 argument_count_ = pred->argument_count();
817 HBasicBlock* pred = block->predecessors()->at(0);
819 HEnvironment* last_environment = pred->last_environment();
820 for (
int i = 0;
i < block->phis()->length(); ++
i) {
821 HPhi* phi = block->phis()->at(
i);
822 if (phi->HasMergedIndex()) {
823 last_environment->SetValueAt(phi->merged_index(), phi);
826 for (
int i = 0;
i < block->deleted_phis()->length(); ++
i) {
827 if (block->deleted_phis()->at(
i) < last_environment->length()) {
828 last_environment->SetValueAt(block->deleted_phis()->at(
i),
829 graph_->GetConstantUndefined());
832 block->UpdateEnvironment(last_environment);
834 argument_count_ = pred->argument_count();
836 HInstruction* current = block->first();
837 int start = chunk_->instructions()->length();
838 while (current !=
NULL && !is_aborted()) {
840 if (!current->EmitAtUses()) {
841 VisitInstruction(current);
843 current = current->next();
845 int end = chunk_->instructions()->length() - 1;
847 block->set_first_instruction_index(start);
848 block->set_last_instruction_index(end);
850 block->set_argument_count(argument_count_);
852 current_block_ =
NULL;
856 void LChunkBuilder::VisitInstruction(HInstruction* current) {
857 HInstruction* old_current = current_instruction_;
858 current_instruction_ = current;
860 LInstruction* instr =
NULL;
861 if (current->CanReplaceWithDummyUses()) {
862 if (current->OperandCount() == 0) {
863 instr = DefineAsRegister(
new(zone()) LDummy());
865 DCHECK(!current->OperandAt(0)->IsControlInstruction());
866 instr = DefineAsRegister(
new(zone())
867 LDummyUse(UseAny(current->OperandAt(0))));
869 for (
int i = 1;
i < current->OperandCount(); ++
i) {
870 if (current->OperandAt(
i)->IsControlInstruction())
continue;
871 LInstruction* dummy =
872 new(zone()) LDummyUse(UseAny(current->OperandAt(
i)));
873 dummy->set_hydrogen_value(current);
874 chunk_->AddInstruction(dummy, current_block_);
877 HBasicBlock* successor;
878 if (current->IsControlInstruction() &&
884 if (!current->IsGoto()) {
885 LClobberDoubles* clobber =
new (zone()) LClobberDoubles(isolate());
886 clobber->set_hydrogen_value(current);
887 chunk_->AddInstruction(clobber, current_block_);
889 instr =
new(zone()) LGoto(successor);
891 instr = current->CompileToLithium(
this);
895 argument_count_ += current->argument_delta();
896 DCHECK(argument_count_ >= 0);
899 AddInstruction(instr, current);
902 current_instruction_ = old_current;
906 void LChunkBuilder::AddInstruction(LInstruction* instr,
907 HInstruction* hydrogen_val) {
910 instr->set_hydrogen_value(hydrogen_val);
923 if (!(instr->ClobbersRegisters() &&
924 instr->ClobbersDoubleRegisters(isolate()))) {
926 int used_at_start = 0;
927 for (UseIterator it(instr); !it.Done(); it.Advance()) {
929 if (operand->IsUsedAtStart()) ++used_at_start;
931 if (instr->Output() !=
NULL) {
934 for (TempIterator it(instr); !it.Done(); it.Advance()) {
936 if (operand->HasFixedPolicy()) ++fixed;
938 DCHECK(fixed == 0 || used_at_start == 0);
942 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
943 instr = AssignPointerMap(instr);
945 if (FLAG_stress_environments && !instr->HasEnvironment()) {
946 instr = AssignEnvironment(instr);
948 if (instr->IsGoto() &&
949 (LGoto::cast(instr)->jumps_to_join() || next_block_->is_osr_entry())) {
954 LClobberDoubles* clobber =
new(zone()) LClobberDoubles(isolate());
955 clobber->set_hydrogen_value(hydrogen_val);
956 chunk_->AddInstruction(clobber, current_block_);
958 chunk_->AddInstruction(instr, current_block_);
960 if (instr->IsCall()) {
961 HValue* hydrogen_value_for_lazy_bailout = hydrogen_val;
962 LInstruction* instruction_needing_environment =
NULL;
963 if (hydrogen_val->HasObservableSideEffects()) {
964 HSimulate* sim = HSimulate::cast(hydrogen_val->next());
965 instruction_needing_environment = instr;
966 sim->ReplayEnvironment(current_block_->last_environment());
967 hydrogen_value_for_lazy_bailout = sim;
969 LInstruction* bailout = AssignEnvironment(
new(zone()) LLazyBailout());
970 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
971 chunk_->AddInstruction(bailout, current_block_);
972 if (instruction_needing_environment !=
NULL) {
975 instruction_needing_environment->
976 SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
982 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
983 return new(zone()) LGoto(instr->FirstSuccessor());
987 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
988 HValue* value = instr->value();
989 Representation r = value->representation();
990 HType type = value->type();
991 ToBooleanStub::Types expected = instr->expected_input_types();
994 bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() ||
995 type.IsJSArray() || type.IsHeapNumber() || type.IsString();
996 LOperand* temp = !easy_case && expected.NeedsMap() ? TempRegister() :
NULL;
997 LInstruction* branch =
998 temp !=
NULL ?
new (zone()) LBranch(UseRegister(value), temp)
999 :
new (zone()) LBranch(UseRegisterAtStart(value), temp);
1002 !expected.IsGeneric())) {
1003 branch = AssignEnvironment(branch);
1009 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
1010 return new(zone()) LDebugBreak();
1014 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
1015 DCHECK(instr->value()->representation().IsTagged());
1016 LOperand* value = UseRegisterAtStart(instr->value());
1017 return new(zone()) LCmpMapAndBranch(value);
1021 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
1022 info()->MarkAsRequiresFrame();
1023 return DefineAsRegister(
new(zone()) LArgumentsLength(Use(length->value())));
1027 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
1028 info()->MarkAsRequiresFrame();
1029 return DefineAsRegister(
new(zone()) LArgumentsElements);
1033 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
1036 LOperand* context = UseFixed(instr->context(),
esi);
1037 LInstanceOf* result =
new(zone()) LInstanceOf(context, left, right);
1038 return MarkAsCall(DefineFixed(result,
eax), instr);
1042 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1043 HInstanceOfKnownGlobal* instr) {
1044 LInstanceOfKnownGlobal* result =
1045 new(zone()) LInstanceOfKnownGlobal(
1046 UseFixed(instr->context(),
esi),
1049 return MarkAsCall(DefineFixed(result,
eax), instr);
1053 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
1054 LOperand* receiver = UseRegister(instr->receiver());
1055 LOperand*
function = UseRegister(instr->function());
1056 LOperand* temp = TempRegister();
1057 LWrapReceiver* result =
1058 new(zone()) LWrapReceiver(receiver,
function, temp);
1059 return AssignEnvironment(DefineSameAsFirst(result));
1063 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1064 LOperand*
function = UseFixed(instr->function(),
edi);
1065 LOperand* receiver = UseFixed(instr->receiver(),
eax);
1066 LOperand* length = UseFixed(instr->length(),
ebx);
1067 LOperand* elements = UseFixed(instr->elements(),
ecx);
1068 LApplyArguments* result =
new(zone()) LApplyArguments(
function,
1072 return MarkAsCall(DefineFixed(result,
eax), instr, CAN_DEOPTIMIZE_EAGERLY);
1076 LInstruction* LChunkBuilder::DoPushArguments(HPushArguments* instr) {
1077 int argc = instr->OperandCount();
1078 for (
int i = 0;
i < argc; ++
i) {
1079 LOperand* argument = UseAny(instr->argument(
i));
1080 AddInstruction(
new(zone()) LPushArgument(argument), instr);
1086 LInstruction* LChunkBuilder::DoStoreCodeEntry(
1087 HStoreCodeEntry* store_code_entry) {
1088 LOperand*
function = UseRegister(store_code_entry->function());
1089 LOperand* code_object = UseTempRegister(store_code_entry->code_object());
1090 return new(zone()) LStoreCodeEntry(
function, code_object);
1094 LInstruction* LChunkBuilder::DoInnerAllocatedObject(
1095 HInnerAllocatedObject* instr) {
1096 LOperand* base_object = UseRegisterAtStart(instr->base_object());
1097 LOperand* offset = UseRegisterOrConstantAtStart(instr->offset());
1098 return DefineAsRegister(
1099 new(zone()) LInnerAllocatedObject(base_object, offset));
1103 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
1104 return instr->HasNoUses()
1106 : DefineAsRegister(
new(zone()) LThisFunction);
1110 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1111 if (instr->HasNoUses())
return NULL;
1113 if (info()->IsStub()) {
1114 return DefineFixed(
new(zone()) LContext,
esi);
1117 return DefineAsRegister(
new(zone()) LContext);
1121 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1122 LOperand* context = UseFixed(instr->context(),
esi);
1123 return MarkAsCall(
new(zone()) LDeclareGlobals(context), instr);
1127 LInstruction* LChunkBuilder::DoCallJSFunction(
1128 HCallJSFunction* instr) {
1129 LOperand*
function = UseFixed(instr->function(),
edi);
1131 LCallJSFunction* result =
new(zone()) LCallJSFunction(
function);
1133 return MarkAsCall(DefineFixed(result,
eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1137 LInstruction* LChunkBuilder::DoCallWithDescriptor(
1138 HCallWithDescriptor* instr) {
1139 CallInterfaceDescriptor descriptor = instr->descriptor();
1140 LOperand* target = UseRegisterOrConstantAtStart(instr->target());
1141 ZoneList<LOperand*> ops(instr->OperandCount(), zone());
1142 ops.Add(target, zone());
1143 for (
int i = 1;
i < instr->OperandCount();
i++) {
1145 UseFixed(instr->OperandAt(
i), descriptor.GetParameterRegister(
i - 1));
1146 ops.Add(op, zone());
1149 LCallWithDescriptor* result =
new(zone()) LCallWithDescriptor(
1150 descriptor, ops, zone());
1151 return MarkAsCall(DefineFixed(result,
eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1155 LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
1156 HTailCallThroughMegamorphicCache* instr) {
1157 LOperand* context = UseFixed(instr->context(),
esi);
1158 LOperand* receiver_register =
1160 LOperand* name_register =
1163 return new (zone()) LTailCallThroughMegamorphicCache(
1164 context, receiver_register, name_register);
1168 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1169 LOperand* context = UseFixed(instr->context(),
esi);
1170 LOperand*
function = UseFixed(instr->function(),
edi);
1171 LInvokeFunction* result =
new(zone()) LInvokeFunction(context,
function);
1172 return MarkAsCall(DefineFixed(result,
eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1176 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1177 switch (instr->op()) {
1178 case kMathFloor:
return DoMathFloor(instr);
1179 case kMathRound:
return DoMathRound(instr);
1180 case kMathFround:
return DoMathFround(instr);
1181 case kMathAbs:
return DoMathAbs(instr);
1182 case kMathLog:
return DoMathLog(instr);
1183 case kMathExp:
return DoMathExp(instr);
1184 case kMathSqrt:
return DoMathSqrt(instr);
1186 case kMathClz32:
return DoMathClz32(instr);
1194 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
1195 LOperand* input = UseRegisterAtStart(instr->value());
1196 LMathFloor* result =
new(zone()) LMathFloor(input);
1197 return AssignEnvironment(DefineAsRegister(result));
1201 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
1202 LOperand* input = UseRegisterAtStart(instr->value());
1203 LInstruction* result = DefineAsRegister(
new (zone()) LMathRound(input));
1204 return AssignEnvironment(result);
1208 LInstruction* LChunkBuilder::DoMathFround(HUnaryMathOperation* instr) {
1209 LOperand* input = UseRegister(instr->value());
1210 LMathFround* result =
new (zone()) LMathFround(input);
1211 return DefineSameAsFirst(result);
1215 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1216 LOperand* context = UseAny(instr->context());
1217 LOperand* input = UseRegisterAtStart(instr->value());
1218 LInstruction* result =
1219 DefineSameAsFirst(
new(zone()) LMathAbs(context, input));
1220 Representation r = instr->value()->representation();
1221 if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result);
1222 if (!r.IsDouble()) result = AssignEnvironment(result);
1227 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
1228 DCHECK(instr->representation().IsDouble());
1229 DCHECK(instr->value()->representation().IsDouble());
1230 LOperand* input = UseRegisterAtStart(instr->value());
1231 return MarkAsCall(DefineSameAsFirst(
new(zone()) LMathLog(input)), instr);
1235 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
1236 LOperand* input = UseRegisterAtStart(instr->value());
1237 LMathClz32* result =
new(zone()) LMathClz32(input);
1238 return DefineAsRegister(result);
1242 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1243 DCHECK(instr->representation().IsDouble());
1244 DCHECK(instr->value()->representation().IsDouble());
1245 LOperand* value = UseRegisterAtStart(instr->value());
1246 LOperand* temp1 = FixedTemp(
ecx);
1247 LOperand* temp2 = FixedTemp(
edx);
1248 LMathExp* result =
new(zone()) LMathExp(value, temp1, temp2);
1249 return MarkAsCall(DefineSameAsFirst(result), instr);
1253 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
1254 LOperand* input = UseRegisterAtStart(instr->value());
1255 LOperand* temp1 = FixedTemp(
ecx);
1256 LOperand* temp2 = FixedTemp(
edx);
1257 LMathSqrt* result =
new(zone()) LMathSqrt(input, temp1, temp2);
1258 return MarkAsCall(DefineSameAsFirst(result), instr);
1262 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) {
1263 LOperand* input = UseRegisterAtStart(instr->value());
1264 LMathPowHalf* result =
new (zone()) LMathPowHalf(input);
1265 return DefineSameAsFirst(result);
1269 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1270 LOperand* context = UseFixed(instr->context(),
esi);
1271 LOperand* constructor = UseFixed(instr->constructor(),
edi);
1272 LCallNew* result =
new(zone()) LCallNew(context, constructor);
1273 return MarkAsCall(DefineFixed(result,
eax), instr);
1277 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1278 LOperand* context = UseFixed(instr->context(),
esi);
1279 LOperand* constructor = UseFixed(instr->constructor(),
edi);
1280 LCallNewArray* result =
new(zone()) LCallNewArray(context, constructor);
1281 return MarkAsCall(DefineFixed(result,
eax), instr);
1285 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1286 LOperand* context = UseFixed(instr->context(),
esi);
1287 LOperand*
function = UseFixed(instr->function(),
edi);
1288 LCallFunction* call =
new(zone()) LCallFunction(context,
function);
1289 return MarkAsCall(DefineFixed(call,
eax), instr);
1293 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1294 LOperand* context = UseFixed(instr->context(),
esi);
1295 return MarkAsCall(DefineFixed(
new(zone()) LCallRuntime(context),
eax), instr);
1299 LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1304 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1305 return DoShift(Token::SHR, instr);
1309 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1310 return DoShift(Token::SAR, instr);
1314 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1315 return DoShift(Token::SHL, instr);
1319 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1320 if (instr->representation().IsSmiOrInteger32()) {
1321 DCHECK(instr->left()->representation().Equals(instr->representation()));
1322 DCHECK(instr->right()->representation().Equals(instr->representation()));
1325 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1326 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1327 return DefineSameAsFirst(
new(zone()) LBitI(left, right));
1329 return DoArithmeticT(instr->op(), instr);
1334 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) {
1335 DCHECK(instr->representation().IsSmiOrInteger32());
1336 DCHECK(instr->left()->representation().Equals(instr->representation()));
1337 DCHECK(instr->right()->representation().Equals(instr->representation()));
1338 LOperand* dividend = UseRegister(instr->left());
1339 int32_t divisor = instr->right()->GetInteger32Constant();
1340 LInstruction* result = DefineAsRegister(
new(zone()) LDivByPowerOf2I(
1341 dividend, divisor));
1345 divisor != 1 && divisor != -1)) {
1346 result = AssignEnvironment(result);
1352 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) {
1353 DCHECK(instr->representation().IsInteger32());
1354 DCHECK(instr->left()->representation().Equals(instr->representation()));
1355 DCHECK(instr->right()->representation().Equals(instr->representation()));
1356 LOperand* dividend = UseRegister(instr->left());
1357 int32_t divisor = instr->right()->GetInteger32Constant();
1358 LOperand* temp1 = FixedTemp(
eax);
1359 LOperand* temp2 = FixedTemp(
edx);
1360 LInstruction* result = DefineFixed(
new(zone()) LDivByConstI(
1361 dividend, divisor, temp1, temp2),
edx);
1365 result = AssignEnvironment(result);
1371 LInstruction* LChunkBuilder::DoDivI(HDiv* instr) {
1372 DCHECK(instr->representation().IsSmiOrInteger32());
1373 DCHECK(instr->left()->representation().Equals(instr->representation()));
1374 DCHECK(instr->right()->representation().Equals(instr->representation()));
1375 LOperand* dividend = UseFixed(instr->left(),
eax);
1376 LOperand* divisor = UseRegister(instr->right());
1377 LOperand* temp = FixedTemp(
edx);
1378 LInstruction* result = DefineFixed(
new(zone()) LDivI(
1379 dividend, divisor, temp),
eax);
1384 result = AssignEnvironment(result);
1390 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1391 if (instr->representation().IsSmiOrInteger32()) {
1392 if (instr->RightIsPowerOf2()) {
1393 return DoDivByPowerOf2I(instr);
1394 }
else if (instr->right()->IsConstant()) {
1395 return DoDivByConstI(instr);
1397 return DoDivI(instr);
1399 }
else if (instr->representation().IsDouble()) {
1407 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
1408 LOperand* dividend = UseRegisterAtStart(instr->left());
1409 int32_t divisor = instr->right()->GetInteger32Constant();
1410 LInstruction* result = DefineSameAsFirst(
new(zone()) LFlooringDivByPowerOf2I(
1411 dividend, divisor));
1414 result = AssignEnvironment(result);
1420 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
1421 DCHECK(instr->representation().IsInteger32());
1422 DCHECK(instr->left()->representation().Equals(instr->representation()));
1423 DCHECK(instr->right()->representation().Equals(instr->representation()));
1424 LOperand* dividend = UseRegister(instr->left());
1425 int32_t divisor = instr->right()->GetInteger32Constant();
1426 LOperand* temp1 = FixedTemp(
eax);
1427 LOperand* temp2 = FixedTemp(
edx);
1431 NULL : TempRegister();
1432 LInstruction* result =
1433 DefineFixed(
new(zone()) LFlooringDivByConstI(dividend,
1441 result = AssignEnvironment(result);
1447 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) {
1448 DCHECK(instr->representation().IsSmiOrInteger32());
1449 DCHECK(instr->left()->representation().Equals(instr->representation()));
1450 DCHECK(instr->right()->representation().Equals(instr->representation()));
1451 LOperand* dividend = UseFixed(instr->left(),
eax);
1452 LOperand* divisor = UseRegister(instr->right());
1453 LOperand* temp = FixedTemp(
edx);
1454 LInstruction* result = DefineFixed(
new(zone()) LFlooringDivI(
1455 dividend, divisor, temp),
eax);
1459 result = AssignEnvironment(result);
1465 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1466 if (instr->RightIsPowerOf2()) {
1467 return DoFlooringDivByPowerOf2I(instr);
1468 }
else if (instr->right()->IsConstant()) {
1469 return DoFlooringDivByConstI(instr);
1471 return DoFlooringDivI(instr);
1476 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
1477 DCHECK(instr->representation().IsSmiOrInteger32());
1478 DCHECK(instr->left()->representation().Equals(instr->representation()));
1479 DCHECK(instr->right()->representation().Equals(instr->representation()));
1480 LOperand* dividend = UseRegisterAtStart(instr->left());
1481 int32_t divisor = instr->right()->GetInteger32Constant();
1482 LInstruction* result = DefineSameAsFirst(
new(zone()) LModByPowerOf2I(
1483 dividend, divisor));
1486 result = AssignEnvironment(result);
1492 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) {
1493 DCHECK(instr->representation().IsSmiOrInteger32());
1494 DCHECK(instr->left()->representation().Equals(instr->representation()));
1495 DCHECK(instr->right()->representation().Equals(instr->representation()));
1496 LOperand* dividend = UseRegister(instr->left());
1497 int32_t divisor = instr->right()->GetInteger32Constant();
1498 LOperand* temp1 = FixedTemp(
eax);
1499 LOperand* temp2 = FixedTemp(
edx);
1500 LInstruction* result = DefineFixed(
new(zone()) LModByConstI(
1501 dividend, divisor, temp1, temp2),
eax);
1503 result = AssignEnvironment(result);
1509 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
1510 DCHECK(instr->representation().IsSmiOrInteger32());
1511 DCHECK(instr->left()->representation().Equals(instr->representation()));
1512 DCHECK(instr->right()->representation().Equals(instr->representation()));
1513 LOperand* dividend = UseFixed(instr->left(),
eax);
1514 LOperand* divisor = UseRegister(instr->right());
1515 LOperand* temp = FixedTemp(
edx);
1516 LInstruction* result = DefineFixed(
new(zone()) LModI(
1517 dividend, divisor, temp),
edx);
1520 result = AssignEnvironment(result);
1526 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1527 if (instr->representation().IsSmiOrInteger32()) {
1528 if (instr->RightIsPowerOf2()) {
1529 return DoModByPowerOf2I(instr);
1530 }
else if (instr->right()->IsConstant()) {
1531 return DoModByConstI(instr);
1533 return DoModI(instr);
1535 }
else if (instr->representation().IsDouble()) {
1536 return DoArithmeticD(Token::MOD, instr);
1538 return DoArithmeticT(Token::MOD, instr);
1543 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1544 if (instr->representation().IsSmiOrInteger32()) {
1545 DCHECK(instr->left()->representation().Equals(instr->representation()));
1546 DCHECK(instr->right()->representation().Equals(instr->representation()));
1547 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1548 LOperand* right = UseOrConstant(instr->BetterRightOperand());
1549 LOperand* temp =
NULL;
1551 temp = TempRegister();
1553 LMulI* mul =
new(zone()) LMulI(left, right, temp);
1556 AssignEnvironment(mul);
1558 return DefineSameAsFirst(mul);
1559 }
else if (instr->representation().IsDouble()) {
1567 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1568 if (instr->representation().IsSmiOrInteger32()) {
1569 DCHECK(instr->left()->representation().Equals(instr->representation()));
1570 DCHECK(instr->right()->representation().Equals(instr->representation()));
1571 LOperand* left = UseRegisterAtStart(instr->left());
1572 LOperand* right = UseOrConstantAtStart(instr->right());
1573 LSubI* sub =
new(zone()) LSubI(left, right);
1574 LInstruction* result = DefineSameAsFirst(sub);
1576 result = AssignEnvironment(result);
1579 }
else if (instr->representation().IsDouble()) {
1587 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1588 if (instr->representation().IsSmiOrInteger32()) {
1589 DCHECK(instr->left()->representation().Equals(instr->representation()));
1590 DCHECK(instr->right()->representation().Equals(instr->representation()));
1595 bool use_lea = LAddI::UseLea(instr);
1596 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1597 HValue* right_candidate = instr->BetterRightOperand();
1598 LOperand* right = use_lea
1599 ? UseRegisterOrConstantAtStart(right_candidate)
1600 : UseOrConstantAtStart(right_candidate);
1601 LAddI* add =
new(zone()) LAddI(left, right);
1603 LInstruction* result = use_lea
1604 ? DefineAsRegister(add)
1605 : DefineSameAsFirst(add);
1607 result = AssignEnvironment(result);
1610 }
else if (instr->representation().IsDouble()) {
1612 }
else if (instr->representation().IsExternal()) {
1613 DCHECK(instr->left()->representation().IsExternal());
1614 DCHECK(instr->right()->representation().IsInteger32());
1616 bool use_lea = LAddI::UseLea(instr);
1617 LOperand* left = UseRegisterAtStart(instr->left());
1618 HValue* right_candidate = instr->right();
1619 LOperand* right = use_lea
1620 ? UseRegisterOrConstantAtStart(right_candidate)
1621 : UseOrConstantAtStart(right_candidate);
1622 LAddI* add =
new(zone()) LAddI(left, right);
1623 LInstruction* result = use_lea
1624 ? DefineAsRegister(add)
1625 : DefineSameAsFirst(add);
1633 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1634 LOperand* left =
NULL;
1635 LOperand* right =
NULL;
1636 LOperand* scratch = TempRegister();
1638 if (instr->representation().IsSmiOrInteger32()) {
1639 DCHECK(instr->left()->representation().Equals(instr->representation()));
1640 DCHECK(instr->right()->representation().Equals(instr->representation()));
1641 left = UseRegisterAtStart(instr->BetterLeftOperand());
1642 right = UseOrConstantAtStart(instr->BetterRightOperand());
1644 DCHECK(instr->representation().IsDouble());
1645 DCHECK(instr->left()->representation().IsDouble());
1646 DCHECK(instr->right()->representation().IsDouble());
1647 left = UseRegisterAtStart(instr->left());
1648 right = UseRegisterAtStart(instr->right());
1650 LMathMinMax* minmax =
new (zone()) LMathMinMax(left, right, scratch);
1651 return DefineSameAsFirst(minmax);
1655 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1657 DCHECK(instr->representation().IsDouble());
1658 DCHECK(instr->left()->representation().IsDouble());
1659 LOperand* left = UseRegisterAtStart(instr->left());
1660 LOperand* right = UseRegisterAtStart(instr->right());
1661 LPower* result =
new (zone()) LPower(left, right);
1662 return MarkAsCall(DefineSameAsFirst(result), instr);
1666 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1667 DCHECK(instr->left()->representation().IsSmiOrTagged());
1668 DCHECK(instr->right()->representation().IsSmiOrTagged());
1669 LOperand* context = UseFixed(instr->context(),
esi);
1670 LOperand* left = UseFixed(instr->left(),
edx);
1671 LOperand* right = UseFixed(instr->right(),
eax);
1672 LCmpT* result =
new(zone()) LCmpT(context, left, right);
1673 return MarkAsCall(DefineFixed(result,
eax), instr);
1677 LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
1678 HCompareNumericAndBranch* instr) {
1679 Representation r = instr->representation();
1680 if (r.IsSmiOrInteger32()) {
1681 DCHECK(instr->left()->representation().Equals(r));
1682 DCHECK(instr->right()->representation().Equals(r));
1683 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1684 LOperand* right = UseOrConstantAtStart(instr->right());
1685 return new(zone()) LCompareNumericAndBranch(left, right);
1688 DCHECK(instr->left()->representation().IsDouble());
1689 DCHECK(instr->right()->representation().IsDouble());
1692 if (CanBeImmediateConstant(instr->left()) &&
1693 CanBeImmediateConstant(instr->right())) {
1696 left = UseConstant(instr->left());
1697 right = UseConstant(instr->right());
1699 left = UseRegisterAtStart(instr->left());
1700 right = UseRegisterAtStart(instr->right());
1702 return new(zone()) LCompareNumericAndBranch(left, right);
1707 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1708 HCompareObjectEqAndBranch* instr) {
1709 LOperand* left = UseRegisterAtStart(instr->left());
1710 LOperand* right = UseOrConstantAtStart(instr->right());
1711 return new(zone()) LCmpObjectEqAndBranch(left, right);
1715 LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1716 HCompareHoleAndBranch* instr) {
1717 LOperand* value = UseRegisterAtStart(instr->value());
1718 return new(zone()) LCmpHoleAndBranch(value);
1722 LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
1723 HCompareMinusZeroAndBranch* instr) {
1724 LOperand* value = UseRegisterAtStart(instr->value());
1725 return new (zone()) LCompareMinusZeroAndBranch(value);
1729 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1730 DCHECK(instr->value()->representation().IsSmiOrTagged());
1731 LOperand* temp = TempRegister();
1732 return new(zone()) LIsObjectAndBranch(UseRegister(instr->value()), temp);
1736 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1737 DCHECK(instr->value()->representation().IsTagged());
1738 LOperand* temp = TempRegister();
1739 return new(zone()) LIsStringAndBranch(UseRegister(instr->value()), temp);
1743 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1744 DCHECK(instr->value()->representation().IsTagged());
1745 return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1749 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1750 HIsUndetectableAndBranch* instr) {
1751 DCHECK(instr->value()->representation().IsTagged());
1752 return new(zone()) LIsUndetectableAndBranch(
1753 UseRegisterAtStart(instr->value()), TempRegister());
1757 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1758 HStringCompareAndBranch* instr) {
1759 DCHECK(instr->left()->representation().IsTagged());
1760 DCHECK(instr->right()->representation().IsTagged());
1761 LOperand* context = UseFixed(instr->context(),
esi);
1762 LOperand* left = UseFixed(instr->left(),
edx);
1763 LOperand* right = UseFixed(instr->right(),
eax);
1765 LStringCompareAndBranch* result =
new(zone())
1766 LStringCompareAndBranch(context, left, right);
1768 return MarkAsCall(result, instr);
1772 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1773 HHasInstanceTypeAndBranch* instr) {
1774 DCHECK(instr->value()->representation().IsTagged());
1775 return new(zone()) LHasInstanceTypeAndBranch(
1776 UseRegisterAtStart(instr->value()),
1781 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1782 HGetCachedArrayIndex* instr) {
1783 DCHECK(instr->value()->representation().IsTagged());
1784 LOperand* value = UseRegisterAtStart(instr->value());
1786 return DefineAsRegister(
new(zone()) LGetCachedArrayIndex(value));
1790 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1791 HHasCachedArrayIndexAndBranch* instr) {
1792 DCHECK(instr->value()->representation().IsTagged());
1793 return new(zone()) LHasCachedArrayIndexAndBranch(
1794 UseRegisterAtStart(instr->value()));
1798 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1799 HClassOfTestAndBranch* instr) {
1800 DCHECK(instr->value()->representation().IsTagged());
1801 return new(zone()) LClassOfTestAndBranch(UseRegister(instr->value()),
1807 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1808 LOperand*
map = UseRegisterAtStart(instr->value());
1809 return DefineAsRegister(
new(zone()) LMapEnumLength(
map));
1813 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1814 LOperand* date = UseFixed(instr->value(),
eax);
1815 LDateField* result =
1816 new(zone()) LDateField(date, FixedTemp(
ecx), instr->index());
1817 return MarkAsCall(DefineFixed(result,
eax), instr, CAN_DEOPTIMIZE_EAGERLY);
1821 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
1822 LOperand*
string = UseRegisterAtStart(instr->string());
1823 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1824 return DefineAsRegister(
new(zone()) LSeqStringGetChar(
string, index));
1828 LOperand* LChunkBuilder::GetSeqStringSetCharOperand(HSeqStringSetChar* instr) {
1830 if (FLAG_debug_code) {
1831 return UseFixed(instr->value(),
eax);
1833 return UseFixedOrConstant(instr->value(),
eax);
1836 if (FLAG_debug_code) {
1837 return UseRegisterAtStart(instr->value());
1839 return UseRegisterOrConstantAtStart(instr->value());
1845 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1846 LOperand*
string = UseRegisterAtStart(instr->string());
1847 LOperand* index = FLAG_debug_code
1848 ? UseRegisterAtStart(instr->index())
1849 : UseRegisterOrConstantAtStart(instr->index());
1850 LOperand* value = GetSeqStringSetCharOperand(instr);
1851 LOperand* context = FLAG_debug_code ? UseFixed(instr->context(),
esi) :
NULL;
1852 LInstruction* result =
new(zone()) LSeqStringSetChar(context,
string,
1854 if (FLAG_debug_code) {
1855 result = MarkAsCall(result, instr);
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 ? UseOrConstantAtStart(instr->length())
1866 : UseAtStart(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 LOperand* temp = TempRegister();
1917 LInstruction* result =
1918 DefineAsRegister(
new(zone()) LNumberUntagD(value, temp));
1919 if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1921 }
else if (
to.IsSmi()) {
1922 LOperand* value = UseRegister(val);
1923 if (val->type().IsSmi()) {
1924 return DefineSameAsFirst(
new(zone()) LDummyUse(value));
1926 return AssignEnvironment(DefineSameAsFirst(
new(zone()) LCheckSmi(value)));
1929 if (val->type().IsSmi() || val->representation().IsSmi()) {
1930 LOperand* value = UseRegister(val);
1931 return DefineSameAsFirst(
new(zone()) LSmiUntag(value,
false));
1933 LOperand* value = UseRegister(val);
1934 LInstruction* result = DefineSameAsFirst(
new(zone()) LTaggedToI(value));
1935 if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1939 }
else if (from.IsDouble()) {
1940 if (
to.IsTagged()) {
1941 info()->MarkAsDeferredCalling();
1942 LOperand* value = UseRegisterAtStart(val);
1943 LOperand* temp = FLAG_inline_new ? TempRegister() :
NULL;
1944 LUnallocated* result_temp = TempRegister();
1945 LNumberTagD* result =
new(zone()) LNumberTagD(value, temp);
1946 return AssignPointerMap(Define(result, result_temp));
1947 }
else if (
to.IsSmi()) {
1948 LOperand* value = UseRegister(val);
1949 return AssignEnvironment(
1950 DefineAsRegister(
new(zone()) LDoubleToSmi(value)));
1953 bool truncating = instr->CanTruncateToInt32();
1954 LOperand* value = UseRegister(val);
1955 LInstruction* result = DefineAsRegister(
new(zone()) LDoubleToI(value));
1956 if (!truncating) result = AssignEnvironment(result);
1959 }
else if (from.IsInteger32()) {
1960 info()->MarkAsDeferredCalling();
1961 if (
to.IsTagged()) {
1963 LOperand* value = UseRegister(val);
1964 return DefineSameAsFirst(
new(zone()) LSmiTag(value));
1966 LOperand* value = UseRegister(val);
1967 LOperand* temp = TempRegister();
1968 LNumberTagU* result =
new(zone()) LNumberTagU(value, temp);
1969 return AssignPointerMap(DefineSameAsFirst(result));
1971 LOperand* value = UseRegister(val);
1972 LOperand* temp = TempRegister();
1973 LNumberTagI* result =
new(zone()) LNumberTagI(value, temp);
1974 return AssignPointerMap(DefineSameAsFirst(result));
1976 }
else if (
to.IsSmi()) {
1977 LOperand* value = UseRegister(val);
1978 LInstruction* result = DefineSameAsFirst(
new(zone()) LSmiTag(value));
1980 result = AssignEnvironment(result);
1986 return DefineAsRegister(
new(zone()) LUint32ToDouble(UseRegister(val)));
1988 return DefineAsRegister(
new(zone()) LInteger32ToDouble(Use(val)));
1997 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
1998 LOperand* value = UseAtStart(instr->value());
1999 LInstruction* result =
new(zone()) LCheckNonSmi(value);
2000 if (!instr->value()->type().IsHeapObject()) {
2001 result = AssignEnvironment(result);
2007 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
2008 LOperand* value = UseRegisterAtStart(instr->value());
2009 return AssignEnvironment(
new(zone()) LCheckSmi(value));
2013 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
2014 LOperand* value = UseRegisterAtStart(instr->value());
2015 LOperand* temp = TempRegister();
2016 LCheckInstanceType* result =
new(zone()) LCheckInstanceType(value, temp);
2017 return AssignEnvironment(result);
2021 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
2026 LOperand* value = instr->object_in_new_space()
2027 ? UseRegisterAtStart(instr->value()) : UseAtStart(instr->value());
2028 return AssignEnvironment(
new(zone()) LCheckValue(value));
2032 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
2033 if (instr->IsStabilityCheck())
return new(zone()) LCheckMaps;
2034 LOperand* value = UseRegisterAtStart(instr->value());
2035 LInstruction* result = AssignEnvironment(
new(zone()) LCheckMaps(value));
2036 if (instr->HasMigrationTarget()) {
2037 info()->MarkAsDeferredCalling();
2038 result = AssignPointerMap(result);
2044 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
2045 HValue* value = instr->value();
2046 Representation input_rep = value->representation();
2047 if (input_rep.IsDouble()) {
2048 LOperand* reg = UseRegister(value);
2049 return DefineFixed(
new (zone()) LClampDToUint8(reg),
eax);
2050 }
else if (input_rep.IsInteger32()) {
2051 LOperand* reg = UseFixed(value,
eax);
2052 return DefineFixed(
new(zone()) LClampIToUint8(reg),
eax);
2054 DCHECK(input_rep.IsSmiOrTagged());
2055 LOperand* value = UseRegister(instr->value());
2056 LClampTToUint8NoSSE2* res =
2057 new(zone()) LClampTToUint8NoSSE2(value, TempRegister(),
2058 TempRegister(), TempRegister());
2059 return AssignEnvironment(DefineFixed(res,
ecx));
2064 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) {
2065 HValue* value = instr->value();
2066 DCHECK(value->representation().IsDouble());
2067 return DefineAsRegister(
new(zone()) LDoubleBits(UseRegister(value)));
2071 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
2072 LOperand*
lo = UseRegister(instr->lo());
2073 LOperand*
hi = UseRegister(instr->hi());
2074 return DefineAsRegister(
new(zone()) LConstructDouble(
hi,
lo));
2078 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
2079 LOperand* context = info()->IsStub() ? UseFixed(instr->context(),
esi) :
NULL;
2080 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
2081 return new(zone()) LReturn(
2082 UseFixed(instr->value(),
eax), context, parameter_count);
2086 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
2087 Representation r = instr->representation();
2089 return DefineAsRegister(
new(zone()) LConstantS);
2090 }
else if (r.IsInteger32()) {
2091 return DefineAsRegister(
new(zone()) LConstantI);
2092 }
else if (r.IsDouble()) {
2093 return DefineAsRegister(
new (zone()) LConstantD);
2094 }
else if (r.IsExternal()) {
2095 return DefineAsRegister(
new(zone()) LConstantE);
2096 }
else if (r.IsTagged()) {
2097 return DefineAsRegister(
new(zone()) LConstantT);
2105 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
2106 LLoadGlobalCell* result =
new(zone()) LLoadGlobalCell;
2107 return instr->RequiresHoleCheck()
2108 ? AssignEnvironment(DefineAsRegister(result))
2109 : DefineAsRegister(result);
2113 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
2114 LOperand* context = UseFixed(instr->context(),
esi);
2115 LOperand* global_object =
2117 LOperand* vector =
NULL;
2118 if (FLAG_vector_ics) {
2122 LLoadGlobalGeneric* result =
2123 new(zone()) LLoadGlobalGeneric(context, global_object, vector);
2124 return MarkAsCall(DefineFixed(result,
eax), instr);
2128 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
2129 LStoreGlobalCell* result =
2130 new(zone()) LStoreGlobalCell(UseRegister(instr->value()));
2131 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
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 LOperand* context = UseRegister(instr->context());
2150 if (instr->NeedsWriteBarrier()) {
2151 value = UseTempRegister(instr->value());
2152 temp = TempRegister();
2154 value = UseRegister(instr->value());
2157 LInstruction* result =
new(zone()) LStoreContextSlot(context, value, temp);
2158 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
2159 result = AssignEnvironment(result);
2165 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
2166 LOperand* obj = (instr->access().IsExternalMemory() &&
2167 instr->access().offset() == 0)
2168 ? UseRegisterOrConstantAtStart(instr->object())
2169 : UseRegisterAtStart(instr->object());
2170 return DefineAsRegister(
new(zone()) LLoadNamedField(obj));
2174 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
2175 LOperand* context = UseFixed(instr->context(),
esi);
2178 LOperand* vector =
NULL;
2179 if (FLAG_vector_ics) {
2182 LLoadNamedGeneric* result =
new(zone()) LLoadNamedGeneric(
2183 context,
object, vector);
2184 return MarkAsCall(DefineFixed(result,
eax), instr);
2188 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
2189 HLoadFunctionPrototype* instr) {
2190 return AssignEnvironment(DefineAsRegister(
2191 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()),
2196 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
2197 return DefineAsRegister(
new(zone()) LLoadRoot);
2201 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
2202 DCHECK(instr->key()->representation().IsSmiOrInteger32());
2205 instr->key()->representation(), elements_kind);
2206 LOperand* key = clobbers_key
2207 ? UseTempRegister(instr->key())
2208 : UseRegisterOrConstantAtStart(instr->key());
2209 LInstruction* result =
NULL;
2211 if (!instr->is_typed_elements()) {
2212 LOperand* obj = UseRegisterAtStart(instr->elements());
2213 result = DefineAsRegister(
new(zone()) LLoadKeyed(obj, key));
2216 (instr->representation().IsInteger32() &&
2218 (instr->representation().IsDouble() &&
2220 LOperand* backing_store = UseRegister(instr->elements());
2221 result = DefineAsRegister(
new(zone()) LLoadKeyed(backing_store, key));
2224 if ((instr->is_external() || instr->is_fixed_typed_array()) ?
2231 instr->RequiresHoleCheck()) {
2232 result = AssignEnvironment(result);
2238 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
2239 LOperand* context = UseFixed(instr->context(),
esi);
2243 LOperand* vector =
NULL;
2244 if (FLAG_vector_ics) {
2247 LLoadKeyedGeneric* result =
2248 new(zone()) LLoadKeyedGeneric(context,
object, key, vector);
2249 return MarkAsCall(DefineFixed(result,
eax), instr);
2253 LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) {
2257 bool val_is_fixed_register =
2264 if (val_is_fixed_register) {
2265 return UseFixed(instr->value(),
eax);
2269 return UseRegisterAtStart(instr->value());
2272 return UseRegister(instr->value());
2276 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
2277 if (!instr->is_typed_elements()) {
2278 DCHECK(instr->elements()->representation().IsTagged());
2279 DCHECK(instr->key()->representation().IsInteger32() ||
2280 instr->key()->representation().IsSmi());
2282 if (instr->value()->representation().IsDouble()) {
2283 LOperand*
object = UseRegisterAtStart(instr->elements());
2285 LOperand* val = instr->IsConstantHoleStore()
2287 : UseRegisterAtStart(instr->value());
2288 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
2289 return new(zone()) LStoreKeyed(
object, key, val);
2291 DCHECK(instr->value()->representation().IsSmiOrTagged());
2292 bool needs_write_barrier = instr->NeedsWriteBarrier();
2294 LOperand* obj = UseRegister(instr->elements());
2297 if (needs_write_barrier) {
2298 val = UseTempRegister(instr->value());
2299 key = UseTempRegister(instr->key());
2301 val = UseRegisterOrConstantAtStart(instr->value());
2302 key = UseRegisterOrConstantAtStart(instr->key());
2304 return new(zone()) LStoreKeyed(obj, key, val);
2310 (instr->value()->representation().IsInteger32() &&
2312 (instr->value()->representation().IsDouble() &&
2314 DCHECK((instr->is_fixed_typed_array() &&
2315 instr->elements()->representation().IsTagged()) ||
2316 (instr->is_external() &&
2317 instr->elements()->representation().IsExternal()));
2319 LOperand* backing_store = UseRegister(instr->elements());
2320 LOperand* val = GetStoreKeyedValueOperand(instr);
2322 instr->key()->representation(), elements_kind);
2323 LOperand* key = clobbers_key
2324 ? UseTempRegister(instr->key())
2325 : UseRegisterOrConstantAtStart(instr->key());
2326 return new(zone()) LStoreKeyed(backing_store, key, val);
2330 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
2331 LOperand* context = UseFixed(instr->context(),
esi);
2337 DCHECK(instr->object()->representation().IsTagged());
2338 DCHECK(instr->key()->representation().IsTagged());
2339 DCHECK(instr->value()->representation().IsTagged());
2341 LStoreKeyedGeneric* result =
2342 new(zone()) LStoreKeyedGeneric(context,
object, key, value);
2343 return MarkAsCall(result, instr);
2347 LInstruction* LChunkBuilder::DoTransitionElementsKind(
2348 HTransitionElementsKind* instr) {
2350 LOperand*
object = UseRegister(instr->object());
2351 LOperand* new_map_reg = TempRegister();
2352 LOperand* temp_reg = TempRegister();
2353 LTransitionElementsKind* result =
2354 new(zone()) LTransitionElementsKind(
object,
NULL,
2355 new_map_reg, temp_reg);
2358 LOperand*
object = UseFixed(instr->object(),
eax);
2359 LOperand* context = UseFixed(instr->context(),
esi);
2360 LTransitionElementsKind* result =
2361 new(zone()) LTransitionElementsKind(
object, context,
NULL,
NULL);
2362 return MarkAsCall(result, instr);
2367 LInstruction* LChunkBuilder::DoTrapAllocationMemento(
2368 HTrapAllocationMemento* instr) {
2369 LOperand*
object = UseRegister(instr->object());
2370 LOperand* temp = TempRegister();
2371 LTrapAllocationMemento* result =
2372 new(zone()) LTrapAllocationMemento(
object, temp);
2373 return AssignEnvironment(result);
2377 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2378 bool is_in_object = instr->access().IsInobject();
2379 bool is_external_location = instr->access().IsExternalMemory() &&
2380 instr->access().offset() == 0;
2381 bool needs_write_barrier = instr->NeedsWriteBarrier();
2382 bool needs_write_barrier_for_map = instr->has_transition() &&
2383 instr->NeedsWriteBarrierForMap();
2386 if (needs_write_barrier) {
2388 ? UseRegister(instr->object())
2389 : UseTempRegister(instr->object());
2390 }
else if (is_external_location) {
2392 DCHECK(!needs_write_barrier);
2393 DCHECK(!needs_write_barrier_for_map);
2394 obj = UseRegisterOrConstant(instr->object());
2396 obj = needs_write_barrier_for_map
2397 ? UseRegister(instr->object())
2398 : UseRegisterAtStart(instr->object());
2401 bool can_be_constant = instr->value()->IsConstant() &&
2402 HConstant::cast(instr->value())->NotInNewSpace() &&
2403 !instr->field_representation().IsDouble();
2406 if (instr->field_representation().IsInteger8() ||
2407 instr->field_representation().IsUInteger8()) {
2410 val = UseFixed(instr->value(),
eax);
2411 }
else if (needs_write_barrier) {
2412 val = UseTempRegister(instr->value());
2413 }
else if (can_be_constant) {
2414 val = UseRegisterOrConstant(instr->value());
2415 }
else if (instr->field_representation().IsDouble()) {
2416 val = UseRegisterAtStart(instr->value());
2418 val = UseRegister(instr->value());
2423 LOperand* temp = (!is_in_object || needs_write_barrier ||
2424 needs_write_barrier_for_map) ? TempRegister() :
NULL;
2427 LOperand* temp_map = needs_write_barrier_for_map ? TempRegister() :
NULL;
2429 return new(zone()) LStoreNamedField(obj, val, temp, temp_map);
2433 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2434 LOperand* context = UseFixed(instr->context(),
esi);
2439 LStoreNamedGeneric* result =
2440 new(zone()) LStoreNamedGeneric(context,
object, value);
2441 return MarkAsCall(result, instr);
2445 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2446 LOperand* context = UseFixed(instr->context(),
esi);
2447 LOperand* left = UseFixed(instr->left(),
edx);
2448 LOperand* right = UseFixed(instr->right(),
eax);
2449 LStringAdd* string_add =
new(zone()) LStringAdd(context, left, right);
2450 return MarkAsCall(DefineFixed(string_add,
eax), instr);
2454 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2455 LOperand*
string = UseTempRegister(instr->string());
2456 LOperand* index = UseTempRegister(instr->index());
2457 LOperand* context = UseAny(instr->context());
2458 LStringCharCodeAt* result =
2459 new(zone()) LStringCharCodeAt(context,
string, index);
2460 return AssignPointerMap(DefineAsRegister(result));
2464 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2465 LOperand* char_code = UseRegister(instr->value());
2466 LOperand* context = UseAny(instr->context());
2467 LStringCharFromCode* result =
2468 new(zone()) LStringCharFromCode(context, char_code);
2469 return AssignPointerMap(DefineAsRegister(result));
2473 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
2474 info()->MarkAsDeferredCalling();
2475 LOperand* context = UseAny(instr->context());
2476 LOperand*
size = instr->size()->IsConstant()
2477 ? UseConstant(instr->size())
2478 : UseTempRegister(instr->
size());
2479 LOperand* temp = TempRegister();
2480 LAllocate* result =
new(zone()) LAllocate(context,
size, temp);
2481 return AssignPointerMap(DefineAsRegister(result));
2485 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2486 LOperand* context = UseFixed(instr->context(),
esi);
2488 DefineFixed(
new(zone()) LRegExpLiteral(context),
eax), instr);
2492 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2493 LOperand* context = UseFixed(instr->context(),
esi);
2495 DefineFixed(
new(zone()) LFunctionLiteral(context),
eax), instr);
2499 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2500 DCHECK(argument_count_ == 0);
2501 allocator_->MarkAsOsrEntry();
2502 current_block_->last_environment()->set_ast_id(instr->ast_id());
2503 return AssignEnvironment(
new(zone()) LOsrEntry);
2507 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2508 LParameter* result =
new(zone()) LParameter;
2509 if (instr->kind() == HParameter::STACK_PARAMETER) {
2510 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2511 return DefineAsSpilled(result, spill_index);
2513 DCHECK(info()->IsStub());
2514 CallInterfaceDescriptor descriptor =
2515 info()->code_stub()->GetCallInterfaceDescriptor();
2516 int index =
static_cast<int>(instr->index());
2517 Register reg = descriptor.GetEnvironmentParameterRegister(index);
2518 return DefineFixed(result, reg);
2523 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2526 int env_index = instr->index();
2527 int spill_index = 0;
2528 if (instr->environment()->is_parameter_index(env_index)) {
2529 spill_index = chunk()->GetParameterStackSlot(env_index);
2531 spill_index = env_index - instr->environment()->first_local_index();
2533 Retry(kNotEnoughSpillSlotsForOsr);
2536 if (spill_index == 0) {
2539 spill_index = graph()->osr()->UnoptimizedFrameSlots();
2542 return DefineAsSpilled(
new(zone()) LUnknownOSRValue, spill_index);
2546 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2547 LOperand* context = UseFixed(instr->context(),
esi);
2548 LCallStub* result =
new(zone()) LCallStub(context);
2549 return MarkAsCall(DefineFixed(result,
eax), instr);
2553 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2562 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
2563 instr->ReplayEnvironment(current_block_->last_environment());
2570 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2571 info()->MarkAsRequiresFrame();
2572 LOperand* args = UseRegister(instr->arguments());
2575 if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
2576 length = UseRegisterOrConstant(instr->length());
2577 index = UseOrConstant(instr->index());
2579 length = UseTempRegister(instr->length());
2580 index = Use(instr->index());
2582 return DefineAsRegister(
new(zone()) LAccessArgumentsAt(args, length, index));
2586 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2587 LOperand*
object = UseFixed(instr->value(),
eax);
2588 LToFastProperties* result =
new(zone()) LToFastProperties(
object);
2589 return MarkAsCall(DefineFixed(result,
eax), instr);
2593 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2594 LOperand* context = UseFixed(instr->context(),
esi);
2595 LOperand* value = UseAtStart(instr->value());
2596 LTypeof* result =
new(zone()) LTypeof(context, value);
2597 return MarkAsCall(DefineFixed(result,
eax), instr);
2601 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2602 return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
2606 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2607 HIsConstructCallAndBranch* instr) {
2608 return new(zone()) LIsConstructCallAndBranch(TempRegister());
2612 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2613 instr->ReplayEnvironment(current_block_->last_environment());
2618 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2619 info()->MarkAsDeferredCalling();
2620 if (instr->is_function_entry()) {
2621 LOperand* context = UseFixed(instr->context(),
esi);
2622 return MarkAsCall(
new(zone()) LStackCheck(context), instr);
2624 DCHECK(instr->is_backwards_branch());
2625 LOperand* context = UseAny(instr->context());
2626 return AssignEnvironment(
2627 AssignPointerMap(
new(zone()) LStackCheck(context)));
2632 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2633 HEnvironment* outer = current_block_->last_environment();
2634 outer->set_ast_id(instr->ReturnId());
2635 HConstant* undefined = graph()->GetConstantUndefined();
2636 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2637 instr->arguments_count(),
2640 instr->inlining_kind());
2642 if (instr->arguments_var() !=
NULL && instr->arguments_object()->IsLinked()) {
2643 inner->Bind(instr->arguments_var(), instr->arguments_object());
2645 inner->BindContext(instr->closure_context());
2646 inner->set_entry(instr);
2647 current_block_->UpdateEnvironment(inner);
2648 chunk_->AddInlinedClosure(instr->closure());
2653 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2654 LInstruction* pop =
NULL;
2656 HEnvironment* env = current_block_->last_environment();
2658 if (env->entry()->arguments_pushed()) {
2659 int argument_count = env->arguments_environment()->parameter_count();
2660 pop =
new(zone()) LDrop(argument_count);
2661 DCHECK(instr->argument_delta() == -argument_count);
2664 HEnvironment* outer = current_block_->last_environment()->
2665 DiscardInlined(
false);
2666 current_block_->UpdateEnvironment(outer);
2671 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2672 LOperand* context = UseFixed(instr->context(),
esi);
2673 LOperand*
object = UseFixed(instr->enumerable(),
eax);
2674 LForInPrepareMap* result =
new(zone()) LForInPrepareMap(context,
object);
2675 return MarkAsCall(DefineFixed(result,
eax), instr, CAN_DEOPTIMIZE_EAGERLY);
2679 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2680 LOperand*
map = UseRegister(instr->map());
2681 return AssignEnvironment(DefineAsRegister(
2682 new(zone()) LForInCacheArray(
map)));
2686 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2687 LOperand* value = UseRegisterAtStart(instr->value());
2688 LOperand*
map = UseRegisterAtStart(instr->map());
2689 return AssignEnvironment(
new(zone()) LCheckMapValue(value,
map));
2693 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2694 LOperand*
object = UseRegister(instr->object());
2695 LOperand* index = UseTempRegister(instr->index());
2696 LLoadFieldByIndex* load =
new(zone()) LLoadFieldByIndex(
object, index);
2697 LInstruction* result = DefineSameAsFirst(load);
2698 return AssignPointerMap(result);
2702 LInstruction* LChunkBuilder::DoStoreFrameContext(HStoreFrameContext* instr) {
2703 LOperand* context = UseRegisterAtStart(instr->context());
2704 return new(zone()) LStoreFrameContext(context);
2708 LInstruction* LChunkBuilder::DoAllocateBlockContext(
2709 HAllocateBlockContext* instr) {
2710 LOperand* context = UseFixed(instr->context(),
esi);
2711 LOperand*
function = UseRegisterAtStart(instr->function());
2712 LAllocateBlockContext* result =
2713 new(zone()) LAllocateBlockContext(context,
function);
2714 return MarkAsCall(DefineFixed(result,
esi), instr);
static HValue * cast(HValue *value)
@ kAllUsesTruncatingToInt32
virtual void PrintDataTo(StringStream *stream) OVERRIDE
LParallelMove * parallel_moves_[LAST_INNER_POSITION+1]
virtual int InputCount()=0
bool HasDoubleRegisterInput()
virtual bool HasResult() const =0
friend class TempIterator
bool HasPointerMap() const
virtual const char * Mnemonic() const =0
virtual void PrintTo(StringStream *stream)
bool HasDoubleRegisterResult()
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)
bool IsDoubleInput(X87Register reg, LCodeGen *cgen)
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)
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 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)
#define DCHECK_EQ(v1, v2)
bool IsDoubleOrFloatElementsKind(ElementsKind kind)
static bool ExternalArrayOpRequiresTemp(Representation key_representation, ElementsKind elements_kind)
@ EXTERNAL_UINT8_ELEMENTS
@ EXTERNAL_UINT32_ELEMENTS
@ EXTERNAL_UINT8_CLAMPED_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(Register reg)
static int ToAllocationIndex(X87Register reg)