1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "src/arm/lithium-codegen-arm.h"
10 #include "src/hydrogen-osr.h"
11 #include "src/lithium-inl.h"
16 #define DEFINE_COMPILE(type) \
17 void L##type::CompileToNative(LCodeGen* generator) { \
18 generator->Do##type(this); \
20 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
24 void LInstruction::VerifyCall() {
25 // Call instructions can use only fixed registers as temporaries and
26 // outputs because all registers are blocked by the calling convention.
27 // Inputs operands must use a fixed register or use-at-start policy or
28 // a non-register policy.
29 DCHECK(Output() == NULL ||
30 LUnallocated::cast(Output())->HasFixedPolicy() ||
31 !LUnallocated::cast(Output())->HasRegisterPolicy());
32 for (UseIterator it(this); !it.Done(); it.Advance()) {
33 LUnallocated* operand = LUnallocated::cast(it.Current());
34 DCHECK(operand->HasFixedPolicy() ||
35 operand->IsUsedAtStart());
37 for (TempIterator it(this); !it.Done(); it.Advance()) {
38 LUnallocated* operand = LUnallocated::cast(it.Current());
39 DCHECK(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
45 void LInstruction::PrintTo(StringStream* stream) {
46 stream->Add("%s ", this->Mnemonic());
48 PrintOutputOperandTo(stream);
52 if (HasEnvironment()) {
54 environment()->PrintTo(stream);
57 if (HasPointerMap()) {
59 pointer_map()->PrintTo(stream);
64 void LInstruction::PrintDataTo(StringStream* stream) {
66 for (int i = 0; i < InputCount(); i++) {
67 if (i > 0) stream->Add(" ");
68 if (InputAt(i) == NULL) {
71 InputAt(i)->PrintTo(stream);
77 void LInstruction::PrintOutputOperandTo(StringStream* stream) {
78 if (HasResult()) result()->PrintTo(stream);
82 void LLabel::PrintDataTo(StringStream* stream) {
83 LGap::PrintDataTo(stream);
84 LLabel* rep = replacement();
86 stream->Add(" Dead block replaced with B%d", rep->block_id());
91 bool LGap::IsRedundant() const {
92 for (int i = 0; i < 4; i++) {
93 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
102 void LGap::PrintDataTo(StringStream* stream) {
103 for (int i = 0; i < 4; i++) {
105 if (parallel_moves_[i] != NULL) {
106 parallel_moves_[i]->PrintDataTo(stream);
113 const char* LArithmeticD::Mnemonic() const {
115 case Token::ADD: return "add-d";
116 case Token::SUB: return "sub-d";
117 case Token::MUL: return "mul-d";
118 case Token::DIV: return "div-d";
119 case Token::MOD: return "mod-d";
127 const char* LArithmeticT::Mnemonic() const {
129 case Token::ADD: return "add-t";
130 case Token::SUB: return "sub-t";
131 case Token::MUL: return "mul-t";
132 case Token::MOD: return "mod-t";
133 case Token::DIV: return "div-t";
134 case Token::BIT_AND: return "bit-and-t";
135 case Token::BIT_OR: return "bit-or-t";
136 case Token::BIT_XOR: return "bit-xor-t";
137 case Token::ROR: return "ror-t";
138 case Token::SHL: return "shl-t";
139 case Token::SAR: return "sar-t";
140 case Token::SHR: return "shr-t";
148 bool LGoto::HasInterestingComment(LCodeGen* gen) const {
149 return !gen->IsNextEmittedBlock(block_id());
153 void LGoto::PrintDataTo(StringStream* stream) {
154 stream->Add("B%d", block_id());
158 void LBranch::PrintDataTo(StringStream* stream) {
159 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
160 value()->PrintTo(stream);
164 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
166 left()->PrintTo(stream);
167 stream->Add(" %s ", Token::String(op()));
168 right()->PrintTo(stream);
169 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
173 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
174 stream->Add("if is_object(");
175 value()->PrintTo(stream);
176 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
180 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
181 stream->Add("if is_string(");
182 value()->PrintTo(stream);
183 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
187 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
188 stream->Add("if is_smi(");
189 value()->PrintTo(stream);
190 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
194 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
195 stream->Add("if is_undetectable(");
196 value()->PrintTo(stream);
197 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
201 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
202 stream->Add("if string_compare(");
203 left()->PrintTo(stream);
204 right()->PrintTo(stream);
205 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
209 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
210 stream->Add("if has_instance_type(");
211 value()->PrintTo(stream);
212 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
216 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
217 stream->Add("if has_cached_array_index(");
218 value()->PrintTo(stream);
219 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
223 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
224 stream->Add("if class_of_test(");
225 value()->PrintTo(stream);
226 stream->Add(", \"%o\") then B%d else B%d",
227 *hydrogen()->class_name(),
233 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
234 stream->Add("if typeof ");
235 value()->PrintTo(stream);
236 stream->Add(" == \"%s\" then B%d else B%d",
237 hydrogen()->type_literal()->ToCString().get(),
238 true_block_id(), false_block_id());
242 void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
244 function()->PrintTo(stream);
245 stream->Add(".code_entry = ");
246 code_object()->PrintTo(stream);
250 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
252 base_object()->PrintTo(stream);
254 offset()->PrintTo(stream);
258 void LCallJSFunction::PrintDataTo(StringStream* stream) {
260 function()->PrintTo(stream);
261 stream->Add("#%d / ", arity());
265 void LCallWithDescriptor::PrintDataTo(StringStream* stream) {
266 for (int i = 0; i < InputCount(); i++) {
267 InputAt(i)->PrintTo(stream);
270 stream->Add("#%d / ", arity());
274 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
275 context()->PrintTo(stream);
276 stream->Add("[%d]", slot_index());
280 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
281 context()->PrintTo(stream);
282 stream->Add("[%d] <- ", slot_index());
283 value()->PrintTo(stream);
287 void LInvokeFunction::PrintDataTo(StringStream* stream) {
289 function()->PrintTo(stream);
290 stream->Add(" #%d / ", arity());
294 void LCallNew::PrintDataTo(StringStream* stream) {
296 constructor()->PrintTo(stream);
297 stream->Add(" #%d / ", arity());
301 void LCallNewArray::PrintDataTo(StringStream* stream) {
303 constructor()->PrintTo(stream);
304 stream->Add(" #%d / ", arity());
305 ElementsKind kind = hydrogen()->elements_kind();
306 stream->Add(" (%s) ", ElementsKindToString(kind));
310 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
311 arguments()->PrintTo(stream);
312 stream->Add(" length ");
313 length()->PrintTo(stream);
314 stream->Add(" index ");
315 index()->PrintTo(stream);
319 void LStoreNamedField::PrintDataTo(StringStream* stream) {
320 object()->PrintTo(stream);
321 std::ostringstream os;
322 os << hydrogen()->access() << " <- ";
323 stream->Add(os.str().c_str());
324 value()->PrintTo(stream);
328 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
329 object()->PrintTo(stream);
331 stream->Add(String::cast(*name())->ToCString().get());
333 value()->PrintTo(stream);
337 void LLoadKeyed::PrintDataTo(StringStream* stream) {
338 elements()->PrintTo(stream);
340 key()->PrintTo(stream);
341 if (hydrogen()->IsDehoisted()) {
342 stream->Add(" + %d]", base_offset());
349 void LStoreKeyed::PrintDataTo(StringStream* stream) {
350 elements()->PrintTo(stream);
352 key()->PrintTo(stream);
353 if (hydrogen()->IsDehoisted()) {
354 stream->Add(" + %d] <-", base_offset());
356 stream->Add("] <- ");
359 if (value() == NULL) {
360 DCHECK(hydrogen()->IsConstantHoleStore() &&
361 hydrogen()->value()->representation().IsDouble());
362 stream->Add("<the hole(nan)>");
364 value()->PrintTo(stream);
369 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
370 object()->PrintTo(stream);
372 key()->PrintTo(stream);
373 stream->Add("] <- ");
374 value()->PrintTo(stream);
378 void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
379 object()->PrintTo(stream);
380 stream->Add(" %p -> %p", *original_map(), *transitioned_map());
384 int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
385 // Skip a slot if for a double-width slot.
386 if (kind == DOUBLE_REGISTERS) spill_slot_count_++;
387 return spill_slot_count_++;
391 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
392 int index = GetNextSpillIndex(kind);
393 if (kind == DOUBLE_REGISTERS) {
394 return LDoubleStackSlot::Create(index, zone());
396 DCHECK(kind == GENERAL_REGISTERS);
397 return LStackSlot::Create(index, zone());
402 LPlatformChunk* LChunkBuilder::Build() {
404 chunk_ = new(zone()) LPlatformChunk(info(), graph());
405 LPhase phase("L_Building chunk", chunk_);
408 // If compiling for OSR, reserve space for the unoptimized frame,
409 // which will be subsumed into this frame.
410 if (graph()->has_osr()) {
411 for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
412 chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
416 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
417 for (int i = 0; i < blocks->length(); i++) {
418 HBasicBlock* next = NULL;
419 if (i < blocks->length() - 1) next = blocks->at(i + 1);
420 DoBasicBlock(blocks->at(i), next);
421 if (is_aborted()) return NULL;
428 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
429 return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
430 Register::ToAllocationIndex(reg));
434 LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
435 return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
436 DoubleRegister::ToAllocationIndex(reg));
440 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
441 return Use(value, ToUnallocated(fixed_register));
445 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, DoubleRegister reg) {
446 return Use(value, ToUnallocated(reg));
450 LOperand* LChunkBuilder::UseRegister(HValue* value) {
451 return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
455 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
457 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
458 LUnallocated::USED_AT_START));
462 LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
463 return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
467 LOperand* LChunkBuilder::Use(HValue* value) {
468 return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
472 LOperand* LChunkBuilder::UseAtStart(HValue* value) {
473 return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
474 LUnallocated::USED_AT_START));
478 LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
479 return value->IsConstant()
480 ? chunk_->DefineConstantOperand(HConstant::cast(value))
485 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
486 return value->IsConstant()
487 ? chunk_->DefineConstantOperand(HConstant::cast(value))
492 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
493 return value->IsConstant()
494 ? chunk_->DefineConstantOperand(HConstant::cast(value))
495 : UseRegister(value);
499 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
500 return value->IsConstant()
501 ? chunk_->DefineConstantOperand(HConstant::cast(value))
502 : UseRegisterAtStart(value);
506 LOperand* LChunkBuilder::UseConstant(HValue* value) {
507 return chunk_->DefineConstantOperand(HConstant::cast(value));
511 LOperand* LChunkBuilder::UseAny(HValue* value) {
512 return value->IsConstant()
513 ? chunk_->DefineConstantOperand(HConstant::cast(value))
514 : Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
518 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
519 if (value->EmitAtUses()) {
520 HInstruction* instr = HInstruction::cast(value);
521 VisitInstruction(instr);
523 operand->set_virtual_register(value->id());
528 LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr,
529 LUnallocated* result) {
530 result->set_virtual_register(current_instruction_->id());
531 instr->set_result(result);
536 LInstruction* LChunkBuilder::DefineAsRegister(
537 LTemplateResultInstruction<1>* instr) {
539 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
543 LInstruction* LChunkBuilder::DefineAsSpilled(
544 LTemplateResultInstruction<1>* instr, int index) {
546 new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
550 LInstruction* LChunkBuilder::DefineSameAsFirst(
551 LTemplateResultInstruction<1>* instr) {
553 new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
557 LInstruction* LChunkBuilder::DefineFixed(
558 LTemplateResultInstruction<1>* instr, Register reg) {
559 return Define(instr, ToUnallocated(reg));
563 LInstruction* LChunkBuilder::DefineFixedDouble(
564 LTemplateResultInstruction<1>* instr, DoubleRegister reg) {
565 return Define(instr, ToUnallocated(reg));
569 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
570 HEnvironment* hydrogen_env = current_block_->last_environment();
571 int argument_index_accumulator = 0;
572 ZoneList<HValue*> objects_to_materialize(0, zone());
573 instr->set_environment(CreateEnvironment(hydrogen_env,
574 &argument_index_accumulator,
575 &objects_to_materialize));
580 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
581 HInstruction* hinstr,
582 CanDeoptimize can_deoptimize) {
583 info()->MarkAsNonDeferredCalling();
588 instr = AssignPointerMap(instr);
590 // If instruction does not have side-effects lazy deoptimization
591 // after the call will try to deoptimize to the point before the call.
592 // Thus we still need to attach environment to this call even if
593 // call sequence can not deoptimize eagerly.
594 bool needs_environment =
595 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
596 !hinstr->HasObservableSideEffects();
597 if (needs_environment && !instr->HasEnvironment()) {
598 instr = AssignEnvironment(instr);
599 // We can't really figure out if the environment is needed or not.
600 instr->environment()->set_has_been_used();
607 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
608 DCHECK(!instr->HasPointerMap());
609 instr->set_pointer_map(new(zone()) LPointerMap(zone()));
614 LUnallocated* LChunkBuilder::TempRegister() {
615 LUnallocated* operand =
616 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
617 int vreg = allocator_->GetVirtualRegister();
618 if (!allocator_->AllocationOk()) {
619 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
622 operand->set_virtual_register(vreg);
627 LUnallocated* LChunkBuilder::TempDoubleRegister() {
628 LUnallocated* operand =
629 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_DOUBLE_REGISTER);
630 int vreg = allocator_->GetVirtualRegister();
631 if (!allocator_->AllocationOk()) {
632 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
635 operand->set_virtual_register(vreg);
640 LOperand* LChunkBuilder::FixedTemp(Register reg) {
641 LUnallocated* operand = ToUnallocated(reg);
642 DCHECK(operand->HasFixedPolicy());
647 LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) {
648 LUnallocated* operand = ToUnallocated(reg);
649 DCHECK(operand->HasFixedPolicy());
654 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
655 return new(zone()) LLabel(instr->block());
659 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
660 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value())));
664 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
670 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
671 return AssignEnvironment(new(zone()) LDeoptimize);
675 LInstruction* LChunkBuilder::DoShift(Token::Value op,
676 HBitwiseBinaryOperation* instr) {
677 if (instr->representation().IsSmiOrInteger32()) {
678 DCHECK(instr->left()->representation().Equals(instr->representation()));
679 DCHECK(instr->right()->representation().Equals(instr->representation()));
680 LOperand* left = UseRegisterAtStart(instr->left());
682 HValue* right_value = instr->right();
683 LOperand* right = NULL;
684 int constant_value = 0;
685 bool does_deopt = false;
686 if (right_value->IsConstant()) {
687 HConstant* constant = HConstant::cast(right_value);
688 right = chunk_->DefineConstantOperand(constant);
689 constant_value = constant->Integer32Value() & 0x1f;
690 // Left shifts can deoptimize if we shift by > 0 and the result cannot be
692 if (instr->representation().IsSmi() && constant_value > 0) {
693 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi);
696 right = UseRegisterAtStart(right_value);
699 // Shift operations can only deoptimize if we do a logical shift
700 // by 0 and the result cannot be truncated to int32.
701 if (op == Token::SHR && constant_value == 0) {
702 does_deopt = !instr->CheckFlag(HInstruction::kUint32);
705 LInstruction* result =
706 DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
707 return does_deopt ? AssignEnvironment(result) : result;
709 return DoArithmeticT(op, instr);
714 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
715 HArithmeticBinaryOperation* instr) {
716 DCHECK(instr->representation().IsDouble());
717 DCHECK(instr->left()->representation().IsDouble());
718 DCHECK(instr->right()->representation().IsDouble());
719 if (op == Token::MOD) {
720 LOperand* left = UseFixedDouble(instr->left(), d0);
721 LOperand* right = UseFixedDouble(instr->right(), d1);
722 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
723 return MarkAsCall(DefineFixedDouble(result, d0), instr);
725 LOperand* left = UseRegisterAtStart(instr->left());
726 LOperand* right = UseRegisterAtStart(instr->right());
727 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
728 return DefineAsRegister(result);
733 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
734 HBinaryOperation* instr) {
735 HValue* left = instr->left();
736 HValue* right = instr->right();
737 DCHECK(left->representation().IsTagged());
738 DCHECK(right->representation().IsTagged());
739 LOperand* context = UseFixed(instr->context(), cp);
740 LOperand* left_operand = UseFixed(left, r1);
741 LOperand* right_operand = UseFixed(right, r0);
742 LArithmeticT* result =
743 new(zone()) LArithmeticT(op, context, left_operand, right_operand);
744 return MarkAsCall(DefineFixed(result, r0), instr);
748 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
749 DCHECK(is_building());
750 current_block_ = block;
751 next_block_ = next_block;
752 if (block->IsStartBlock()) {
753 block->UpdateEnvironment(graph_->start_environment());
755 } else if (block->predecessors()->length() == 1) {
756 // We have a single predecessor => copy environment and outgoing
757 // argument count from the predecessor.
758 DCHECK(block->phis()->length() == 0);
759 HBasicBlock* pred = block->predecessors()->at(0);
760 HEnvironment* last_environment = pred->last_environment();
761 DCHECK(last_environment != NULL);
762 // Only copy the environment, if it is later used again.
763 if (pred->end()->SecondSuccessor() == NULL) {
764 DCHECK(pred->end()->FirstSuccessor() == block);
766 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
767 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
768 last_environment = last_environment->Copy();
771 block->UpdateEnvironment(last_environment);
772 DCHECK(pred->argument_count() >= 0);
773 argument_count_ = pred->argument_count();
775 // We are at a state join => process phis.
776 HBasicBlock* pred = block->predecessors()->at(0);
777 // No need to copy the environment, it cannot be used later.
778 HEnvironment* last_environment = pred->last_environment();
779 for (int i = 0; i < block->phis()->length(); ++i) {
780 HPhi* phi = block->phis()->at(i);
781 if (phi->HasMergedIndex()) {
782 last_environment->SetValueAt(phi->merged_index(), phi);
785 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
786 if (block->deleted_phis()->at(i) < last_environment->length()) {
787 last_environment->SetValueAt(block->deleted_phis()->at(i),
788 graph_->GetConstantUndefined());
791 block->UpdateEnvironment(last_environment);
792 // Pick up the outgoing argument count of one of the predecessors.
793 argument_count_ = pred->argument_count();
795 HInstruction* current = block->first();
796 int start = chunk_->instructions()->length();
797 while (current != NULL && !is_aborted()) {
798 // Code for constants in registers is generated lazily.
799 if (!current->EmitAtUses()) {
800 VisitInstruction(current);
802 current = current->next();
804 int end = chunk_->instructions()->length() - 1;
806 block->set_first_instruction_index(start);
807 block->set_last_instruction_index(end);
809 block->set_argument_count(argument_count_);
811 current_block_ = NULL;
815 void LChunkBuilder::VisitInstruction(HInstruction* current) {
816 HInstruction* old_current = current_instruction_;
817 current_instruction_ = current;
819 LInstruction* instr = NULL;
820 if (current->CanReplaceWithDummyUses()) {
821 if (current->OperandCount() == 0) {
822 instr = DefineAsRegister(new(zone()) LDummy());
824 DCHECK(!current->OperandAt(0)->IsControlInstruction());
825 instr = DefineAsRegister(new(zone())
826 LDummyUse(UseAny(current->OperandAt(0))));
828 for (int i = 1; i < current->OperandCount(); ++i) {
829 if (current->OperandAt(i)->IsControlInstruction()) continue;
830 LInstruction* dummy =
831 new(zone()) LDummyUse(UseAny(current->OperandAt(i)));
832 dummy->set_hydrogen_value(current);
833 chunk_->AddInstruction(dummy, current_block_);
836 HBasicBlock* successor;
837 if (current->IsControlInstruction() &&
838 HControlInstruction::cast(current)->KnownSuccessorBlock(&successor) &&
840 instr = new(zone()) LGoto(successor);
842 instr = current->CompileToLithium(this);
846 argument_count_ += current->argument_delta();
847 DCHECK(argument_count_ >= 0);
850 AddInstruction(instr, current);
853 current_instruction_ = old_current;
857 void LChunkBuilder::AddInstruction(LInstruction* instr,
858 HInstruction* hydrogen_val) {
859 // Associate the hydrogen instruction first, since we may need it for
860 // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
861 instr->set_hydrogen_value(hydrogen_val);
864 // Make sure that the lithium instruction has either no fixed register
865 // constraints in temps or the result OR no uses that are only used at
866 // start. If this invariant doesn't hold, the register allocator can decide
867 // to insert a split of a range immediately before the instruction due to an
868 // already allocated register needing to be used for the instruction's fixed
869 // register constraint. In this case, The register allocator won't see an
870 // interference between the split child and the use-at-start (it would if
871 // the it was just a plain use), so it is free to move the split child into
872 // the same register that is used for the use-at-start.
873 // See https://code.google.com/p/chromium/issues/detail?id=201590
874 if (!(instr->ClobbersRegisters() &&
875 instr->ClobbersDoubleRegisters(isolate()))) {
877 int used_at_start = 0;
878 for (UseIterator it(instr); !it.Done(); it.Advance()) {
879 LUnallocated* operand = LUnallocated::cast(it.Current());
880 if (operand->IsUsedAtStart()) ++used_at_start;
882 if (instr->Output() != NULL) {
883 if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
885 for (TempIterator it(instr); !it.Done(); it.Advance()) {
886 LUnallocated* operand = LUnallocated::cast(it.Current());
887 if (operand->HasFixedPolicy()) ++fixed;
889 DCHECK(fixed == 0 || used_at_start == 0);
893 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
894 instr = AssignPointerMap(instr);
896 if (FLAG_stress_environments && !instr->HasEnvironment()) {
897 instr = AssignEnvironment(instr);
899 chunk_->AddInstruction(instr, current_block_);
901 if (instr->IsCall()) {
902 HValue* hydrogen_value_for_lazy_bailout = hydrogen_val;
903 LInstruction* instruction_needing_environment = NULL;
904 if (hydrogen_val->HasObservableSideEffects()) {
905 HSimulate* sim = HSimulate::cast(hydrogen_val->next());
906 instruction_needing_environment = instr;
907 sim->ReplayEnvironment(current_block_->last_environment());
908 hydrogen_value_for_lazy_bailout = sim;
910 LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout());
911 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
912 chunk_->AddInstruction(bailout, current_block_);
913 if (instruction_needing_environment != NULL) {
914 // Store the lazy deopt environment with the instruction if needed.
915 // Right now it is only used for LInstanceOfKnownGlobal.
916 instruction_needing_environment->
917 SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
923 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
924 return new(zone()) LGoto(instr->FirstSuccessor());
928 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
929 HValue* value = instr->value();
930 Representation r = value->representation();
931 HType type = value->type();
932 ToBooleanStub::Types expected = instr->expected_input_types();
933 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
935 bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() ||
936 type.IsJSArray() || type.IsHeapNumber() || type.IsString();
937 LInstruction* branch = new(zone()) LBranch(UseRegister(value));
939 ((!expected.Contains(ToBooleanStub::SMI) && expected.NeedsMap()) ||
940 !expected.IsGeneric())) {
941 branch = AssignEnvironment(branch);
947 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
948 return new(zone()) LDebugBreak();
952 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
953 DCHECK(instr->value()->representation().IsTagged());
954 LOperand* value = UseRegisterAtStart(instr->value());
955 LOperand* temp = TempRegister();
956 return new(zone()) LCmpMapAndBranch(value, temp);
960 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) {
961 info()->MarkAsRequiresFrame();
962 LOperand* value = UseRegister(instr->value());
963 return DefineAsRegister(new(zone()) LArgumentsLength(value));
967 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
968 info()->MarkAsRequiresFrame();
969 return DefineAsRegister(new(zone()) LArgumentsElements);
973 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
974 LOperand* context = UseFixed(instr->context(), cp);
975 LInstanceOf* result =
976 new(zone()) LInstanceOf(context, UseFixed(instr->left(), r0),
977 UseFixed(instr->right(), r1));
978 return MarkAsCall(DefineFixed(result, r0), instr);
982 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
983 HInstanceOfKnownGlobal* instr) {
984 LInstanceOfKnownGlobal* result =
985 new(zone()) LInstanceOfKnownGlobal(
986 UseFixed(instr->context(), cp),
987 UseFixed(instr->left(), r0),
989 return MarkAsCall(DefineFixed(result, r0), instr);
993 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
994 LOperand* receiver = UseRegisterAtStart(instr->receiver());
995 LOperand* function = UseRegisterAtStart(instr->function());
996 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function);
997 return AssignEnvironment(DefineAsRegister(result));
1001 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1002 LOperand* function = UseFixed(instr->function(), r1);
1003 LOperand* receiver = UseFixed(instr->receiver(), r0);
1004 LOperand* length = UseFixed(instr->length(), r2);
1005 LOperand* elements = UseFixed(instr->elements(), r3);
1006 LApplyArguments* result = new(zone()) LApplyArguments(function,
1010 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
1014 LInstruction* LChunkBuilder::DoPushArguments(HPushArguments* instr) {
1015 int argc = instr->OperandCount();
1016 for (int i = 0; i < argc; ++i) {
1017 LOperand* argument = Use(instr->argument(i));
1018 AddInstruction(new(zone()) LPushArgument(argument), instr);
1024 LInstruction* LChunkBuilder::DoStoreCodeEntry(
1025 HStoreCodeEntry* store_code_entry) {
1026 LOperand* function = UseRegister(store_code_entry->function());
1027 LOperand* code_object = UseTempRegister(store_code_entry->code_object());
1028 return new(zone()) LStoreCodeEntry(function, code_object);
1032 LInstruction* LChunkBuilder::DoInnerAllocatedObject(
1033 HInnerAllocatedObject* instr) {
1034 LOperand* base_object = UseRegisterAtStart(instr->base_object());
1035 LOperand* offset = UseRegisterOrConstantAtStart(instr->offset());
1036 return DefineAsRegister(
1037 new(zone()) LInnerAllocatedObject(base_object, offset));
1041 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
1042 return instr->HasNoUses()
1044 : DefineAsRegister(new(zone()) LThisFunction);
1048 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1049 if (instr->HasNoUses()) return NULL;
1051 if (info()->IsStub()) {
1052 return DefineFixed(new(zone()) LContext, cp);
1055 return DefineAsRegister(new(zone()) LContext);
1059 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1060 LOperand* context = UseFixed(instr->context(), cp);
1061 return MarkAsCall(new(zone()) LDeclareGlobals(context), instr);
1065 LInstruction* LChunkBuilder::DoCallJSFunction(
1066 HCallJSFunction* instr) {
1067 LOperand* function = UseFixed(instr->function(), r1);
1069 LCallJSFunction* result = new(zone()) LCallJSFunction(function);
1071 return MarkAsCall(DefineFixed(result, r0), instr);
1075 LInstruction* LChunkBuilder::DoCallWithDescriptor(
1076 HCallWithDescriptor* instr) {
1077 CallInterfaceDescriptor descriptor = instr->descriptor();
1079 LOperand* target = UseRegisterOrConstantAtStart(instr->target());
1080 ZoneList<LOperand*> ops(instr->OperandCount(), zone());
1081 ops.Add(target, zone());
1082 for (int i = 1; i < instr->OperandCount(); i++) {
1084 UseFixed(instr->OperandAt(i), descriptor.GetParameterRegister(i - 1));
1085 ops.Add(op, zone());
1088 LCallWithDescriptor* result = new(zone()) LCallWithDescriptor(
1089 descriptor, ops, zone());
1090 return MarkAsCall(DefineFixed(result, r0), instr);
1094 LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
1095 HTailCallThroughMegamorphicCache* instr) {
1096 LOperand* context = UseFixed(instr->context(), cp);
1097 LOperand* receiver_register =
1098 UseFixed(instr->receiver(), LoadDescriptor::ReceiverRegister());
1099 LOperand* name_register =
1100 UseFixed(instr->name(), LoadDescriptor::NameRegister());
1101 // Not marked as call. It can't deoptimize, and it never returns.
1102 return new (zone()) LTailCallThroughMegamorphicCache(
1103 context, receiver_register, name_register);
1107 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1108 LOperand* context = UseFixed(instr->context(), cp);
1109 LOperand* function = UseFixed(instr->function(), r1);
1110 LInvokeFunction* result = new(zone()) LInvokeFunction(context, function);
1111 return MarkAsCall(DefineFixed(result, r0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1115 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1116 switch (instr->op()) {
1118 return DoMathFloor(instr);
1120 return DoMathRound(instr);
1122 return DoMathFround(instr);
1124 return DoMathAbs(instr);
1126 return DoMathLog(instr);
1128 return DoMathExp(instr);
1130 return DoMathSqrt(instr);
1132 return DoMathPowHalf(instr);
1134 return DoMathClz32(instr);
1142 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
1143 LOperand* input = UseRegister(instr->value());
1144 LMathFloor* result = new(zone()) LMathFloor(input);
1145 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1149 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
1150 LOperand* input = UseRegister(instr->value());
1151 LOperand* temp = TempDoubleRegister();
1152 LMathRound* result = new(zone()) LMathRound(input, temp);
1153 return AssignEnvironment(DefineAsRegister(result));
1157 LInstruction* LChunkBuilder::DoMathFround(HUnaryMathOperation* instr) {
1158 LOperand* input = UseRegister(instr->value());
1159 LMathFround* result = new (zone()) LMathFround(input);
1160 return DefineAsRegister(result);
1164 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1165 Representation r = instr->value()->representation();
1166 LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32())
1168 : UseFixed(instr->context(), cp);
1169 LOperand* input = UseRegister(instr->value());
1170 LInstruction* result =
1171 DefineAsRegister(new(zone()) LMathAbs(context, input));
1172 if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result);
1173 if (!r.IsDouble()) result = AssignEnvironment(result);
1178 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
1179 DCHECK(instr->representation().IsDouble());
1180 DCHECK(instr->value()->representation().IsDouble());
1181 LOperand* input = UseFixedDouble(instr->value(), d0);
1182 return MarkAsCall(DefineFixedDouble(new(zone()) LMathLog(input), d0), instr);
1186 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
1187 LOperand* input = UseRegisterAtStart(instr->value());
1188 LMathClz32* result = new(zone()) LMathClz32(input);
1189 return DefineAsRegister(result);
1193 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1194 DCHECK(instr->representation().IsDouble());
1195 DCHECK(instr->value()->representation().IsDouble());
1196 LOperand* input = UseRegister(instr->value());
1197 LOperand* temp1 = TempRegister();
1198 LOperand* temp2 = TempRegister();
1199 LOperand* double_temp = TempDoubleRegister();
1200 LMathExp* result = new(zone()) LMathExp(input, double_temp, temp1, temp2);
1201 return DefineAsRegister(result);
1205 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
1206 LOperand* input = UseRegisterAtStart(instr->value());
1207 LMathSqrt* result = new(zone()) LMathSqrt(input);
1208 return DefineAsRegister(result);
1212 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) {
1213 LOperand* input = UseRegisterAtStart(instr->value());
1214 LMathPowHalf* result = new(zone()) LMathPowHalf(input);
1215 return DefineAsRegister(result);
1219 LInstruction* LChunkBuilder::DoNullarySIMDOperation(
1220 HNullarySIMDOperation* instr) {
1226 LInstruction* LChunkBuilder::DoUnarySIMDOperation(
1227 HUnarySIMDOperation* instr) {
1233 LInstruction* LChunkBuilder::DoBinarySIMDOperation(
1234 HBinarySIMDOperation* instr) {
1240 LInstruction* LChunkBuilder::DoTernarySIMDOperation(
1241 HTernarySIMDOperation* instr) {
1247 LInstruction* LChunkBuilder::DoQuarternarySIMDOperation(
1248 HQuarternarySIMDOperation* instr) {
1254 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1255 LOperand* context = UseFixed(instr->context(), cp);
1256 LOperand* constructor = UseFixed(instr->constructor(), r1);
1257 LCallNew* result = new(zone()) LCallNew(context, constructor);
1258 return MarkAsCall(DefineFixed(result, r0), instr);
1262 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1263 LOperand* context = UseFixed(instr->context(), cp);
1264 LOperand* constructor = UseFixed(instr->constructor(), r1);
1265 LCallNewArray* result = new(zone()) LCallNewArray(context, constructor);
1266 return MarkAsCall(DefineFixed(result, r0), instr);
1270 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1271 LOperand* context = UseFixed(instr->context(), cp);
1272 LOperand* function = UseFixed(instr->function(), r1);
1273 LCallFunction* call = new(zone()) LCallFunction(context, function);
1274 return MarkAsCall(DefineFixed(call, r0), instr);
1278 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1279 LOperand* context = UseFixed(instr->context(), cp);
1280 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), r0), instr);
1284 LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1285 return DoShift(Token::ROR, instr);
1289 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1290 return DoShift(Token::SHR, instr);
1294 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1295 return DoShift(Token::SAR, instr);
1299 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1300 return DoShift(Token::SHL, instr);
1304 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1305 if (instr->representation().IsSmiOrInteger32()) {
1306 DCHECK(instr->left()->representation().Equals(instr->representation()));
1307 DCHECK(instr->right()->representation().Equals(instr->representation()));
1308 DCHECK(instr->CheckFlag(HValue::kTruncatingToInt32));
1310 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1311 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1312 return DefineAsRegister(new(zone()) LBitI(left, right));
1314 return DoArithmeticT(instr->op(), instr);
1319 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) {
1320 DCHECK(instr->representation().IsSmiOrInteger32());
1321 DCHECK(instr->left()->representation().Equals(instr->representation()));
1322 DCHECK(instr->right()->representation().Equals(instr->representation()));
1323 LOperand* dividend = UseRegister(instr->left());
1324 int32_t divisor = instr->right()->GetInteger32Constant();
1325 LInstruction* result = DefineAsRegister(new(zone()) LDivByPowerOf2I(
1326 dividend, divisor));
1327 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1328 (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) ||
1329 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1330 divisor != 1 && divisor != -1)) {
1331 result = AssignEnvironment(result);
1337 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) {
1338 DCHECK(instr->representation().IsInteger32());
1339 DCHECK(instr->left()->representation().Equals(instr->representation()));
1340 DCHECK(instr->right()->representation().Equals(instr->representation()));
1341 LOperand* dividend = UseRegister(instr->left());
1342 int32_t divisor = instr->right()->GetInteger32Constant();
1343 LInstruction* result = DefineAsRegister(new(zone()) LDivByConstI(
1344 dividend, divisor));
1346 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1347 !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1348 result = AssignEnvironment(result);
1354 LInstruction* LChunkBuilder::DoDivI(HDiv* instr) {
1355 DCHECK(instr->representation().IsSmiOrInteger32());
1356 DCHECK(instr->left()->representation().Equals(instr->representation()));
1357 DCHECK(instr->right()->representation().Equals(instr->representation()));
1358 LOperand* dividend = UseRegister(instr->left());
1359 LOperand* divisor = UseRegister(instr->right());
1361 CpuFeatures::IsSupported(SUDIV) ? NULL : TempDoubleRegister();
1362 LInstruction* result =
1363 DefineAsRegister(new(zone()) LDivI(dividend, divisor, temp));
1364 if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1365 instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1366 (instr->CheckFlag(HValue::kCanOverflow) &&
1367 (!CpuFeatures::IsSupported(SUDIV) ||
1368 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) ||
1369 (!instr->IsMathFloorOfDiv() &&
1370 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
1371 result = AssignEnvironment(result);
1377 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1378 if (instr->representation().IsSmiOrInteger32()) {
1379 if (instr->RightIsPowerOf2()) {
1380 return DoDivByPowerOf2I(instr);
1381 } else if (instr->right()->IsConstant()) {
1382 return DoDivByConstI(instr);
1384 return DoDivI(instr);
1386 } else if (instr->representation().IsDouble()) {
1387 return DoArithmeticD(Token::DIV, instr);
1389 return DoArithmeticT(Token::DIV, instr);
1394 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
1395 LOperand* dividend = UseRegisterAtStart(instr->left());
1396 int32_t divisor = instr->right()->GetInteger32Constant();
1397 LInstruction* result = DefineAsRegister(new(zone()) LFlooringDivByPowerOf2I(
1398 dividend, divisor));
1399 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1400 (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) {
1401 result = AssignEnvironment(result);
1407 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
1408 DCHECK(instr->representation().IsInteger32());
1409 DCHECK(instr->left()->representation().Equals(instr->representation()));
1410 DCHECK(instr->right()->representation().Equals(instr->representation()));
1411 LOperand* dividend = UseRegister(instr->left());
1412 int32_t divisor = instr->right()->GetInteger32Constant();
1414 ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) ||
1415 (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) ?
1416 NULL : TempRegister();
1417 LInstruction* result = DefineAsRegister(
1418 new(zone()) LFlooringDivByConstI(dividend, divisor, temp));
1420 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) {
1421 result = AssignEnvironment(result);
1427 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) {
1428 DCHECK(instr->representation().IsSmiOrInteger32());
1429 DCHECK(instr->left()->representation().Equals(instr->representation()));
1430 DCHECK(instr->right()->representation().Equals(instr->representation()));
1431 LOperand* dividend = UseRegister(instr->left());
1432 LOperand* divisor = UseRegister(instr->right());
1434 CpuFeatures::IsSupported(SUDIV) ? NULL : TempDoubleRegister();
1435 LFlooringDivI* div = new(zone()) LFlooringDivI(dividend, divisor, temp);
1436 return AssignEnvironment(DefineAsRegister(div));
1440 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1441 if (instr->RightIsPowerOf2()) {
1442 return DoFlooringDivByPowerOf2I(instr);
1443 } else if (instr->right()->IsConstant()) {
1444 return DoFlooringDivByConstI(instr);
1446 return DoFlooringDivI(instr);
1451 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
1452 DCHECK(instr->representation().IsSmiOrInteger32());
1453 DCHECK(instr->left()->representation().Equals(instr->representation()));
1454 DCHECK(instr->right()->representation().Equals(instr->representation()));
1455 LOperand* dividend = UseRegisterAtStart(instr->left());
1456 int32_t divisor = instr->right()->GetInteger32Constant();
1457 LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I(
1458 dividend, divisor));
1459 if (instr->CheckFlag(HValue::kLeftCanBeNegative) &&
1460 instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1461 result = AssignEnvironment(result);
1467 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) {
1468 DCHECK(instr->representation().IsSmiOrInteger32());
1469 DCHECK(instr->left()->representation().Equals(instr->representation()));
1470 DCHECK(instr->right()->representation().Equals(instr->representation()));
1471 LOperand* dividend = UseRegister(instr->left());
1472 int32_t divisor = instr->right()->GetInteger32Constant();
1473 LInstruction* result = DefineAsRegister(new(zone()) LModByConstI(
1474 dividend, divisor));
1475 if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1476 result = AssignEnvironment(result);
1482 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
1483 DCHECK(instr->representation().IsSmiOrInteger32());
1484 DCHECK(instr->left()->representation().Equals(instr->representation()));
1485 DCHECK(instr->right()->representation().Equals(instr->representation()));
1486 LOperand* dividend = UseRegister(instr->left());
1487 LOperand* divisor = UseRegister(instr->right());
1489 CpuFeatures::IsSupported(SUDIV) ? NULL : TempDoubleRegister();
1491 CpuFeatures::IsSupported(SUDIV) ? NULL : TempDoubleRegister();
1492 LInstruction* result = DefineAsRegister(new(zone()) LModI(
1493 dividend, divisor, temp, temp2));
1494 if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1495 instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1496 result = AssignEnvironment(result);
1502 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1503 if (instr->representation().IsSmiOrInteger32()) {
1504 if (instr->RightIsPowerOf2()) {
1505 return DoModByPowerOf2I(instr);
1506 } else if (instr->right()->IsConstant()) {
1507 return DoModByConstI(instr);
1509 return DoModI(instr);
1511 } else if (instr->representation().IsDouble()) {
1512 return DoArithmeticD(Token::MOD, instr);
1514 return DoArithmeticT(Token::MOD, instr);
1519 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1520 if (instr->representation().IsSmiOrInteger32()) {
1521 DCHECK(instr->left()->representation().Equals(instr->representation()));
1522 DCHECK(instr->right()->representation().Equals(instr->representation()));
1523 HValue* left = instr->BetterLeftOperand();
1524 HValue* right = instr->BetterRightOperand();
1527 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
1528 bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero);
1530 if (right->IsConstant()) {
1531 HConstant* constant = HConstant::cast(right);
1532 int32_t constant_value = constant->Integer32Value();
1533 // Constants -1, 0 and 1 can be optimized if the result can overflow.
1534 // For other constants, it can be optimized only without overflow.
1535 if (!can_overflow || ((constant_value >= -1) && (constant_value <= 1))) {
1536 left_op = UseRegisterAtStart(left);
1537 right_op = UseConstant(right);
1539 if (bailout_on_minus_zero) {
1540 left_op = UseRegister(left);
1542 left_op = UseRegisterAtStart(left);
1544 right_op = UseRegister(right);
1547 if (bailout_on_minus_zero) {
1548 left_op = UseRegister(left);
1550 left_op = UseRegisterAtStart(left);
1552 right_op = UseRegister(right);
1554 LMulI* mul = new(zone()) LMulI(left_op, right_op);
1555 if (can_overflow || bailout_on_minus_zero) {
1556 AssignEnvironment(mul);
1558 return DefineAsRegister(mul);
1560 } else if (instr->representation().IsDouble()) {
1561 if (instr->HasOneUse() && (instr->uses().value()->IsAdd() ||
1562 instr->uses().value()->IsSub())) {
1563 HBinaryOperation* use = HBinaryOperation::cast(instr->uses().value());
1565 if (use->IsAdd() && instr == use->left()) {
1566 // This mul is the lhs of an add. The add and mul will be folded into a
1567 // multiply-add in DoAdd.
1570 if (instr == use->right() && use->IsAdd() && !use->left()->IsMul()) {
1571 // This mul is the rhs of an add, where the lhs is not another mul.
1572 // The add and mul will be folded into a multiply-add in DoAdd.
1575 if (instr == use->right() && use->IsSub()) {
1576 // This mul is the rhs of a sub. The sub and mul will be folded into a
1577 // multiply-sub in DoSub.
1582 return DoArithmeticD(Token::MUL, instr);
1584 return DoArithmeticT(Token::MUL, instr);
1589 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1590 if (instr->representation().IsSmiOrInteger32()) {
1591 DCHECK(instr->left()->representation().Equals(instr->representation()));
1592 DCHECK(instr->right()->representation().Equals(instr->representation()));
1594 if (instr->left()->IsConstant()) {
1595 // If lhs is constant, do reverse subtraction instead.
1596 return DoRSub(instr);
1599 LOperand* left = UseRegisterAtStart(instr->left());
1600 LOperand* right = UseOrConstantAtStart(instr->right());
1601 LSubI* sub = new(zone()) LSubI(left, right);
1602 LInstruction* result = DefineAsRegister(sub);
1603 if (instr->CheckFlag(HValue::kCanOverflow)) {
1604 result = AssignEnvironment(result);
1607 } else if (instr->representation().IsDouble()) {
1608 if (instr->right()->IsMul() && instr->right()->HasOneUse()) {
1609 return DoMultiplySub(instr->left(), HMul::cast(instr->right()));
1612 return DoArithmeticD(Token::SUB, instr);
1614 return DoArithmeticT(Token::SUB, instr);
1619 LInstruction* LChunkBuilder::DoRSub(HSub* instr) {
1620 DCHECK(instr->representation().IsSmiOrInteger32());
1621 DCHECK(instr->left()->representation().Equals(instr->representation()));
1622 DCHECK(instr->right()->representation().Equals(instr->representation()));
1624 // Note: The lhs of the subtraction becomes the rhs of the
1625 // reverse-subtraction.
1626 LOperand* left = UseRegisterAtStart(instr->right());
1627 LOperand* right = UseOrConstantAtStart(instr->left());
1628 LRSubI* rsb = new(zone()) LRSubI(left, right);
1629 LInstruction* result = DefineAsRegister(rsb);
1630 if (instr->CheckFlag(HValue::kCanOverflow)) {
1631 result = AssignEnvironment(result);
1637 LInstruction* LChunkBuilder::DoMultiplyAdd(HMul* mul, HValue* addend) {
1638 LOperand* multiplier_op = UseRegisterAtStart(mul->left());
1639 LOperand* multiplicand_op = UseRegisterAtStart(mul->right());
1640 LOperand* addend_op = UseRegisterAtStart(addend);
1641 return DefineSameAsFirst(new(zone()) LMultiplyAddD(addend_op, multiplier_op,
1646 LInstruction* LChunkBuilder::DoMultiplySub(HValue* minuend, HMul* mul) {
1647 LOperand* minuend_op = UseRegisterAtStart(minuend);
1648 LOperand* multiplier_op = UseRegisterAtStart(mul->left());
1649 LOperand* multiplicand_op = UseRegisterAtStart(mul->right());
1651 return DefineSameAsFirst(new(zone()) LMultiplySubD(minuend_op,
1657 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1658 if (instr->representation().IsSmiOrInteger32()) {
1659 DCHECK(instr->left()->representation().Equals(instr->representation()));
1660 DCHECK(instr->right()->representation().Equals(instr->representation()));
1661 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1662 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1663 LAddI* add = new(zone()) LAddI(left, right);
1664 LInstruction* result = DefineAsRegister(add);
1665 if (instr->CheckFlag(HValue::kCanOverflow)) {
1666 result = AssignEnvironment(result);
1669 } else if (instr->representation().IsExternal()) {
1670 DCHECK(instr->left()->representation().IsExternal());
1671 DCHECK(instr->right()->representation().IsInteger32());
1672 DCHECK(!instr->CheckFlag(HValue::kCanOverflow));
1673 LOperand* left = UseRegisterAtStart(instr->left());
1674 LOperand* right = UseOrConstantAtStart(instr->right());
1675 LAddI* add = new(zone()) LAddI(left, right);
1676 LInstruction* result = DefineAsRegister(add);
1678 } else if (instr->representation().IsDouble()) {
1679 if (instr->left()->IsMul() && instr->left()->HasOneUse()) {
1680 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right());
1683 if (instr->right()->IsMul() && instr->right()->HasOneUse()) {
1684 DCHECK(!instr->left()->IsMul() || !instr->left()->HasOneUse());
1685 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left());
1688 return DoArithmeticD(Token::ADD, instr);
1690 return DoArithmeticT(Token::ADD, instr);
1695 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1696 LOperand* left = NULL;
1697 LOperand* right = NULL;
1698 if (instr->representation().IsSmiOrInteger32()) {
1699 DCHECK(instr->left()->representation().Equals(instr->representation()));
1700 DCHECK(instr->right()->representation().Equals(instr->representation()));
1701 left = UseRegisterAtStart(instr->BetterLeftOperand());
1702 right = UseOrConstantAtStart(instr->BetterRightOperand());
1704 DCHECK(instr->representation().IsDouble());
1705 DCHECK(instr->left()->representation().IsDouble());
1706 DCHECK(instr->right()->representation().IsDouble());
1707 left = UseRegisterAtStart(instr->left());
1708 right = UseRegisterAtStart(instr->right());
1710 return DefineAsRegister(new(zone()) LMathMinMax(left, right));
1714 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1715 DCHECK(instr->representation().IsDouble());
1716 // We call a C function for double power. It can't trigger a GC.
1717 // We need to use fixed result register for the call.
1718 Representation exponent_type = instr->right()->representation();
1719 DCHECK(instr->left()->representation().IsDouble());
1720 LOperand* left = UseFixedDouble(instr->left(), d0);
1722 exponent_type.IsDouble()
1723 ? UseFixedDouble(instr->right(), d1)
1724 : UseFixed(instr->right(), MathPowTaggedDescriptor::exponent());
1725 LPower* result = new(zone()) LPower(left, right);
1726 return MarkAsCall(DefineFixedDouble(result, d2),
1728 CAN_DEOPTIMIZE_EAGERLY);
1732 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1733 DCHECK(instr->left()->representation().IsTagged());
1734 DCHECK(instr->right()->representation().IsTagged());
1735 LOperand* context = UseFixed(instr->context(), cp);
1736 LOperand* left = UseFixed(instr->left(), r1);
1737 LOperand* right = UseFixed(instr->right(), r0);
1738 LCmpT* result = new(zone()) LCmpT(context, left, right);
1739 return MarkAsCall(DefineFixed(result, r0), instr);
1743 LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
1744 HCompareNumericAndBranch* instr) {
1745 Representation r = instr->representation();
1746 if (r.IsSmiOrInteger32()) {
1747 DCHECK(instr->left()->representation().Equals(r));
1748 DCHECK(instr->right()->representation().Equals(r));
1749 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1750 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
1751 return new(zone()) LCompareNumericAndBranch(left, right);
1753 DCHECK(r.IsDouble());
1754 DCHECK(instr->left()->representation().IsDouble());
1755 DCHECK(instr->right()->representation().IsDouble());
1756 LOperand* left = UseRegisterAtStart(instr->left());
1757 LOperand* right = UseRegisterAtStart(instr->right());
1758 return new(zone()) LCompareNumericAndBranch(left, right);
1763 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1764 HCompareObjectEqAndBranch* instr) {
1765 LOperand* left = UseRegisterAtStart(instr->left());
1766 LOperand* right = UseRegisterAtStart(instr->right());
1767 return new(zone()) LCmpObjectEqAndBranch(left, right);
1771 LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1772 HCompareHoleAndBranch* instr) {
1773 LOperand* value = UseRegisterAtStart(instr->value());
1774 return new(zone()) LCmpHoleAndBranch(value);
1778 LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
1779 HCompareMinusZeroAndBranch* instr) {
1780 LOperand* value = UseRegister(instr->value());
1781 LOperand* scratch = TempRegister();
1782 return new(zone()) LCompareMinusZeroAndBranch(value, scratch);
1786 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1787 DCHECK(instr->value()->representation().IsTagged());
1788 LOperand* value = UseRegisterAtStart(instr->value());
1789 LOperand* temp = TempRegister();
1790 return new(zone()) LIsObjectAndBranch(value, temp);
1794 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1795 DCHECK(instr->value()->representation().IsTagged());
1796 LOperand* value = UseRegisterAtStart(instr->value());
1797 LOperand* temp = TempRegister();
1798 return new(zone()) LIsStringAndBranch(value, temp);
1802 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1803 DCHECK(instr->value()->representation().IsTagged());
1804 return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1808 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1809 HIsUndetectableAndBranch* instr) {
1810 DCHECK(instr->value()->representation().IsTagged());
1811 LOperand* value = UseRegisterAtStart(instr->value());
1812 return new(zone()) LIsUndetectableAndBranch(value, TempRegister());
1816 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1817 HStringCompareAndBranch* instr) {
1818 DCHECK(instr->left()->representation().IsTagged());
1819 DCHECK(instr->right()->representation().IsTagged());
1820 LOperand* context = UseFixed(instr->context(), cp);
1821 LOperand* left = UseFixed(instr->left(), r1);
1822 LOperand* right = UseFixed(instr->right(), r0);
1823 LStringCompareAndBranch* result =
1824 new(zone()) LStringCompareAndBranch(context, left, right);
1825 return MarkAsCall(result, instr);
1829 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1830 HHasInstanceTypeAndBranch* instr) {
1831 DCHECK(instr->value()->representation().IsTagged());
1832 LOperand* value = UseRegisterAtStart(instr->value());
1833 return new(zone()) LHasInstanceTypeAndBranch(value);
1837 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1838 HGetCachedArrayIndex* instr) {
1839 DCHECK(instr->value()->representation().IsTagged());
1840 LOperand* value = UseRegisterAtStart(instr->value());
1842 return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
1846 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1847 HHasCachedArrayIndexAndBranch* instr) {
1848 DCHECK(instr->value()->representation().IsTagged());
1849 return new(zone()) LHasCachedArrayIndexAndBranch(
1850 UseRegisterAtStart(instr->value()));
1854 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1855 HClassOfTestAndBranch* instr) {
1856 DCHECK(instr->value()->representation().IsTagged());
1857 LOperand* value = UseRegister(instr->value());
1858 return new(zone()) LClassOfTestAndBranch(value, TempRegister());
1862 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1863 LOperand* map = UseRegisterAtStart(instr->value());
1864 return DefineAsRegister(new(zone()) LMapEnumLength(map));
1868 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1869 LOperand* object = UseFixed(instr->value(), r0);
1870 LDateField* result =
1871 new(zone()) LDateField(object, FixedTemp(r1), instr->index());
1872 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
1876 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
1877 LOperand* string = UseRegisterAtStart(instr->string());
1878 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1879 return DefineAsRegister(new(zone()) LSeqStringGetChar(string, index));
1883 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1884 LOperand* string = UseRegisterAtStart(instr->string());
1885 LOperand* index = FLAG_debug_code
1886 ? UseRegisterAtStart(instr->index())
1887 : UseRegisterOrConstantAtStart(instr->index());
1888 LOperand* value = UseRegisterAtStart(instr->value());
1889 LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), cp) : NULL;
1890 return new(zone()) LSeqStringSetChar(context, string, index, value);
1894 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1895 if (!FLAG_debug_code && instr->skip_check()) return NULL;
1896 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1897 LOperand* length = !index->IsConstantOperand()
1898 ? UseRegisterOrConstantAtStart(instr->length())
1899 : UseRegisterAtStart(instr->length());
1900 LInstruction* result = new(zone()) LBoundsCheck(index, length);
1901 if (!FLAG_debug_code || !instr->skip_check()) {
1902 result = AssignEnvironment(result);
1908 LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
1909 HBoundsCheckBaseIndexInformation* instr) {
1915 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1916 // The control instruction marking the end of a block that completed
1917 // abruptly (e.g., threw an exception). There is nothing specific to do.
1922 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1927 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1928 // All HForceRepresentation instructions should be eliminated in the
1929 // representation change phase of Hydrogen.
1935 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1936 Representation from = instr->from();
1937 Representation to = instr->to();
1938 HValue* val = instr->value();
1940 if (to.IsTagged()) {
1941 LOperand* value = UseRegister(val);
1942 return DefineSameAsFirst(new(zone()) LDummyUse(value));
1944 from = Representation::Tagged();
1946 if (from.IsTagged()) {
1947 if (to.IsDouble()) {
1948 LOperand* value = UseRegister(val);
1949 LInstruction* result = DefineAsRegister(new(zone()) LNumberUntagD(value));
1950 if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1952 } else if (to.IsSmi()) {
1953 LOperand* value = UseRegister(val);
1954 if (val->type().IsSmi()) {
1955 return DefineSameAsFirst(new(zone()) LDummyUse(value));
1957 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value)));
1959 DCHECK(to.IsInteger32());
1960 if (val->type().IsSmi() || val->representation().IsSmi()) {
1961 LOperand* value = UseRegisterAtStart(val);
1962 return DefineAsRegister(new(zone()) LSmiUntag(value, false));
1964 LOperand* value = UseRegister(val);
1965 LOperand* temp1 = TempRegister();
1966 LOperand* temp2 = TempDoubleRegister();
1967 LInstruction* result =
1968 DefineSameAsFirst(new(zone()) LTaggedToI(value, temp1, temp2));
1969 if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1973 } else if (from.IsDouble()) {
1974 if (to.IsTagged()) {
1975 info()->MarkAsDeferredCalling();
1976 LOperand* value = UseRegister(val);
1977 LOperand* temp1 = TempRegister();
1978 LOperand* temp2 = TempRegister();
1979 LUnallocated* result_temp = TempRegister();
1980 LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2);
1981 return AssignPointerMap(Define(result, result_temp));
1982 } else if (to.IsSmi()) {
1983 LOperand* value = UseRegister(val);
1984 return AssignEnvironment(
1985 DefineAsRegister(new(zone()) LDoubleToSmi(value)));
1987 DCHECK(to.IsInteger32());
1988 LOperand* value = UseRegister(val);
1989 LInstruction* result = DefineAsRegister(new(zone()) LDoubleToI(value));
1990 if (!instr->CanTruncateToInt32()) result = AssignEnvironment(result);
1993 } else if (from.IsInteger32()) {
1994 info()->MarkAsDeferredCalling();
1995 if (to.IsTagged()) {
1996 if (!instr->CheckFlag(HValue::kCanOverflow)) {
1997 LOperand* value = UseRegisterAtStart(val);
1998 return DefineAsRegister(new(zone()) LSmiTag(value));
1999 } else if (val->CheckFlag(HInstruction::kUint32)) {
2000 LOperand* value = UseRegisterAtStart(val);
2001 LOperand* temp1 = TempRegister();
2002 LOperand* temp2 = TempRegister();
2003 LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2);
2004 return AssignPointerMap(DefineAsRegister(result));
2006 LOperand* value = UseRegisterAtStart(val);
2007 LOperand* temp1 = TempRegister();
2008 LOperand* temp2 = TempRegister();
2009 LNumberTagI* result = new(zone()) LNumberTagI(value, temp1, temp2);
2010 return AssignPointerMap(DefineAsRegister(result));
2012 } else if (to.IsSmi()) {
2013 LOperand* value = UseRegister(val);
2014 LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value));
2015 if (instr->CheckFlag(HValue::kCanOverflow)) {
2016 result = AssignEnvironment(result);
2020 DCHECK(to.IsDouble());
2021 if (val->CheckFlag(HInstruction::kUint32)) {
2022 return DefineAsRegister(new(zone()) LUint32ToDouble(UseRegister(val)));
2024 return DefineAsRegister(new(zone()) LInteger32ToDouble(Use(val)));
2033 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
2034 LOperand* value = UseRegisterAtStart(instr->value());
2035 LInstruction* result = new(zone()) LCheckNonSmi(value);
2036 if (!instr->value()->type().IsHeapObject()) {
2037 result = AssignEnvironment(result);
2043 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
2044 LOperand* value = UseRegisterAtStart(instr->value());
2045 return AssignEnvironment(new(zone()) LCheckSmi(value));
2049 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
2050 LOperand* value = UseRegisterAtStart(instr->value());
2051 LInstruction* result = new(zone()) LCheckInstanceType(value);
2052 return AssignEnvironment(result);
2056 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
2057 LOperand* value = UseRegisterAtStart(instr->value());
2058 return AssignEnvironment(new(zone()) LCheckValue(value));
2062 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
2063 if (instr->IsStabilityCheck()) return new(zone()) LCheckMaps;
2064 LOperand* value = UseRegisterAtStart(instr->value());
2065 LInstruction* result = AssignEnvironment(new(zone()) LCheckMaps(value));
2066 if (instr->HasMigrationTarget()) {
2067 info()->MarkAsDeferredCalling();
2068 result = AssignPointerMap(result);
2074 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
2075 HValue* value = instr->value();
2076 Representation input_rep = value->representation();
2077 LOperand* reg = UseRegister(value);
2078 if (input_rep.IsDouble()) {
2079 return DefineAsRegister(new(zone()) LClampDToUint8(reg));
2080 } else if (input_rep.IsInteger32()) {
2081 return DefineAsRegister(new(zone()) LClampIToUint8(reg));
2083 DCHECK(input_rep.IsSmiOrTagged());
2084 // Register allocator doesn't (yet) support allocation of double
2085 // temps. Reserve d1 explicitly.
2086 LClampTToUint8* result =
2087 new(zone()) LClampTToUint8(reg, TempDoubleRegister());
2088 return AssignEnvironment(DefineAsRegister(result));
2093 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) {
2094 HValue* value = instr->value();
2095 DCHECK(value->representation().IsDouble());
2096 return DefineAsRegister(new(zone()) LDoubleBits(UseRegister(value)));
2100 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
2101 LOperand* lo = UseRegister(instr->lo());
2102 LOperand* hi = UseRegister(instr->hi());
2103 return DefineAsRegister(new(zone()) LConstructDouble(hi, lo));
2107 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
2108 LOperand* context = info()->IsStub()
2109 ? UseFixed(instr->context(), cp)
2111 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
2112 return new(zone()) LReturn(UseFixed(instr->value(), r0), context,
2117 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
2118 Representation r = instr->representation();
2120 return DefineAsRegister(new(zone()) LConstantS);
2121 } else if (r.IsInteger32()) {
2122 return DefineAsRegister(new(zone()) LConstantI);
2123 } else if (r.IsDouble()) {
2124 return DefineAsRegister(new(zone()) LConstantD);
2125 } else if (r.IsExternal()) {
2126 return DefineAsRegister(new(zone()) LConstantE);
2127 } else if (r.IsTagged()) {
2128 return DefineAsRegister(new(zone()) LConstantT);
2136 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
2137 LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
2138 return instr->RequiresHoleCheck()
2139 ? AssignEnvironment(DefineAsRegister(result))
2140 : DefineAsRegister(result);
2144 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
2145 LOperand* context = UseFixed(instr->context(), cp);
2146 LOperand* global_object =
2147 UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister());
2148 LOperand* vector = NULL;
2149 if (FLAG_vector_ics) {
2150 vector = FixedTemp(VectorLoadICDescriptor::VectorRegister());
2152 LLoadGlobalGeneric* result =
2153 new(zone()) LLoadGlobalGeneric(context, global_object, vector);
2154 return MarkAsCall(DefineFixed(result, r0), instr);
2158 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
2159 LOperand* value = UseRegister(instr->value());
2160 // Use a temp to check the value in the cell in the case where we perform
2162 return instr->RequiresHoleCheck()
2163 ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister()))
2164 : new(zone()) LStoreGlobalCell(value, NULL);
2168 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
2169 LOperand* context = UseRegisterAtStart(instr->value());
2170 LInstruction* result =
2171 DefineAsRegister(new(zone()) LLoadContextSlot(context));
2172 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
2173 result = AssignEnvironment(result);
2179 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
2182 if (instr->NeedsWriteBarrier()) {
2183 context = UseTempRegister(instr->context());
2184 value = UseTempRegister(instr->value());
2186 context = UseRegister(instr->context());
2187 value = UseRegister(instr->value());
2189 LInstruction* result = new(zone()) LStoreContextSlot(context, value);
2190 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
2191 result = AssignEnvironment(result);
2197 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
2198 LOperand* obj = UseRegisterAtStart(instr->object());
2199 return DefineAsRegister(new(zone()) LLoadNamedField(obj));
2203 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
2204 LOperand* context = UseFixed(instr->context(), cp);
2206 UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
2207 LOperand* vector = NULL;
2208 if (FLAG_vector_ics) {
2209 vector = FixedTemp(VectorLoadICDescriptor::VectorRegister());
2212 LInstruction* result =
2213 DefineFixed(new(zone()) LLoadNamedGeneric(context, object, vector), r0);
2214 return MarkAsCall(result, instr);
2218 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
2219 HLoadFunctionPrototype* instr) {
2220 return AssignEnvironment(DefineAsRegister(
2221 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
2225 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
2226 return DefineAsRegister(new(zone()) LLoadRoot);
2230 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
2231 DCHECK(instr->key()->representation().IsSmiOrInteger32());
2232 ElementsKind elements_kind = instr->elements_kind();
2233 bool load_128bits_without_neon = IsSIMD128ElementsKind(elements_kind);
2234 LOperand* key = load_128bits_without_neon
2235 ? UseRegisterOrConstant(instr->key())
2236 : UseRegisterOrConstantAtStart(instr->key());
2237 LInstruction* result = NULL;
2239 if (!instr->is_typed_elements()) {
2240 LOperand* obj = NULL;
2241 if (instr->representation().IsDouble()) {
2242 obj = UseRegister(instr->elements());
2244 DCHECK(instr->representation().IsSmiOrTagged());
2245 obj = UseRegisterAtStart(instr->elements());
2247 result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key, NULL, NULL));
2250 (instr->representation().IsInteger32() &&
2251 !IsDoubleOrFloatElementsKind(elements_kind)) ||
2252 (instr->representation().IsDouble() &&
2253 IsDoubleOrFloatElementsKind(elements_kind)) ||
2254 (instr->representation().IsTagged() &&
2255 (IsSIMD128ElementsKind(elements_kind))));
2256 LOperand* backing_store = UseRegister(instr->elements());
2257 result = load_128bits_without_neon
2258 ? DefineAsRegister(new(zone()) LLoadKeyed(
2259 backing_store, key, TempRegister(), TempRegister()))
2260 : DefineAsRegister(new(zone()) LLoadKeyed(
2261 backing_store, key, NULL, NULL));
2262 if (load_128bits_without_neon) {
2263 info()->MarkAsDeferredCalling();
2264 AssignPointerMap(result);
2268 if ((instr->is_external() || instr->is_fixed_typed_array()) ?
2269 // see LCodeGen::DoLoadKeyedExternalArray
2270 ((elements_kind == EXTERNAL_UINT32_ELEMENTS ||
2271 elements_kind == UINT32_ELEMENTS) &&
2272 !instr->CheckFlag(HInstruction::kUint32)) :
2273 // see LCodeGen::DoLoadKeyedFixedDoubleArray and
2274 // LCodeGen::DoLoadKeyedFixedArray
2275 instr->RequiresHoleCheck()) {
2276 result = AssignEnvironment(result);
2282 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
2283 LOperand* context = UseFixed(instr->context(), cp);
2285 UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
2286 LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister());
2287 LOperand* vector = NULL;
2288 if (FLAG_vector_ics) {
2289 vector = FixedTemp(VectorLoadICDescriptor::VectorRegister());
2292 LInstruction* result =
2293 DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key, vector),
2295 return MarkAsCall(result, instr);
2299 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
2300 if (!instr->is_typed_elements()) {
2301 DCHECK(instr->elements()->representation().IsTagged());
2302 bool needs_write_barrier = instr->NeedsWriteBarrier();
2303 LOperand* object = NULL;
2304 LOperand* key = NULL;
2305 LOperand* val = NULL;
2307 if (instr->value()->representation().IsDouble()) {
2308 object = UseRegisterAtStart(instr->elements());
2309 val = UseRegister(instr->value());
2310 key = UseRegisterOrConstantAtStart(instr->key());
2312 DCHECK(instr->value()->representation().IsSmiOrTagged());
2313 if (needs_write_barrier) {
2314 object = UseTempRegister(instr->elements());
2315 val = UseTempRegister(instr->value());
2316 key = UseTempRegister(instr->key());
2318 object = UseRegisterAtStart(instr->elements());
2319 val = UseRegisterAtStart(instr->value());
2320 key = UseRegisterOrConstantAtStart(instr->key());
2324 return new(zone()) LStoreKeyed(object, key, val, NULL, NULL);
2328 (instr->value()->representation().IsInteger32() &&
2329 !IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
2330 (instr->value()->representation().IsDouble() &&
2331 IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
2332 (instr->value()->representation().IsTagged() &&
2333 IsSIMD128ElementsKind(instr->elements_kind())));
2334 DCHECK((instr->is_fixed_typed_array() &&
2335 instr->elements()->representation().IsTagged()) ||
2336 (instr->is_external() &&
2337 instr->elements()->representation().IsExternal()));
2338 LOperand* val = UseRegister(instr->value());
2339 LOperand* backing_store = UseRegister(instr->elements());
2340 bool store_128bits_without_neon =
2341 IsSIMD128ElementsKind(instr->elements_kind());
2342 LOperand* key = store_128bits_without_neon
2343 ? UseRegisterOrConstant(instr->key())
2344 : UseRegisterOrConstantAtStart(instr->key());
2345 LStoreKeyed* result =
2346 new(zone()) LStoreKeyed(backing_store, key, val,
2347 store_128bits_without_neon ? TempRegister() : NULL,
2348 store_128bits_without_neon ? TempRegister() : NULL);
2349 return store_128bits_without_neon ? AssignEnvironment(result) : result;
2353 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
2354 LOperand* context = UseFixed(instr->context(), cp);
2356 UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
2357 LOperand* key = UseFixed(instr->key(), StoreDescriptor::NameRegister());
2358 LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
2360 DCHECK(instr->object()->representation().IsTagged());
2361 DCHECK(instr->key()->representation().IsTagged());
2362 DCHECK(instr->value()->representation().IsTagged());
2365 new(zone()) LStoreKeyedGeneric(context, obj, key, val), instr);
2369 LInstruction* LChunkBuilder::DoTransitionElementsKind(
2370 HTransitionElementsKind* instr) {
2371 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
2372 LOperand* object = UseRegister(instr->object());
2373 LOperand* new_map_reg = TempRegister();
2374 LTransitionElementsKind* result =
2375 new(zone()) LTransitionElementsKind(object, NULL, new_map_reg);
2378 LOperand* object = UseFixed(instr->object(), r0);
2379 LOperand* context = UseFixed(instr->context(), cp);
2380 LTransitionElementsKind* result =
2381 new(zone()) LTransitionElementsKind(object, context, NULL);
2382 return MarkAsCall(result, instr);
2387 LInstruction* LChunkBuilder::DoTrapAllocationMemento(
2388 HTrapAllocationMemento* instr) {
2389 LOperand* object = UseRegister(instr->object());
2390 LOperand* temp = TempRegister();
2391 LTrapAllocationMemento* result =
2392 new(zone()) LTrapAllocationMemento(object, temp);
2393 return AssignEnvironment(result);
2397 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2398 bool is_in_object = instr->access().IsInobject();
2399 bool needs_write_barrier = instr->NeedsWriteBarrier();
2400 bool needs_write_barrier_for_map = instr->has_transition() &&
2401 instr->NeedsWriteBarrierForMap();
2404 if (needs_write_barrier) {
2406 ? UseRegister(instr->object())
2407 : UseTempRegister(instr->object());
2409 obj = needs_write_barrier_for_map
2410 ? UseRegister(instr->object())
2411 : UseRegisterAtStart(instr->object());
2415 if (needs_write_barrier) {
2416 val = UseTempRegister(instr->value());
2417 } else if (instr->field_representation().IsDouble()) {
2418 val = UseRegisterAtStart(instr->value());
2420 val = UseRegister(instr->value());
2423 // We need a temporary register for write barrier of the map field.
2424 LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
2426 return new(zone()) LStoreNamedField(obj, val, temp);
2430 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2431 LOperand* context = UseFixed(instr->context(), cp);
2433 UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
2434 LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
2436 LInstruction* result = new(zone()) LStoreNamedGeneric(context, obj, val);
2437 return MarkAsCall(result, instr);
2441 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2442 LOperand* context = UseFixed(instr->context(), cp);
2443 LOperand* left = UseFixed(instr->left(), r1);
2444 LOperand* right = UseFixed(instr->right(), r0);
2446 DefineFixed(new(zone()) LStringAdd(context, left, right), r0),
2451 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2452 LOperand* string = UseTempRegister(instr->string());
2453 LOperand* index = UseTempRegister(instr->index());
2454 LOperand* context = UseAny(instr->context());
2455 LStringCharCodeAt* result =
2456 new(zone()) LStringCharCodeAt(context, string, index);
2457 return AssignPointerMap(DefineAsRegister(result));
2461 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2462 LOperand* char_code = UseRegister(instr->value());
2463 LOperand* context = UseAny(instr->context());
2464 LStringCharFromCode* result =
2465 new(zone()) LStringCharFromCode(context, char_code);
2466 return AssignPointerMap(DefineAsRegister(result));
2470 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
2471 info()->MarkAsDeferredCalling();
2472 LOperand* context = UseAny(instr->context());
2473 LOperand* size = UseRegisterOrConstant(instr->size());
2474 LOperand* temp1 = TempRegister();
2475 LOperand* temp2 = TempRegister();
2476 LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2);
2477 return AssignPointerMap(DefineAsRegister(result));
2481 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2482 LOperand* context = UseFixed(instr->context(), cp);
2484 DefineFixed(new(zone()) LRegExpLiteral(context), r0), instr);
2488 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2489 LOperand* context = UseFixed(instr->context(), cp);
2491 DefineFixed(new(zone()) LFunctionLiteral(context), r0), 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) {
2520 // Use an index that corresponds to the location in the unoptimized frame,
2521 // which the optimized frame will subsume.
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();
2528 if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
2529 Retry(kTooManySpillSlotsNeededForOSR);
2533 return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
2537 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2538 LOperand* context = UseFixed(instr->context(), cp);
2539 return MarkAsCall(DefineFixed(new(zone()) LCallStub(context), r0), instr);
2543 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2544 // There are no real uses of the arguments object.
2545 // arguments.length and element access are supported directly on
2546 // stack arguments, and any real arguments object use causes a bailout.
2547 // So this value is never used.
2552 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
2553 instr->ReplayEnvironment(current_block_->last_environment());
2555 // There are no real uses of a captured object.
2560 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2561 info()->MarkAsRequiresFrame();
2562 LOperand* args = UseRegister(instr->arguments());
2563 LOperand* length = UseRegisterOrConstantAtStart(instr->length());
2564 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
2565 return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
2569 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2570 LOperand* object = UseFixed(instr->value(), r0);
2571 LToFastProperties* result = new(zone()) LToFastProperties(object);
2572 return MarkAsCall(DefineFixed(result, r0), instr);
2576 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2577 LOperand* context = UseFixed(instr->context(), cp);
2578 LTypeof* result = new(zone()) LTypeof(context, UseFixed(instr->value(), r0));
2579 return MarkAsCall(DefineFixed(result, r0), instr);
2583 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2584 return new(zone()) LTypeofIsAndBranch(UseRegister(instr->value()));
2588 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2589 HIsConstructCallAndBranch* instr) {
2590 return new(zone()) LIsConstructCallAndBranch(TempRegister());
2594 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2595 instr->ReplayEnvironment(current_block_->last_environment());
2600 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2601 if (instr->is_function_entry()) {
2602 LOperand* context = UseFixed(instr->context(), cp);
2603 return MarkAsCall(new(zone()) LStackCheck(context), instr);
2605 DCHECK(instr->is_backwards_branch());
2606 LOperand* context = UseAny(instr->context());
2607 return AssignEnvironment(
2608 AssignPointerMap(new(zone()) LStackCheck(context)));
2613 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2614 HEnvironment* outer = current_block_->last_environment();
2615 outer->set_ast_id(instr->ReturnId());
2616 HConstant* undefined = graph()->GetConstantUndefined();
2617 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2618 instr->arguments_count(),
2621 instr->inlining_kind());
2622 // Only replay binding of arguments object if it wasn't removed from graph.
2623 if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
2624 inner->Bind(instr->arguments_var(), instr->arguments_object());
2626 inner->BindContext(instr->closure_context());
2627 inner->set_entry(instr);
2628 current_block_->UpdateEnvironment(inner);
2629 chunk_->AddInlinedClosure(instr->closure());
2634 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2635 LInstruction* pop = NULL;
2637 HEnvironment* env = current_block_->last_environment();
2639 if (env->entry()->arguments_pushed()) {
2640 int argument_count = env->arguments_environment()->parameter_count();
2641 pop = new(zone()) LDrop(argument_count);
2642 DCHECK(instr->argument_delta() == -argument_count);
2645 HEnvironment* outer = current_block_->last_environment()->
2646 DiscardInlined(false);
2647 current_block_->UpdateEnvironment(outer);
2653 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2654 LOperand* context = UseFixed(instr->context(), cp);
2655 LOperand* object = UseFixed(instr->enumerable(), r0);
2656 LForInPrepareMap* result = new(zone()) LForInPrepareMap(context, object);
2657 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
2661 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2662 LOperand* map = UseRegister(instr->map());
2663 return AssignEnvironment(DefineAsRegister(new(zone()) LForInCacheArray(map)));
2667 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2668 LOperand* value = UseRegisterAtStart(instr->value());
2669 LOperand* map = UseRegisterAtStart(instr->map());
2670 return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
2674 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2675 LOperand* object = UseRegister(instr->object());
2676 LOperand* index = UseTempRegister(instr->index());
2677 LLoadFieldByIndex* load = new(zone()) LLoadFieldByIndex(object, index);
2678 LInstruction* result = DefineSameAsFirst(load);
2679 return AssignPointerMap(result);
2683 LInstruction* LChunkBuilder::DoStoreFrameContext(HStoreFrameContext* instr) {
2684 LOperand* context = UseRegisterAtStart(instr->context());
2685 return new(zone()) LStoreFrameContext(context);
2689 LInstruction* LChunkBuilder::DoAllocateBlockContext(
2690 HAllocateBlockContext* instr) {
2691 LOperand* context = UseFixed(instr->context(), cp);
2692 LOperand* function = UseRegisterAtStart(instr->function());
2693 LAllocateBlockContext* result =
2694 new(zone()) LAllocateBlockContext(context, function);
2695 return MarkAsCall(DefineFixed(result, cp), instr);
2698 } } // namespace v8::internal