7 #if V8_TARGET_ARCH_IA32
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()) {
63 stream->Add(
"%s ", this->
Mnemonic());
84 if (
i > 0) stream->Add(
" ");
99 void LLabel::PrintDataTo(StringStream* stream) {
101 LLabel* rep = replacement();
103 stream->Add(
" Dead block replaced with B%d", rep->block_id());
109 for (
int i = 0;
i < 4;
i++) {
120 for (
int i = 0;
i < 4;
i++) {
130 const char* LArithmeticD::Mnemonic()
const {
136 case Token::MOD:
return "mod-d";
144 const char* LArithmeticT::Mnemonic()
const {
149 case Token::MOD:
return "mod-t";
151 case Token::BIT_AND:
return "bit-and-t";
152 case Token::BIT_OR:
return "bit-or-t";
153 case Token::BIT_XOR:
return "bit-xor-t";
155 case Token::SHL:
return "sal-t";
156 case Token::SAR:
return "sar-t";
157 case Token::SHR:
return "shr-t";
165 bool LGoto::HasInterestingComment(LCodeGen* gen)
const {
166 return !gen->IsNextEmittedBlock(block_id());
170 void LGoto::PrintDataTo(StringStream* stream) {
171 stream->Add(
"B%d", block_id());
175 void LBranch::PrintDataTo(StringStream* stream) {
176 stream->Add(
"B%d | B%d on ", true_block_id(), false_block_id());
177 value()->PrintTo(stream);
181 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
183 left()->PrintTo(stream);
185 right()->PrintTo(stream);
186 stream->Add(
" then B%d else B%d", true_block_id(), false_block_id());
190 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
191 stream->Add(
"if is_object(");
192 value()->PrintTo(stream);
193 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
197 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
198 stream->Add(
"if is_string(");
199 value()->PrintTo(stream);
200 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
204 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
205 stream->Add(
"if is_smi(");
206 value()->PrintTo(stream);
207 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
211 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
212 stream->Add(
"if is_undetectable(");
213 value()->PrintTo(stream);
214 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
218 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
219 stream->Add(
"if string_compare(");
220 left()->PrintTo(stream);
221 right()->PrintTo(stream);
222 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
226 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
227 stream->Add(
"if has_instance_type(");
228 value()->PrintTo(stream);
229 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
233 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
234 stream->Add(
"if has_cached_array_index(");
235 value()->PrintTo(stream);
236 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
240 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
241 stream->Add(
"if class_of_test(");
242 value()->PrintTo(stream);
243 stream->Add(
", \"%o\") then B%d else B%d",
244 *hydrogen()->class_name(),
250 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
251 stream->Add(
"if typeof ");
252 value()->PrintTo(stream);
253 stream->Add(
" == \"%s\" then B%d else B%d",
254 hydrogen()->type_literal()->ToCString().get(),
255 true_block_id(), false_block_id());
259 void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
261 function()->PrintTo(stream);
262 stream->Add(
".code_entry = ");
263 code_object()->PrintTo(stream);
267 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
269 base_object()->PrintTo(stream);
271 offset()->PrintTo(stream);
275 void LCallJSFunction::PrintDataTo(StringStream* stream) {
277 function()->PrintTo(stream);
278 stream->Add(
"#%d / ", arity());
282 void LCallWithDescriptor::PrintDataTo(StringStream* stream) {
283 for (
int i = 0;
i < InputCount();
i++) {
284 InputAt(
i)->PrintTo(stream);
287 stream->Add(
"#%d / ", arity());
291 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
292 context()->PrintTo(stream);
293 stream->Add(
"[%d]", slot_index());
297 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
298 context()->PrintTo(stream);
299 stream->Add(
"[%d] <- ", slot_index());
300 value()->PrintTo(stream);
304 void LInvokeFunction::PrintDataTo(StringStream* stream) {
306 context()->PrintTo(stream);
308 function()->PrintTo(stream);
309 stream->Add(
" #%d / ", arity());
313 void LCallNew::PrintDataTo(StringStream* stream) {
315 context()->PrintTo(stream);
317 constructor()->PrintTo(stream);
318 stream->Add(
" #%d / ", arity());
322 void LCallNewArray::PrintDataTo(StringStream* stream) {
324 context()->PrintTo(stream);
326 constructor()->PrintTo(stream);
327 stream->Add(
" #%d / ", arity());
333 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
334 arguments()->PrintTo(stream);
336 stream->Add(
" length ");
337 length()->PrintTo(stream);
339 stream->Add(
" index ");
340 index()->PrintTo(stream);
344 int LPlatformChunk::GetNextSpillIndex(
RegisterKind kind) {
348 spill_slot_count_ |= 1;
351 return spill_slot_count_++;
355 LOperand* LPlatformChunk::GetNextSpillSlot(
RegisterKind kind) {
356 int index = GetNextSpillIndex(kind);
358 return LDoubleStackSlot::Create(index, zone());
361 return LStackSlot::Create(index, zone());
366 void LStoreNamedField::PrintDataTo(StringStream* stream) {
367 object()->PrintTo(stream);
369 os << hydrogen()->access() <<
" <- ";
370 stream->Add(os.c_str());
371 value()->PrintTo(stream);
375 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
376 object()->PrintTo(stream);
378 stream->Add(String::cast(*
name())->ToCString().get());
380 value()->PrintTo(stream);
388 if (hydrogen()->IsDehoisted()) {
400 if (hydrogen()->IsDehoisted()) {
403 stream->Add(
"] <- ");
407 DCHECK(hydrogen()->IsConstantHoleStore() &&
408 hydrogen()->
value()->representation().IsDouble());
409 stream->Add(
"<the hole(nan)>");
416 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
417 object()->PrintTo(stream);
419 key()->PrintTo(stream);
420 stream->Add(
"] <- ");
421 value()->PrintTo(stream);
425 void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
426 object()->PrintTo(stream);
427 stream->Add(
" %p -> %p", *original_map(), *transitioned_map());
431 LPlatformChunk* LChunkBuilder::Build() {
433 chunk_ =
new(zone()) LPlatformChunk(info(), graph());
434 LPhase phase(
"L_Building chunk", chunk_);
438 if (info()->IsOptimizing()) {
441 USE(alignment_state_index);
446 if (graph()->has_osr()) {
447 for (
int i = graph()->osr()->UnoptimizedFrameSlots();
i > 0;
i--) {
452 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
453 for (
int i = 0;
i < blocks->length();
i++) {
454 HBasicBlock* next =
NULL;
455 if (i < blocks->length() - 1) next = blocks->at(
i + 1);
456 DoBasicBlock(blocks->at(
i), next);
457 if (is_aborted())
return NULL;
464 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
470 LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
476 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
477 return Use(value, ToUnallocated(fixed_register));
481 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) {
482 return Use(value, ToUnallocated(reg));
486 LOperand* LChunkBuilder::UseRegister(HValue* value) {
491 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
498 LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
503 LOperand* LChunkBuilder::Use(HValue* value) {
508 LOperand* LChunkBuilder::UseAtStart(HValue* value) {
514 static inline bool CanBeImmediateConstant(HValue* value) {
515 return value->IsConstant() && HConstant::cast(value)->NotInNewSpace();
519 LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
520 return CanBeImmediateConstant(value)
521 ? chunk_->DefineConstantOperand(HConstant::cast(value))
526 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
527 return CanBeImmediateConstant(value)
528 ? chunk_->DefineConstantOperand(HConstant::cast(value))
533 LOperand* LChunkBuilder::UseFixedOrConstant(HValue* value,
534 Register fixed_register) {
535 return CanBeImmediateConstant(value)
536 ? chunk_->DefineConstantOperand(HConstant::cast(value))
537 : UseFixed(value, fixed_register);
541 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
542 return CanBeImmediateConstant(value)
543 ? chunk_->DefineConstantOperand(HConstant::cast(value))
544 : UseRegister(value);
548 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
549 return CanBeImmediateConstant(value)
550 ? chunk_->DefineConstantOperand(HConstant::cast(value))
551 : UseRegisterAtStart(value);
555 LOperand* LChunkBuilder::UseConstant(HValue* value) {
556 return chunk_->DefineConstantOperand(HConstant::cast(value));
560 LOperand* LChunkBuilder::UseAny(HValue* value) {
561 return value->IsConstant()
562 ? chunk_->DefineConstantOperand(HConstant::cast(value))
567 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
568 if (value->EmitAtUses()) {
570 VisitInstruction(instr);
572 operand->set_virtual_register(value->id());
577 LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr,
578 LUnallocated* result) {
579 result->set_virtual_register(current_instruction_->id());
580 instr->set_result(result);
585 LInstruction* LChunkBuilder::DefineAsRegister(
586 LTemplateResultInstruction<1>* instr) {
592 LInstruction* LChunkBuilder::DefineAsSpilled(
593 LTemplateResultInstruction<1>* instr,
600 LInstruction* LChunkBuilder::DefineSameAsFirst(
601 LTemplateResultInstruction<1>* instr) {
607 LInstruction* LChunkBuilder::DefineFixed(LTemplateResultInstruction<1>* instr,
609 return Define(instr, ToUnallocated(reg));
613 LInstruction* LChunkBuilder::DefineFixedDouble(
614 LTemplateResultInstruction<1>* instr,
616 return Define(instr, ToUnallocated(reg));
620 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
621 HEnvironment* hydrogen_env = current_block_->last_environment();
622 int argument_index_accumulator = 0;
623 ZoneList<HValue*> objects_to_materialize(0, zone());
625 hydrogen_env, &argument_index_accumulator, &objects_to_materialize));
630 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
631 HInstruction* hinstr,
632 CanDeoptimize can_deoptimize) {
633 info()->MarkAsNonDeferredCalling();
639 instr = AssignPointerMap(instr);
645 bool needs_environment =
646 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
647 !hinstr->HasObservableSideEffects();
648 if (needs_environment && !instr->HasEnvironment()) {
649 instr = AssignEnvironment(instr);
651 instr->environment()->set_has_been_used();
658 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
659 DCHECK(!instr->HasPointerMap());
660 instr->set_pointer_map(
new(zone()) LPointerMap(zone()));
665 LUnallocated* LChunkBuilder::TempRegister() {
666 LUnallocated* operand =
668 int vreg = allocator_->GetVirtualRegister();
669 if (!allocator_->AllocationOk()) {
670 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
673 operand->set_virtual_register(vreg);
678 LOperand* LChunkBuilder::FixedTemp(Register reg) {
679 LUnallocated* operand = ToUnallocated(reg);
680 DCHECK(operand->HasFixedPolicy());
685 LOperand* LChunkBuilder::FixedTemp(XMMRegister reg) {
686 LUnallocated* operand = ToUnallocated(reg);
687 DCHECK(operand->HasFixedPolicy());
692 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
693 return new(zone()) LLabel(instr->block());
697 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
698 return DefineAsRegister(
new(zone()) LDummyUse(UseAny(instr->value())));
702 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
708 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
709 return AssignEnvironment(
new(zone()) LDeoptimize);
714 HBitwiseBinaryOperation* instr) {
715 if (instr->representation().IsSmiOrInteger32()) {
716 DCHECK(instr->left()->representation().Equals(instr->representation()));
717 DCHECK(instr->right()->representation().Equals(instr->representation()));
718 LOperand* left = UseRegisterAtStart(instr->left());
720 HValue* right_value = instr->right();
721 LOperand* right =
NULL;
722 int constant_value = 0;
723 bool does_deopt =
false;
724 if (right_value->IsConstant()) {
725 HConstant* constant = HConstant::cast(right_value);
726 right = chunk_->DefineConstantOperand(constant);
727 constant_value = constant->Integer32Value() & 0x1f;
730 if (instr->representation().IsSmi() && constant_value > 0) {
734 right = UseFixed(right_value,
ecx);
739 if (op == Token::SHR && constant_value == 0) {
740 if (FLAG_opt_safe_uint32_operations) {
747 LInstruction* result =
748 DefineSameAsFirst(
new(zone()) LShiftI(op, left, right, does_deopt));
749 return does_deopt ? AssignEnvironment(result) : result;
751 return DoArithmeticT(op, instr);
756 LInstruction* LChunkBuilder::DoArithmeticD(
Token::Value op,
757 HArithmeticBinaryOperation* instr) {
758 DCHECK(instr->representation().IsDouble());
759 DCHECK(instr->left()->representation().IsDouble());
760 DCHECK(instr->right()->representation().IsDouble());
761 if (op == Token::MOD) {
762 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
763 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
764 LArithmeticD* result =
new(zone()) LArithmeticD(op, left, right);
765 return MarkAsCall(DefineSameAsFirst(result), instr);
767 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
768 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
769 LArithmeticD* result =
new(zone()) LArithmeticD(op, left, right);
770 return DefineSameAsFirst(result);
775 LInstruction* LChunkBuilder::DoArithmeticT(
Token::Value op,
776 HBinaryOperation* instr) {
777 HValue* left = instr->left();
778 HValue* right = instr->right();
779 DCHECK(left->representation().IsTagged());
780 DCHECK(right->representation().IsTagged());
781 LOperand* context = UseFixed(instr->context(),
esi);
782 LOperand* left_operand = UseFixed(left,
edx);
783 LOperand* right_operand = UseFixed(right,
eax);
784 LArithmeticT* result =
785 new(zone()) LArithmeticT(op, context, left_operand, right_operand);
786 return MarkAsCall(DefineFixed(result,
eax), instr);
790 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
792 current_block_ = block;
793 next_block_ = next_block;
794 if (block->IsStartBlock()) {
795 block->UpdateEnvironment(graph_->start_environment());
797 }
else if (block->predecessors()->length() == 1) {
800 DCHECK(block->phis()->length() == 0);
801 HBasicBlock* pred = block->predecessors()->at(0);
802 HEnvironment* last_environment = pred->last_environment();
805 if (pred->end()->SecondSuccessor() ==
NULL) {
806 DCHECK(pred->end()->FirstSuccessor() == block);
808 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
809 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
810 last_environment = last_environment->Copy();
813 block->UpdateEnvironment(last_environment);
814 DCHECK(pred->argument_count() >= 0);
815 argument_count_ = pred->argument_count();
818 HBasicBlock* pred = block->predecessors()->at(0);
820 HEnvironment* last_environment = pred->last_environment();
821 for (
int i = 0;
i < block->phis()->length(); ++
i) {
822 HPhi* phi = block->phis()->at(
i);
823 if (phi->HasMergedIndex()) {
824 last_environment->SetValueAt(phi->merged_index(), phi);
827 for (
int i = 0;
i < block->deleted_phis()->length(); ++
i) {
828 if (block->deleted_phis()->at(
i) < last_environment->length()) {
829 last_environment->SetValueAt(block->deleted_phis()->at(
i),
830 graph_->GetConstantUndefined());
833 block->UpdateEnvironment(last_environment);
835 argument_count_ = pred->argument_count();
837 HInstruction* current = block->first();
838 int start = chunk_->instructions()->length();
839 while (current !=
NULL && !is_aborted()) {
841 if (!current->EmitAtUses()) {
842 VisitInstruction(current);
844 current = current->next();
846 int end = chunk_->instructions()->length() - 1;
848 block->set_first_instruction_index(start);
849 block->set_last_instruction_index(end);
851 block->set_argument_count(argument_count_);
853 current_block_ =
NULL;
857 void LChunkBuilder::VisitInstruction(HInstruction* current) {
858 HInstruction* old_current = current_instruction_;
859 current_instruction_ = current;
861 LInstruction* instr =
NULL;
862 if (current->CanReplaceWithDummyUses()) {
863 if (current->OperandCount() == 0) {
864 instr = DefineAsRegister(
new(zone()) LDummy());
866 DCHECK(!current->OperandAt(0)->IsControlInstruction());
867 instr = DefineAsRegister(
new(zone())
868 LDummyUse(UseAny(current->OperandAt(0))));
870 for (
int i = 1;
i < current->OperandCount(); ++
i) {
871 if (current->OperandAt(
i)->IsControlInstruction())
continue;
872 LInstruction* dummy =
873 new(zone()) LDummyUse(UseAny(current->OperandAt(
i)));
874 dummy->set_hydrogen_value(current);
875 chunk_->AddInstruction(dummy, current_block_);
878 HBasicBlock* successor;
879 if (current->IsControlInstruction() &&
882 instr =
new(zone()) LGoto(successor);
884 instr = current->CompileToLithium(
this);
888 argument_count_ += current->argument_delta();
889 DCHECK(argument_count_ >= 0);
892 AddInstruction(instr, current);
895 current_instruction_ = old_current;
899 void LChunkBuilder::AddInstruction(LInstruction* instr,
900 HInstruction* hydrogen_val) {
903 instr->set_hydrogen_value(hydrogen_val);
916 if (!(instr->ClobbersRegisters() &&
917 instr->ClobbersDoubleRegisters(isolate()))) {
919 int used_at_start = 0;
920 for (UseIterator it(instr); !it.Done(); it.Advance()) {
922 if (operand->IsUsedAtStart()) ++used_at_start;
924 if (instr->Output() !=
NULL) {
927 for (TempIterator it(instr); !it.Done(); it.Advance()) {
929 if (operand->HasFixedPolicy()) ++fixed;
931 DCHECK(fixed == 0 || used_at_start == 0);
935 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
936 instr = AssignPointerMap(instr);
938 if (FLAG_stress_environments && !instr->HasEnvironment()) {
939 instr = AssignEnvironment(instr);
941 chunk_->AddInstruction(instr, current_block_);
943 if (instr->IsCall()) {
944 HValue* hydrogen_value_for_lazy_bailout = hydrogen_val;
945 LInstruction* instruction_needing_environment =
NULL;
946 if (hydrogen_val->HasObservableSideEffects()) {
947 HSimulate* sim = HSimulate::cast(hydrogen_val->next());
948 instruction_needing_environment = instr;
949 sim->ReplayEnvironment(current_block_->last_environment());
950 hydrogen_value_for_lazy_bailout = sim;
952 LInstruction* bailout = AssignEnvironment(
new(zone()) LLazyBailout());
953 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
954 chunk_->AddInstruction(bailout, current_block_);
955 if (instruction_needing_environment !=
NULL) {
958 instruction_needing_environment->
959 SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
965 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
966 return new(zone()) LGoto(instr->FirstSuccessor());
970 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
971 HValue* value = instr->value();
972 Representation r = value->representation();
973 HType type = value->type();
974 ToBooleanStub::Types expected = instr->expected_input_types();
977 bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() ||
978 type.IsJSArray() || type.IsHeapNumber() || type.IsString();
979 LOperand* temp = !easy_case && expected.NeedsMap() ? TempRegister() :
NULL;
980 LInstruction* branch =
new(zone()) LBranch(UseRegister(value), temp);
983 !expected.IsGeneric())) {
984 branch = AssignEnvironment(branch);
990 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
991 return new(zone()) LDebugBreak();
995 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
996 DCHECK(instr->value()->representation().IsTagged());
997 LOperand* value = UseRegisterAtStart(instr->value());
998 return new(zone()) LCmpMapAndBranch(value);
1002 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
1003 info()->MarkAsRequiresFrame();
1004 return DefineAsRegister(
new(zone()) LArgumentsLength(Use(length->value())));
1008 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
1009 info()->MarkAsRequiresFrame();
1010 return DefineAsRegister(
new(zone()) LArgumentsElements);
1014 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
1017 LOperand* context = UseFixed(instr->context(),
esi);
1018 LInstanceOf* result =
new(zone()) LInstanceOf(context, left, right);
1019 return MarkAsCall(DefineFixed(result,
eax), instr);
1023 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1024 HInstanceOfKnownGlobal* instr) {
1025 LInstanceOfKnownGlobal* result =
1026 new(zone()) LInstanceOfKnownGlobal(
1027 UseFixed(instr->context(),
esi),
1030 return MarkAsCall(DefineFixed(result,
eax), instr);
1034 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
1035 LOperand* receiver = UseRegister(instr->receiver());
1036 LOperand*
function = UseRegister(instr->function());
1037 LOperand* temp = TempRegister();
1038 LWrapReceiver* result =
1039 new(zone()) LWrapReceiver(receiver,
function, temp);
1040 return AssignEnvironment(DefineSameAsFirst(result));
1044 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1045 LOperand*
function = UseFixed(instr->function(),
edi);
1046 LOperand* receiver = UseFixed(instr->receiver(),
eax);
1047 LOperand* length = UseFixed(instr->length(),
ebx);
1048 LOperand* elements = UseFixed(instr->elements(),
ecx);
1049 LApplyArguments* result =
new(zone()) LApplyArguments(
function,
1053 return MarkAsCall(DefineFixed(result,
eax), instr, CAN_DEOPTIMIZE_EAGERLY);
1057 LInstruction* LChunkBuilder::DoPushArguments(HPushArguments* instr) {
1058 int argc = instr->OperandCount();
1059 for (
int i = 0;
i < argc; ++
i) {
1060 LOperand* argument = UseAny(instr->argument(
i));
1061 AddInstruction(
new(zone()) LPushArgument(argument), instr);
1067 LInstruction* LChunkBuilder::DoStoreCodeEntry(
1068 HStoreCodeEntry* store_code_entry) {
1069 LOperand*
function = UseRegister(store_code_entry->function());
1070 LOperand* code_object = UseTempRegister(store_code_entry->code_object());
1071 return new(zone()) LStoreCodeEntry(
function, code_object);
1075 LInstruction* LChunkBuilder::DoInnerAllocatedObject(
1076 HInnerAllocatedObject* instr) {
1077 LOperand* base_object = UseRegisterAtStart(instr->base_object());
1078 LOperand* offset = UseRegisterOrConstantAtStart(instr->offset());
1079 return DefineAsRegister(
1080 new(zone()) LInnerAllocatedObject(base_object, offset));
1084 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
1085 return instr->HasNoUses()
1087 : DefineAsRegister(
new(zone()) LThisFunction);
1091 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1092 if (instr->HasNoUses())
return NULL;
1094 if (info()->IsStub()) {
1095 return DefineFixed(
new(zone()) LContext,
esi);
1098 return DefineAsRegister(
new(zone()) LContext);
1102 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1103 LOperand* context = UseFixed(instr->context(),
esi);
1104 return MarkAsCall(
new(zone()) LDeclareGlobals(context), instr);
1108 LInstruction* LChunkBuilder::DoCallJSFunction(
1109 HCallJSFunction* instr) {
1110 LOperand*
function = UseFixed(instr->function(),
edi);
1112 LCallJSFunction* result =
new(zone()) LCallJSFunction(
function);
1114 return MarkAsCall(DefineFixed(result,
eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1118 LInstruction* LChunkBuilder::DoCallWithDescriptor(
1119 HCallWithDescriptor* instr) {
1120 CallInterfaceDescriptor descriptor = instr->descriptor();
1121 LOperand* target = UseRegisterOrConstantAtStart(instr->target());
1122 ZoneList<LOperand*> ops(instr->OperandCount(), zone());
1123 ops.Add(target, zone());
1124 for (
int i = 1;
i < instr->OperandCount();
i++) {
1126 UseFixed(instr->OperandAt(
i), descriptor.GetParameterRegister(
i - 1));
1127 ops.Add(op, zone());
1130 LCallWithDescriptor* result =
new(zone()) LCallWithDescriptor(
1131 descriptor, ops, zone());
1132 return MarkAsCall(DefineFixed(result,
eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1136 LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
1137 HTailCallThroughMegamorphicCache* instr) {
1138 LOperand* context = UseFixed(instr->context(),
esi);
1139 LOperand* receiver_register =
1141 LOperand* name_register =
1144 return new (zone()) LTailCallThroughMegamorphicCache(
1145 context, receiver_register, name_register);
1149 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1150 LOperand* context = UseFixed(instr->context(),
esi);
1151 LOperand*
function = UseFixed(instr->function(),
edi);
1152 LInvokeFunction* result =
new(zone()) LInvokeFunction(context,
function);
1153 return MarkAsCall(DefineFixed(result,
eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1157 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1158 switch (instr->op()) {
1160 return DoMathFloor(instr);
1162 return DoMathRound(instr);
1164 return DoMathFround(instr);
1166 return DoMathAbs(instr);
1168 return DoMathLog(instr);
1170 return DoMathExp(instr);
1172 return DoMathSqrt(instr);
1174 return DoMathPowHalf(instr);
1176 return DoMathClz32(instr);
1184 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
1185 LOperand* input = UseRegisterAtStart(instr->value());
1186 LMathFloor* result =
new(zone()) LMathFloor(input);
1187 return AssignEnvironment(DefineAsRegister(result));
1191 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
1192 LOperand* input = UseRegister(instr->value());
1193 LOperand* temp = FixedTemp(
xmm4);
1194 LMathRound* result =
new(zone()) LMathRound(input, temp);
1195 return AssignEnvironment(DefineAsRegister(result));
1199 LInstruction* LChunkBuilder::DoMathFround(HUnaryMathOperation* instr) {
1200 LOperand* input = UseRegister(instr->value());
1201 LMathFround* result =
new (zone()) LMathFround(input);
1202 return DefineAsRegister(result);
1206 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1207 LOperand* context = UseAny(instr->context());
1208 LOperand* input = UseRegisterAtStart(instr->value());
1209 LInstruction* result =
1210 DefineSameAsFirst(
new(zone()) LMathAbs(context, input));
1211 Representation r = instr->value()->representation();
1212 if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result);
1213 if (!r.IsDouble()) result = AssignEnvironment(result);
1218 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
1219 DCHECK(instr->representation().IsDouble());
1220 DCHECK(instr->value()->representation().IsDouble());
1221 LOperand* input = UseRegisterAtStart(instr->value());
1222 return MarkAsCall(DefineSameAsFirst(
new(zone()) LMathLog(input)), instr);
1226 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
1227 LOperand* input = UseRegisterAtStart(instr->value());
1228 LMathClz32* result =
new(zone()) LMathClz32(input);
1229 return DefineAsRegister(result);
1233 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1234 DCHECK(instr->representation().IsDouble());
1235 DCHECK(instr->value()->representation().IsDouble());
1236 LOperand* value = UseTempRegister(instr->value());
1237 LOperand* temp1 = TempRegister();
1238 LOperand* temp2 = TempRegister();
1239 LMathExp* result =
new(zone()) LMathExp(value, temp1, temp2);
1240 return DefineAsRegister(result);
1244 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
1245 LOperand* input = UseAtStart(instr->value());
1246 return DefineAsRegister(
new(zone()) LMathSqrt(input));
1250 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) {
1251 LOperand* input = UseRegisterAtStart(instr->value());
1252 LOperand* temp = TempRegister();
1253 LMathPowHalf* result =
new(zone()) LMathPowHalf(input, temp);
1254 return DefineSameAsFirst(result);
1258 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1259 LOperand* context = UseFixed(instr->context(),
esi);
1260 LOperand* constructor = UseFixed(instr->constructor(),
edi);
1261 LCallNew* result =
new(zone()) LCallNew(context, constructor);
1262 return MarkAsCall(DefineFixed(result,
eax), instr);
1266 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1267 LOperand* context = UseFixed(instr->context(),
esi);
1268 LOperand* constructor = UseFixed(instr->constructor(),
edi);
1269 LCallNewArray* result =
new(zone()) LCallNewArray(context, constructor);
1270 return MarkAsCall(DefineFixed(result,
eax), instr);
1274 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1275 LOperand* context = UseFixed(instr->context(),
esi);
1276 LOperand*
function = UseFixed(instr->function(),
edi);
1277 LCallFunction* call =
new(zone()) LCallFunction(context,
function);
1278 return MarkAsCall(DefineFixed(call,
eax), instr);
1282 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1283 LOperand* context = UseFixed(instr->context(),
esi);
1284 return MarkAsCall(DefineFixed(
new(zone()) LCallRuntime(context),
eax), instr);
1288 LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1293 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1294 return DoShift(Token::SHR, instr);
1298 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1299 return DoShift(Token::SAR, instr);
1303 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1304 return DoShift(Token::SHL, instr);
1308 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1309 if (instr->representation().IsSmiOrInteger32()) {
1310 DCHECK(instr->left()->representation().Equals(instr->representation()));
1311 DCHECK(instr->right()->representation().Equals(instr->representation()));
1314 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1315 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1316 return DefineSameAsFirst(
new(zone()) LBitI(left, right));
1318 return DoArithmeticT(instr->op(), instr);
1323 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) {
1324 DCHECK(instr->representation().IsSmiOrInteger32());
1325 DCHECK(instr->left()->representation().Equals(instr->representation()));
1326 DCHECK(instr->right()->representation().Equals(instr->representation()));
1327 LOperand* dividend = UseRegister(instr->left());
1328 int32_t divisor = instr->right()->GetInteger32Constant();
1329 LInstruction* result = DefineAsRegister(
new(zone()) LDivByPowerOf2I(
1330 dividend, divisor));
1334 divisor != 1 && divisor != -1)) {
1335 result = AssignEnvironment(result);
1341 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) {
1342 DCHECK(instr->representation().IsInteger32());
1343 DCHECK(instr->left()->representation().Equals(instr->representation()));
1344 DCHECK(instr->right()->representation().Equals(instr->representation()));
1345 LOperand* dividend = UseRegister(instr->left());
1346 int32_t divisor = instr->right()->GetInteger32Constant();
1347 LOperand* temp1 = FixedTemp(
eax);
1348 LOperand* temp2 = FixedTemp(
edx);
1349 LInstruction* result = DefineFixed(
new(zone()) LDivByConstI(
1350 dividend, divisor, temp1, temp2),
edx);
1354 result = AssignEnvironment(result);
1360 LInstruction* LChunkBuilder::DoDivI(HDiv* instr) {
1361 DCHECK(instr->representation().IsSmiOrInteger32());
1362 DCHECK(instr->left()->representation().Equals(instr->representation()));
1363 DCHECK(instr->right()->representation().Equals(instr->representation()));
1364 LOperand* dividend = UseFixed(instr->left(),
eax);
1365 LOperand* divisor = UseRegister(instr->right());
1366 LOperand* temp = FixedTemp(
edx);
1367 LInstruction* result = DefineFixed(
new(zone()) LDivI(
1368 dividend, divisor, temp),
eax);
1373 result = AssignEnvironment(result);
1379 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1380 if (instr->representation().IsSmiOrInteger32()) {
1381 if (instr->RightIsPowerOf2()) {
1382 return DoDivByPowerOf2I(instr);
1383 }
else if (instr->right()->IsConstant()) {
1384 return DoDivByConstI(instr);
1386 return DoDivI(instr);
1388 }
else if (instr->representation().IsDouble()) {
1396 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
1397 LOperand* dividend = UseRegisterAtStart(instr->left());
1398 int32_t divisor = instr->right()->GetInteger32Constant();
1399 LInstruction* result = DefineSameAsFirst(
new(zone()) LFlooringDivByPowerOf2I(
1400 dividend, divisor));
1403 result = AssignEnvironment(result);
1409 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
1410 DCHECK(instr->representation().IsInteger32());
1411 DCHECK(instr->left()->representation().Equals(instr->representation()));
1412 DCHECK(instr->right()->representation().Equals(instr->representation()));
1413 LOperand* dividend = UseRegister(instr->left());
1414 int32_t divisor = instr->right()->GetInteger32Constant();
1415 LOperand* temp1 = FixedTemp(
eax);
1416 LOperand* temp2 = FixedTemp(
edx);
1420 NULL : TempRegister();
1421 LInstruction* result =
1422 DefineFixed(
new(zone()) LFlooringDivByConstI(dividend,
1430 result = AssignEnvironment(result);
1436 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) {
1437 DCHECK(instr->representation().IsSmiOrInteger32());
1438 DCHECK(instr->left()->representation().Equals(instr->representation()));
1439 DCHECK(instr->right()->representation().Equals(instr->representation()));
1440 LOperand* dividend = UseFixed(instr->left(),
eax);
1441 LOperand* divisor = UseRegister(instr->right());
1442 LOperand* temp = FixedTemp(
edx);
1443 LInstruction* result = DefineFixed(
new(zone()) LFlooringDivI(
1444 dividend, divisor, temp),
eax);
1448 result = AssignEnvironment(result);
1454 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1455 if (instr->RightIsPowerOf2()) {
1456 return DoFlooringDivByPowerOf2I(instr);
1457 }
else if (instr->right()->IsConstant()) {
1458 return DoFlooringDivByConstI(instr);
1460 return DoFlooringDivI(instr);
1465 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
1466 DCHECK(instr->representation().IsSmiOrInteger32());
1467 DCHECK(instr->left()->representation().Equals(instr->representation()));
1468 DCHECK(instr->right()->representation().Equals(instr->representation()));
1469 LOperand* dividend = UseRegisterAtStart(instr->left());
1470 int32_t divisor = instr->right()->GetInteger32Constant();
1471 LInstruction* result = DefineSameAsFirst(
new(zone()) LModByPowerOf2I(
1472 dividend, divisor));
1475 result = AssignEnvironment(result);
1481 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) {
1482 DCHECK(instr->representation().IsSmiOrInteger32());
1483 DCHECK(instr->left()->representation().Equals(instr->representation()));
1484 DCHECK(instr->right()->representation().Equals(instr->representation()));
1485 LOperand* dividend = UseRegister(instr->left());
1486 int32_t divisor = instr->right()->GetInteger32Constant();
1487 LOperand* temp1 = FixedTemp(
eax);
1488 LOperand* temp2 = FixedTemp(
edx);
1489 LInstruction* result = DefineFixed(
new(zone()) LModByConstI(
1490 dividend, divisor, temp1, temp2),
eax);
1492 result = AssignEnvironment(result);
1498 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
1499 DCHECK(instr->representation().IsSmiOrInteger32());
1500 DCHECK(instr->left()->representation().Equals(instr->representation()));
1501 DCHECK(instr->right()->representation().Equals(instr->representation()));
1502 LOperand* dividend = UseFixed(instr->left(),
eax);
1503 LOperand* divisor = UseRegister(instr->right());
1504 LOperand* temp = FixedTemp(
edx);
1505 LInstruction* result = DefineFixed(
new(zone()) LModI(
1506 dividend, divisor, temp),
edx);
1509 result = AssignEnvironment(result);
1515 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1516 if (instr->representation().IsSmiOrInteger32()) {
1517 if (instr->RightIsPowerOf2()) {
1518 return DoModByPowerOf2I(instr);
1519 }
else if (instr->right()->IsConstant()) {
1520 return DoModByConstI(instr);
1522 return DoModI(instr);
1524 }
else if (instr->representation().IsDouble()) {
1525 return DoArithmeticD(Token::MOD, instr);
1527 return DoArithmeticT(Token::MOD, instr);
1532 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1533 if (instr->representation().IsSmiOrInteger32()) {
1534 DCHECK(instr->left()->representation().Equals(instr->representation()));
1535 DCHECK(instr->right()->representation().Equals(instr->representation()));
1536 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1537 LOperand* right = UseOrConstant(instr->BetterRightOperand());
1538 LOperand* temp =
NULL;
1540 temp = TempRegister();
1542 LMulI* mul =
new(zone()) LMulI(left, right, temp);
1545 AssignEnvironment(mul);
1547 return DefineSameAsFirst(mul);
1548 }
else if (instr->representation().IsDouble()) {
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()));
1560 LOperand* left = UseRegisterAtStart(instr->left());
1561 LOperand* right = UseOrConstantAtStart(instr->right());
1562 LSubI* sub =
new(zone()) LSubI(left, right);
1563 LInstruction* result = DefineSameAsFirst(sub);
1565 result = AssignEnvironment(result);
1568 }
else if (instr->representation().IsDouble()) {
1576 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1577 if (instr->representation().IsSmiOrInteger32()) {
1578 DCHECK(instr->left()->representation().Equals(instr->representation()));
1579 DCHECK(instr->right()->representation().Equals(instr->representation()));
1584 bool use_lea = LAddI::UseLea(instr);
1585 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1586 HValue* right_candidate = instr->BetterRightOperand();
1587 LOperand* right = use_lea
1588 ? UseRegisterOrConstantAtStart(right_candidate)
1589 : UseOrConstantAtStart(right_candidate);
1590 LAddI* add =
new(zone()) LAddI(left, right);
1592 LInstruction* result = use_lea
1593 ? DefineAsRegister(add)
1594 : DefineSameAsFirst(add);
1596 result = AssignEnvironment(result);
1599 }
else if (instr->representation().IsDouble()) {
1601 }
else if (instr->representation().IsExternal()) {
1602 DCHECK(instr->left()->representation().IsExternal());
1603 DCHECK(instr->right()->representation().IsInteger32());
1605 bool use_lea = LAddI::UseLea(instr);
1606 LOperand* left = UseRegisterAtStart(instr->left());
1607 HValue* right_candidate = instr->right();
1608 LOperand* right = use_lea
1609 ? UseRegisterOrConstantAtStart(right_candidate)
1610 : UseOrConstantAtStart(right_candidate);
1611 LAddI* add =
new(zone()) LAddI(left, right);
1612 LInstruction* result = use_lea
1613 ? DefineAsRegister(add)
1614 : DefineSameAsFirst(add);
1622 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1623 LOperand* left =
NULL;
1624 LOperand* right =
NULL;
1625 if (instr->representation().IsSmiOrInteger32()) {
1626 DCHECK(instr->left()->representation().Equals(instr->representation()));
1627 DCHECK(instr->right()->representation().Equals(instr->representation()));
1628 left = UseRegisterAtStart(instr->BetterLeftOperand());
1629 right = UseOrConstantAtStart(instr->BetterRightOperand());
1631 DCHECK(instr->representation().IsDouble());
1632 DCHECK(instr->left()->representation().IsDouble());
1633 DCHECK(instr->right()->representation().IsDouble());
1634 left = UseRegisterAtStart(instr->left());
1635 right = UseRegisterAtStart(instr->right());
1637 LMathMinMax* minmax =
new(zone()) LMathMinMax(left, right);
1638 return DefineSameAsFirst(minmax);
1642 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1643 DCHECK(instr->representation().IsDouble());
1646 Representation exponent_type = instr->right()->representation();
1647 DCHECK(instr->left()->representation().IsDouble());
1648 LOperand* left = UseFixedDouble(instr->left(),
xmm2);
1650 exponent_type.IsDouble()
1651 ? UseFixedDouble(instr->right(),
xmm1)
1652 : UseFixed(instr->right(), MathPowTaggedDescriptor::exponent());
1653 LPower* result =
new(zone()) LPower(left, right);
1654 return MarkAsCall(DefineFixedDouble(result,
xmm3), instr,
1655 CAN_DEOPTIMIZE_EAGERLY);
1659 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1660 DCHECK(instr->left()->representation().IsSmiOrTagged());
1661 DCHECK(instr->right()->representation().IsSmiOrTagged());
1662 LOperand* context = UseFixed(instr->context(),
esi);
1663 LOperand* left = UseFixed(instr->left(),
edx);
1664 LOperand* right = UseFixed(instr->right(),
eax);
1665 LCmpT* result =
new(zone()) LCmpT(context, left, right);
1666 return MarkAsCall(DefineFixed(result,
eax), instr);
1670 LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
1671 HCompareNumericAndBranch* instr) {
1672 Representation r = instr->representation();
1673 if (r.IsSmiOrInteger32()) {
1674 DCHECK(instr->left()->representation().Equals(r));
1675 DCHECK(instr->right()->representation().Equals(r));
1676 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1677 LOperand* right = UseOrConstantAtStart(instr->right());
1678 return new(zone()) LCompareNumericAndBranch(left, right);
1681 DCHECK(instr->left()->representation().IsDouble());
1682 DCHECK(instr->right()->representation().IsDouble());
1685 if (CanBeImmediateConstant(instr->left()) &&
1686 CanBeImmediateConstant(instr->right())) {
1689 left = UseConstant(instr->left());
1690 right = UseConstant(instr->right());
1692 left = UseRegisterAtStart(instr->left());
1693 right = UseRegisterAtStart(instr->right());
1695 return new(zone()) LCompareNumericAndBranch(left, right);
1700 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1701 HCompareObjectEqAndBranch* instr) {
1702 LOperand* left = UseRegisterAtStart(instr->left());
1703 LOperand* right = UseOrConstantAtStart(instr->right());
1704 return new(zone()) LCmpObjectEqAndBranch(left, right);
1708 LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1709 HCompareHoleAndBranch* instr) {
1710 LOperand* value = UseRegisterAtStart(instr->value());
1711 return new(zone()) LCmpHoleAndBranch(value);
1715 LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
1716 HCompareMinusZeroAndBranch* instr) {
1717 LOperand* value = UseRegister(instr->value());
1718 LOperand* scratch = TempRegister();
1719 return new(zone()) LCompareMinusZeroAndBranch(value, scratch);
1723 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1724 DCHECK(instr->value()->representation().IsSmiOrTagged());
1725 LOperand* temp = TempRegister();
1726 return new(zone()) LIsObjectAndBranch(UseRegister(instr->value()), temp);
1730 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1731 DCHECK(instr->value()->representation().IsTagged());
1732 LOperand* temp = TempRegister();
1733 return new(zone()) LIsStringAndBranch(UseRegister(instr->value()), temp);
1737 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1738 DCHECK(instr->value()->representation().IsTagged());
1739 return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1743 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1744 HIsUndetectableAndBranch* instr) {
1745 DCHECK(instr->value()->representation().IsTagged());
1746 return new(zone()) LIsUndetectableAndBranch(
1747 UseRegisterAtStart(instr->value()), TempRegister());
1751 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1752 HStringCompareAndBranch* instr) {
1753 DCHECK(instr->left()->representation().IsTagged());
1754 DCHECK(instr->right()->representation().IsTagged());
1755 LOperand* context = UseFixed(instr->context(),
esi);
1756 LOperand* left = UseFixed(instr->left(),
edx);
1757 LOperand* right = UseFixed(instr->right(),
eax);
1759 LStringCompareAndBranch* result =
new(zone())
1760 LStringCompareAndBranch(context, left, right);
1762 return MarkAsCall(result, instr);
1766 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1767 HHasInstanceTypeAndBranch* instr) {
1768 DCHECK(instr->value()->representation().IsTagged());
1769 return new(zone()) LHasInstanceTypeAndBranch(
1770 UseRegisterAtStart(instr->value()),
1775 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1776 HGetCachedArrayIndex* instr) {
1777 DCHECK(instr->value()->representation().IsTagged());
1778 LOperand* value = UseRegisterAtStart(instr->value());
1780 return DefineAsRegister(
new(zone()) LGetCachedArrayIndex(value));
1784 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1785 HHasCachedArrayIndexAndBranch* instr) {
1786 DCHECK(instr->value()->representation().IsTagged());
1787 return new(zone()) LHasCachedArrayIndexAndBranch(
1788 UseRegisterAtStart(instr->value()));
1792 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1793 HClassOfTestAndBranch* instr) {
1794 DCHECK(instr->value()->representation().IsTagged());
1795 return new(zone()) LClassOfTestAndBranch(UseRegister(instr->value()),
1801 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1802 LOperand*
map = UseRegisterAtStart(instr->value());
1803 return DefineAsRegister(
new(zone()) LMapEnumLength(
map));
1807 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1808 LOperand* date = UseFixed(instr->value(),
eax);
1809 LDateField* result =
1810 new(zone()) LDateField(date, FixedTemp(
ecx), instr->index());
1811 return MarkAsCall(DefineFixed(result,
eax), instr, CAN_DEOPTIMIZE_EAGERLY);
1815 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
1816 LOperand*
string = UseRegisterAtStart(instr->string());
1817 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1818 return DefineAsRegister(
new(zone()) LSeqStringGetChar(
string, index));
1822 LOperand* LChunkBuilder::GetSeqStringSetCharOperand(HSeqStringSetChar* instr) {
1824 if (FLAG_debug_code) {
1825 return UseFixed(instr->value(),
eax);
1827 return UseFixedOrConstant(instr->value(),
eax);
1830 if (FLAG_debug_code) {
1831 return UseRegisterAtStart(instr->value());
1833 return UseRegisterOrConstantAtStart(instr->value());
1839 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1840 LOperand*
string = UseRegisterAtStart(instr->string());
1841 LOperand* index = FLAG_debug_code
1842 ? UseRegisterAtStart(instr->index())
1843 : UseRegisterOrConstantAtStart(instr->index());
1844 LOperand* value = GetSeqStringSetCharOperand(instr);
1845 LOperand* context = FLAG_debug_code ? UseFixed(instr->context(),
esi) :
NULL;
1846 LInstruction* result =
new(zone()) LSeqStringSetChar(context,
string,
1848 if (FLAG_debug_code) {
1849 result = MarkAsCall(result, instr);
1855 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1856 if (!FLAG_debug_code && instr->skip_check())
return NULL;
1857 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1858 LOperand* length = !index->IsConstantOperand()
1859 ? UseOrConstantAtStart(instr->length())
1860 : UseAtStart(instr->length());
1861 LInstruction* result =
new(zone()) LBoundsCheck(index, length);
1862 if (!FLAG_debug_code || !instr->skip_check()) {
1863 result = AssignEnvironment(result);
1869 LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
1870 HBoundsCheckBaseIndexInformation* instr) {
1876 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1883 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1888 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1896 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1897 Representation from = instr->from();
1898 Representation
to = instr->to();
1899 HValue* val = instr->value();
1901 if (
to.IsTagged()) {
1902 LOperand* value = UseRegister(val);
1903 return DefineSameAsFirst(
new(zone()) LDummyUse(value));
1907 if (from.IsTagged()) {
1908 if (
to.IsDouble()) {
1909 LOperand* value = UseRegister(val);
1910 LOperand* temp = TempRegister();
1911 LInstruction* result =
1912 DefineAsRegister(
new(zone()) LNumberUntagD(value, temp));
1913 if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1915 }
else if (
to.IsSmi()) {
1916 LOperand* value = UseRegister(val);
1917 if (val->type().IsSmi()) {
1918 return DefineSameAsFirst(
new(zone()) LDummyUse(value));
1920 return AssignEnvironment(DefineSameAsFirst(
new(zone()) LCheckSmi(value)));
1923 if (val->type().IsSmi() || val->representation().IsSmi()) {
1924 LOperand* value = UseRegister(val);
1925 return DefineSameAsFirst(
new(zone()) LSmiUntag(value,
false));
1927 LOperand* value = UseRegister(val);
1928 bool truncating = instr->CanTruncateToInt32();
1929 LOperand* xmm_temp = !truncating ? FixedTemp(
xmm1) :
NULL;
1930 LInstruction* result =
1931 DefineSameAsFirst(
new(zone()) LTaggedToI(value, xmm_temp));
1932 if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1936 }
else if (from.IsDouble()) {
1937 if (
to.IsTagged()) {
1938 info()->MarkAsDeferredCalling();
1939 LOperand* value = UseRegisterAtStart(val);
1940 LOperand* temp = FLAG_inline_new ? TempRegister() :
NULL;
1941 LUnallocated* result_temp = TempRegister();
1942 LNumberTagD* result =
new(zone()) LNumberTagD(value, temp);
1943 return AssignPointerMap(Define(result, result_temp));
1944 }
else if (
to.IsSmi()) {
1945 LOperand* value = UseRegister(val);
1946 return AssignEnvironment(
1947 DefineAsRegister(
new(zone()) LDoubleToSmi(value)));
1950 bool truncating = instr->CanTruncateToInt32();
1951 bool needs_temp = !truncating;
1952 LOperand* value = needs_temp ? UseTempRegister(val) : UseRegister(val);
1953 LOperand* temp = needs_temp ? TempRegister() :
NULL;
1954 LInstruction* result =
1955 DefineAsRegister(
new(zone()) LDoubleToI(value, temp));
1956 if (!truncating) result = AssignEnvironment(result);
1959 }
else if (from.IsInteger32()) {
1960 info()->MarkAsDeferredCalling();
1961 if (
to.IsTagged()) {
1962 LOperand* value = UseRegister(val);
1964 return DefineSameAsFirst(
new(zone()) LSmiTag(value));
1966 LOperand* temp = TempRegister();
1967 LNumberTagU* result =
new(zone()) LNumberTagU(value, temp);
1968 return AssignPointerMap(DefineSameAsFirst(result));
1970 LOperand* temp = TempRegister();
1971 LNumberTagI* result =
new(zone()) LNumberTagI(value, temp);
1972 return AssignPointerMap(DefineSameAsFirst(result));
1974 }
else if (
to.IsSmi()) {
1975 LOperand* value = UseRegister(val);
1976 LInstruction* result = DefineSameAsFirst(
new(zone()) LSmiTag(value));
1978 result = AssignEnvironment(result);
1984 return DefineAsRegister(
new(zone()) LUint32ToDouble(UseRegister(val)));
1986 return DefineAsRegister(
new(zone()) LInteger32ToDouble(Use(val)));
1995 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
1996 LOperand* value = UseAtStart(instr->value());
1997 LInstruction* result =
new(zone()) LCheckNonSmi(value);
1998 if (!instr->value()->type().IsHeapObject()) {
1999 result = AssignEnvironment(result);
2005 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
2006 LOperand* value = UseRegisterAtStart(instr->value());
2007 return AssignEnvironment(
new(zone()) LCheckSmi(value));
2011 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
2012 LOperand* value = UseRegisterAtStart(instr->value());
2013 LOperand* temp = TempRegister();
2014 LCheckInstanceType* result =
new(zone()) LCheckInstanceType(value, temp);
2015 return AssignEnvironment(result);
2019 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
2024 LOperand* value = instr->object_in_new_space()
2025 ? UseRegisterAtStart(instr->value()) : UseAtStart(instr->value());
2026 return AssignEnvironment(
new(zone()) LCheckValue(value));
2030 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
2031 if (instr->IsStabilityCheck())
return new(zone()) LCheckMaps;
2032 LOperand* value = UseRegisterAtStart(instr->value());
2033 LInstruction* result = AssignEnvironment(
new(zone()) LCheckMaps(value));
2034 if (instr->HasMigrationTarget()) {
2035 info()->MarkAsDeferredCalling();
2036 result = AssignPointerMap(result);
2042 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
2043 HValue* value = instr->value();
2044 Representation input_rep = value->representation();
2045 if (input_rep.IsDouble()) {
2046 LOperand* reg = UseRegister(value);
2047 return DefineFixed(
new(zone()) LClampDToUint8(reg),
eax);
2048 }
else if (input_rep.IsInteger32()) {
2049 LOperand* reg = UseFixed(value,
eax);
2050 return DefineFixed(
new(zone()) LClampIToUint8(reg),
eax);
2052 DCHECK(input_rep.IsSmiOrTagged());
2053 LOperand* reg = UseFixed(value,
eax);
2056 LOperand* temp = FixedTemp(
xmm1);
2057 LClampTToUint8* result =
new(zone()) LClampTToUint8(reg, temp);
2058 return AssignEnvironment(DefineFixed(result,
eax));
2063 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) {
2064 HValue* value = instr->value();
2065 DCHECK(value->representation().IsDouble());
2066 return DefineAsRegister(
new(zone()) LDoubleBits(UseRegister(value)));
2070 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
2071 LOperand*
lo = UseRegister(instr->lo());
2072 LOperand*
hi = UseRegister(instr->hi());
2073 return DefineAsRegister(
new(zone()) LConstructDouble(
hi,
lo));
2077 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
2078 LOperand* context = info()->IsStub() ? UseFixed(instr->context(),
esi) :
NULL;
2079 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
2080 return new(zone()) LReturn(
2081 UseFixed(instr->value(),
eax), context, parameter_count);
2085 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
2086 Representation r = instr->representation();
2088 return DefineAsRegister(
new(zone()) LConstantS);
2089 }
else if (r.IsInteger32()) {
2090 return DefineAsRegister(
new(zone()) LConstantI);
2091 }
else if (r.IsDouble()) {
2092 double value = instr->DoubleValue();
2093 bool value_is_zero = bit_cast<uint64_t, double>(value) == 0;
2094 LOperand* temp = value_is_zero ?
NULL : TempRegister();
2095 return DefineAsRegister(
new(zone()) LConstantD(temp));
2096 }
else if (r.IsExternal()) {
2097 return DefineAsRegister(
new(zone()) LConstantE);
2098 }
else if (r.IsTagged()) {
2099 return DefineAsRegister(
new(zone()) LConstantT);
2107 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
2108 LLoadGlobalCell* result =
new(zone()) LLoadGlobalCell;
2109 return instr->RequiresHoleCheck()
2110 ? AssignEnvironment(DefineAsRegister(result))
2111 : DefineAsRegister(result);
2115 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
2116 LOperand* context = UseFixed(instr->context(),
esi);
2117 LOperand* global_object =
2119 LOperand* vector =
NULL;
2120 if (FLAG_vector_ics) {
2124 LLoadGlobalGeneric* result =
2125 new(zone()) LLoadGlobalGeneric(context, global_object, vector);
2126 return MarkAsCall(DefineFixed(result,
eax), instr);
2130 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
2131 LStoreGlobalCell* result =
2132 new(zone()) LStoreGlobalCell(UseRegister(instr->value()));
2133 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
2137 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
2138 LOperand* context = UseRegisterAtStart(instr->value());
2139 LInstruction* result =
2140 DefineAsRegister(
new(zone()) LLoadContextSlot(context));
2141 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
2142 result = AssignEnvironment(result);
2148 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
2151 LOperand* context = UseRegister(instr->context());
2152 if (instr->NeedsWriteBarrier()) {
2153 value = UseTempRegister(instr->value());
2154 temp = TempRegister();
2156 value = UseRegister(instr->value());
2159 LInstruction* result =
new(zone()) LStoreContextSlot(context, value, temp);
2160 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
2161 result = AssignEnvironment(result);
2167 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
2168 LOperand* obj = (instr->access().IsExternalMemory() &&
2169 instr->access().offset() == 0)
2170 ? UseRegisterOrConstantAtStart(instr->object())
2171 : UseRegisterAtStart(instr->object());
2172 return DefineAsRegister(
new(zone()) LLoadNamedField(obj));
2176 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
2177 LOperand* context = UseFixed(instr->context(),
esi);
2180 LOperand* vector =
NULL;
2181 if (FLAG_vector_ics) {
2184 LLoadNamedGeneric* result =
new(zone()) LLoadNamedGeneric(
2185 context,
object, vector);
2186 return MarkAsCall(DefineFixed(result,
eax), instr);
2190 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
2191 HLoadFunctionPrototype* instr) {
2192 return AssignEnvironment(DefineAsRegister(
2193 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()),
2198 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
2199 return DefineAsRegister(
new(zone()) LLoadRoot);
2203 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
2204 DCHECK(instr->key()->representation().IsSmiOrInteger32());
2207 instr->key()->representation(), elements_kind);
2208 LOperand* key = clobbers_key
2209 ? UseTempRegister(instr->key())
2210 : UseRegisterOrConstantAtStart(instr->key());
2211 LInstruction* result =
NULL;
2213 if (!instr->is_typed_elements()) {
2214 LOperand* obj = UseRegisterAtStart(instr->elements());
2215 result = DefineAsRegister(
new(zone()) LLoadKeyed(obj, key));
2218 (instr->representation().IsInteger32() &&
2220 (instr->representation().IsDouble() &&
2222 LOperand* backing_store = UseRegister(instr->elements());
2223 result = DefineAsRegister(
new(zone()) LLoadKeyed(backing_store, key));
2226 if ((instr->is_external() || instr->is_fixed_typed_array()) ?
2233 instr->RequiresHoleCheck()) {
2234 result = AssignEnvironment(result);
2240 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
2241 LOperand* context = UseFixed(instr->context(),
esi);
2245 LOperand* vector =
NULL;
2246 if (FLAG_vector_ics) {
2249 LLoadKeyedGeneric* result =
2250 new(zone()) LLoadKeyedGeneric(context,
object, key, vector);
2251 return MarkAsCall(DefineFixed(result,
eax), instr);
2255 LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) {
2259 bool val_is_fixed_register =
2266 if (val_is_fixed_register) {
2267 return UseFixed(instr->value(),
eax);
2270 return UseRegister(instr->value());
2274 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
2275 if (!instr->is_typed_elements()) {
2276 DCHECK(instr->elements()->representation().IsTagged());
2277 DCHECK(instr->key()->representation().IsInteger32() ||
2278 instr->key()->representation().IsSmi());
2280 if (instr->value()->representation().IsDouble()) {
2281 LOperand*
object = UseRegisterAtStart(instr->elements());
2282 LOperand* val =
NULL;
2283 val = UseRegisterAtStart(instr->value());
2284 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
2285 return new(zone()) LStoreKeyed(
object, key, val);
2287 DCHECK(instr->value()->representation().IsSmiOrTagged());
2288 bool needs_write_barrier = instr->NeedsWriteBarrier();
2290 LOperand* obj = UseRegister(instr->elements());
2293 if (needs_write_barrier) {
2294 val = UseTempRegister(instr->value());
2295 key = UseTempRegister(instr->key());
2297 val = UseRegisterOrConstantAtStart(instr->value());
2298 key = UseRegisterOrConstantAtStart(instr->key());
2300 return new(zone()) LStoreKeyed(obj, key, val);
2306 (instr->value()->representation().IsInteger32() &&
2308 (instr->value()->representation().IsDouble() &&
2310 DCHECK((instr->is_fixed_typed_array() &&
2311 instr->elements()->representation().IsTagged()) ||
2312 (instr->is_external() &&
2313 instr->elements()->representation().IsExternal()));
2315 LOperand* backing_store = UseRegister(instr->elements());
2316 LOperand* val = GetStoreKeyedValueOperand(instr);
2318 instr->key()->representation(), elements_kind);
2319 LOperand* key = clobbers_key
2320 ? UseTempRegister(instr->key())
2321 : UseRegisterOrConstantAtStart(instr->key());
2322 return new(zone()) LStoreKeyed(backing_store, key, val);
2326 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
2327 LOperand* context = UseFixed(instr->context(),
esi);
2333 DCHECK(instr->object()->representation().IsTagged());
2334 DCHECK(instr->key()->representation().IsTagged());
2335 DCHECK(instr->value()->representation().IsTagged());
2337 LStoreKeyedGeneric* result =
2338 new(zone()) LStoreKeyedGeneric(context,
object, key, value);
2339 return MarkAsCall(result, instr);
2343 LInstruction* LChunkBuilder::DoTransitionElementsKind(
2344 HTransitionElementsKind* instr) {
2346 LOperand*
object = UseRegister(instr->object());
2347 LOperand* new_map_reg = TempRegister();
2348 LOperand* temp_reg = TempRegister();
2349 LTransitionElementsKind* result =
2350 new(zone()) LTransitionElementsKind(
object,
NULL,
2351 new_map_reg, temp_reg);
2354 LOperand*
object = UseFixed(instr->object(),
eax);
2355 LOperand* context = UseFixed(instr->context(),
esi);
2356 LTransitionElementsKind* result =
2357 new(zone()) LTransitionElementsKind(
object, context,
NULL,
NULL);
2358 return MarkAsCall(result, instr);
2363 LInstruction* LChunkBuilder::DoTrapAllocationMemento(
2364 HTrapAllocationMemento* instr) {
2365 LOperand*
object = UseRegister(instr->object());
2366 LOperand* temp = TempRegister();
2367 LTrapAllocationMemento* result =
2368 new(zone()) LTrapAllocationMemento(
object, temp);
2369 return AssignEnvironment(result);
2373 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2374 bool is_in_object = instr->access().IsInobject();
2375 bool is_external_location = instr->access().IsExternalMemory() &&
2376 instr->access().offset() == 0;
2377 bool needs_write_barrier = instr->NeedsWriteBarrier();
2378 bool needs_write_barrier_for_map = instr->has_transition() &&
2379 instr->NeedsWriteBarrierForMap();
2382 if (needs_write_barrier) {
2384 ? UseRegister(instr->object())
2385 : UseTempRegister(instr->object());
2386 }
else if (is_external_location) {
2388 DCHECK(!needs_write_barrier);
2389 DCHECK(!needs_write_barrier_for_map);
2390 obj = UseRegisterOrConstant(instr->object());
2392 obj = needs_write_barrier_for_map
2393 ? UseRegister(instr->object())
2394 : UseRegisterAtStart(instr->object());
2397 bool can_be_constant = instr->value()->IsConstant() &&
2398 HConstant::cast(instr->value())->NotInNewSpace() &&
2399 !instr->field_representation().IsDouble();
2402 if (instr->field_representation().IsInteger8() ||
2403 instr->field_representation().IsUInteger8()) {
2406 val = UseFixed(instr->value(),
eax);
2407 }
else if (needs_write_barrier) {
2408 val = UseTempRegister(instr->value());
2409 }
else if (can_be_constant) {
2410 val = UseRegisterOrConstant(instr->value());
2411 }
else if (instr->field_representation().IsDouble()) {
2412 val = UseRegisterAtStart(instr->value());
2414 val = UseRegister(instr->value());
2419 LOperand* temp = (!is_in_object || needs_write_barrier ||
2420 needs_write_barrier_for_map) ? TempRegister() :
NULL;
2423 LOperand* temp_map = needs_write_barrier_for_map ? TempRegister() :
NULL;
2425 return new(zone()) LStoreNamedField(obj, val, temp, temp_map);
2429 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2430 LOperand* context = UseFixed(instr->context(),
esi);
2435 LStoreNamedGeneric* result =
2436 new(zone()) LStoreNamedGeneric(context,
object, value);
2437 return MarkAsCall(result, instr);
2441 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2442 LOperand* context = UseFixed(instr->context(),
esi);
2443 LOperand* left = UseFixed(instr->left(),
edx);
2444 LOperand* right = UseFixed(instr->right(),
eax);
2445 LStringAdd* string_add =
new(zone()) LStringAdd(context, left, right);
2446 return MarkAsCall(DefineFixed(string_add,
eax), instr);
2450 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2451 LOperand*
string = UseTempRegister(instr->string());
2452 LOperand* index = UseTempRegister(instr->index());
2453 LOperand* context = UseAny(instr->context());
2454 LStringCharCodeAt* result =
2455 new(zone()) LStringCharCodeAt(context,
string, index);
2456 return AssignPointerMap(DefineAsRegister(result));
2460 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2461 LOperand* char_code = UseRegister(instr->value());
2462 LOperand* context = UseAny(instr->context());
2463 LStringCharFromCode* result =
2464 new(zone()) LStringCharFromCode(context, char_code);
2465 return AssignPointerMap(DefineAsRegister(result));
2469 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
2470 info()->MarkAsDeferredCalling();
2471 LOperand* context = UseAny(instr->context());
2472 LOperand*
size = instr->size()->IsConstant()
2473 ? UseConstant(instr->size())
2474 : UseTempRegister(instr->
size());
2475 LOperand* temp = TempRegister();
2476 LAllocate* result =
new(zone()) LAllocate(context,
size, temp);
2477 return AssignPointerMap(DefineAsRegister(result));
2481 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2482 LOperand* context = UseFixed(instr->context(),
esi);
2484 DefineFixed(
new(zone()) LRegExpLiteral(context),
eax), instr);
2488 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2489 LOperand* context = UseFixed(instr->context(),
esi);
2491 DefineFixed(
new(zone()) LFunctionLiteral(context),
eax), instr);
2495 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2496 DCHECK(argument_count_ == 0);
2497 allocator_->MarkAsOsrEntry();
2498 current_block_->last_environment()->set_ast_id(instr->ast_id());
2499 return AssignEnvironment(
new(zone()) LOsrEntry);
2503 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2504 LParameter* result =
new(zone()) LParameter;
2505 if (instr->kind() == HParameter::STACK_PARAMETER) {
2506 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2507 return DefineAsSpilled(result, spill_index);
2509 DCHECK(info()->IsStub());
2510 CallInterfaceDescriptor descriptor =
2511 info()->code_stub()->GetCallInterfaceDescriptor();
2512 int index =
static_cast<int>(instr->index());
2513 Register reg = descriptor.GetEnvironmentParameterRegister(index);
2514 return DefineFixed(result, reg);
2519 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2522 int env_index = instr->index();
2523 int spill_index = 0;
2524 if (instr->environment()->is_parameter_index(env_index)) {
2525 spill_index = chunk()->GetParameterStackSlot(env_index);
2527 spill_index = env_index - instr->environment()->first_local_index();
2529 Retry(kNotEnoughSpillSlotsForOsr);
2532 if (spill_index == 0) {
2535 spill_index = graph()->osr()->UnoptimizedFrameSlots();
2538 return DefineAsSpilled(
new(zone()) LUnknownOSRValue, spill_index);
2542 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2543 LOperand* context = UseFixed(instr->context(),
esi);
2544 LCallStub* result =
new(zone()) LCallStub(context);
2545 return MarkAsCall(DefineFixed(result,
eax), instr);
2549 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2558 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
2559 instr->ReplayEnvironment(current_block_->last_environment());
2566 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2567 info()->MarkAsRequiresFrame();
2568 LOperand* args = UseRegister(instr->arguments());
2571 if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
2572 length = UseRegisterOrConstant(instr->length());
2573 index = UseOrConstant(instr->index());
2575 length = UseTempRegister(instr->length());
2576 index = Use(instr->index());
2578 return DefineAsRegister(
new(zone()) LAccessArgumentsAt(args, length, index));
2582 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2583 LOperand*
object = UseFixed(instr->value(),
eax);
2584 LToFastProperties* result =
new(zone()) LToFastProperties(
object);
2585 return MarkAsCall(DefineFixed(result,
eax), instr);
2589 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2590 LOperand* context = UseFixed(instr->context(),
esi);
2591 LOperand* value = UseAtStart(instr->value());
2592 LTypeof* result =
new(zone()) LTypeof(context, value);
2593 return MarkAsCall(DefineFixed(result,
eax), instr);
2597 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2598 return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
2602 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2603 HIsConstructCallAndBranch* instr) {
2604 return new(zone()) LIsConstructCallAndBranch(TempRegister());
2608 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2609 instr->ReplayEnvironment(current_block_->last_environment());
2614 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2615 info()->MarkAsDeferredCalling();
2616 if (instr->is_function_entry()) {
2617 LOperand* context = UseFixed(instr->context(),
esi);
2618 return MarkAsCall(
new(zone()) LStackCheck(context), instr);
2620 DCHECK(instr->is_backwards_branch());
2621 LOperand* context = UseAny(instr->context());
2622 return AssignEnvironment(
2623 AssignPointerMap(
new(zone()) LStackCheck(context)));
2628 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2629 HEnvironment* outer = current_block_->last_environment();
2630 outer->set_ast_id(instr->ReturnId());
2631 HConstant* undefined = graph()->GetConstantUndefined();
2632 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2633 instr->arguments_count(),
2636 instr->inlining_kind());
2638 if (instr->arguments_var() !=
NULL && instr->arguments_object()->IsLinked()) {
2639 inner->Bind(instr->arguments_var(), instr->arguments_object());
2641 inner->BindContext(instr->closure_context());
2642 inner->set_entry(instr);
2643 current_block_->UpdateEnvironment(inner);
2644 chunk_->AddInlinedClosure(instr->closure());
2649 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2650 LInstruction* pop =
NULL;
2652 HEnvironment* env = current_block_->last_environment();
2654 if (env->entry()->arguments_pushed()) {
2655 int argument_count = env->arguments_environment()->parameter_count();
2656 pop =
new(zone()) LDrop(argument_count);
2657 DCHECK(instr->argument_delta() == -argument_count);
2660 HEnvironment* outer = current_block_->last_environment()->
2661 DiscardInlined(
false);
2662 current_block_->UpdateEnvironment(outer);
2667 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2668 LOperand* context = UseFixed(instr->context(),
esi);
2669 LOperand*
object = UseFixed(instr->enumerable(),
eax);
2670 LForInPrepareMap* result =
new(zone()) LForInPrepareMap(context,
object);
2671 return MarkAsCall(DefineFixed(result,
eax), instr, CAN_DEOPTIMIZE_EAGERLY);
2675 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2676 LOperand*
map = UseRegister(instr->map());
2677 return AssignEnvironment(DefineAsRegister(
2678 new(zone()) LForInCacheArray(
map)));
2682 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2683 LOperand* value = UseRegisterAtStart(instr->value());
2684 LOperand*
map = UseRegisterAtStart(instr->map());
2685 return AssignEnvironment(
new(zone()) LCheckMapValue(value,
map));
2689 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2690 LOperand*
object = UseRegister(instr->object());
2691 LOperand* index = UseTempRegister(instr->index());
2692 LLoadFieldByIndex* load =
new(zone()) LLoadFieldByIndex(
object, index);
2693 LInstruction* result = DefineSameAsFirst(load);
2694 return AssignPointerMap(result);
2698 LInstruction* LChunkBuilder::DoStoreFrameContext(HStoreFrameContext* instr) {
2699 LOperand* context = UseRegisterAtStart(instr->context());
2700 return new(zone()) LStoreFrameContext(context);
2704 LInstruction* LChunkBuilder::DoAllocateBlockContext(
2705 HAllocateBlockContext* instr) {
2706 LOperand* context = UseFixed(instr->context(),
esi);
2707 LOperand*
function = UseRegisterAtStart(instr->function());
2708 LAllocateBlockContext* result =
2709 new(zone()) LAllocateBlockContext(context,
function);
2710 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)
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(XMMRegister reg)