30 #if V8_TARGET_ARCH_X64
40 #define DEFINE_COMPILE(type) \
41 void L##type::CompileToNative(LCodeGen* generator) { \
42 generator->Do##type(this); \
49 void LInstruction::VerifyCall() {
57 for (UseIterator it(
this); !it.Done(); it.Advance()) {
59 ASSERT(operand->HasFixedPolicy() ||
60 operand->IsUsedAtStart());
64 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
71 stream->Add(
"%s ", this->
Mnemonic());
91 for (
int i = 0; i < InputCount(); i++) {
92 if (i > 0) stream->Add(
" ");
93 if (InputAt(i) ==
NULL) {
107 void LLabel::PrintDataTo(StringStream* stream) {
109 LLabel* rep = replacement();
111 stream->Add(
" Dead block replaced with B%d", rep->block_id());
117 for (
int i = 0; i < 4; i++) {
118 if (parallel_moves_[i] !=
NULL && !parallel_moves_[i]->
IsRedundant()) {
128 for (
int i = 0; i < 4; i++) {
130 if (parallel_moves_[i] !=
NULL) {
131 parallel_moves_[i]->PrintDataTo(stream);
138 const char* LArithmeticD::Mnemonic()
const {
144 case Token::MOD:
return "mod-d";
152 const char* LArithmeticT::Mnemonic()
const {
157 case Token::MOD:
return "mod-t";
159 case Token::BIT_AND:
return "bit-and-t";
160 case Token::BIT_OR:
return "bit-or-t";
161 case Token::BIT_XOR:
return "bit-xor-t";
163 case Token::SHL:
return "sal-t";
164 case Token::SAR:
return "sar-t";
165 case Token::SHR:
return "shr-t";
173 bool LGoto::HasInterestingComment(LCodeGen* gen)
const {
174 return !gen->IsNextEmittedBlock(block_id());
180 LPlatformChunk* chunk)
const {
181 HValue* hvalue = this->hydrogen_value();
183 if (hvalue ==
NULL)
return false;
184 if (!hvalue->representation().IsInteger32())
return false;
185 if (hvalue->HasRange() && !hvalue->range()->CanBeNegative())
return false;
187 return chunk->GetDehoistedKeyIds()->Contains(hvalue->id());
191 void LGoto::PrintDataTo(StringStream* stream) {
192 stream->Add(
"B%d", block_id());
196 void LBranch::PrintDataTo(StringStream* stream) {
197 stream->Add(
"B%d | B%d on ", true_block_id(), false_block_id());
198 value()->PrintTo(stream);
202 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
204 left()->PrintTo(stream);
206 right()->PrintTo(stream);
207 stream->Add(
" then B%d else B%d", true_block_id(), false_block_id());
211 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
212 stream->Add(
"if is_object(");
213 value()->PrintTo(stream);
214 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
218 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
219 stream->Add(
"if is_string(");
220 value()->PrintTo(stream);
221 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
225 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
226 stream->Add(
"if is_smi(");
227 value()->PrintTo(stream);
228 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
232 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
233 stream->Add(
"if is_undetectable(");
234 value()->PrintTo(stream);
235 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
239 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
240 stream->Add(
"if string_compare(");
241 left()->PrintTo(stream);
242 right()->PrintTo(stream);
243 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
247 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
248 stream->Add(
"if has_instance_type(");
249 value()->PrintTo(stream);
250 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
254 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
255 stream->Add(
"if has_cached_array_index(");
256 value()->PrintTo(stream);
257 stream->Add(
") then B%d else B%d", true_block_id(), false_block_id());
261 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
262 stream->Add(
"if class_of_test(");
263 value()->PrintTo(stream);
264 stream->Add(
", \"%o\") then B%d else B%d",
265 *hydrogen()->class_name(),
271 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
272 stream->Add(
"if typeof ");
273 value()->PrintTo(stream);
274 stream->Add(
" == \"%s\" then B%d else B%d",
275 hydrogen()->type_literal()->
ToCString().
get(),
276 true_block_id(), false_block_id());
280 void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
282 function()->PrintTo(stream);
283 stream->Add(
".code_entry = ");
284 code_object()->PrintTo(stream);
288 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
290 base_object()->PrintTo(stream);
292 offset()->PrintTo(stream);
296 void LCallJSFunction::PrintDataTo(StringStream* stream) {
298 function()->PrintTo(stream);
299 stream->Add(
"#%d / ", arity());
303 void LCallWithDescriptor::PrintDataTo(StringStream* stream) {
304 for (
int i = 0; i < InputCount(); i++) {
305 InputAt(i)->PrintTo(stream);
308 stream->Add(
"#%d / ", arity());
312 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
313 context()->PrintTo(stream);
314 stream->Add(
"[%d]", slot_index());
318 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
319 context()->PrintTo(stream);
320 stream->Add(
"[%d] <- ", slot_index());
321 value()->PrintTo(stream);
325 void LInvokeFunction::PrintDataTo(StringStream* stream) {
327 function()->PrintTo(stream);
328 stream->Add(
" #%d / ", arity());
332 void LCallNew::PrintDataTo(StringStream* stream) {
334 constructor()->PrintTo(stream);
335 stream->Add(
" #%d / ", arity());
339 void LCallNewArray::PrintDataTo(StringStream* stream) {
341 constructor()->PrintTo(stream);
342 stream->Add(
" #%d / ", arity());
348 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
349 arguments()->PrintTo(stream);
351 stream->Add(
" length ");
352 length()->PrintTo(stream);
354 stream->Add(
" index ");
355 index()->PrintTo(stream);
359 int LPlatformChunk::GetNextSpillIndex(
RegisterKind kind) {
360 return spill_slot_count_++;
364 LOperand* LPlatformChunk::GetNextSpillSlot(
RegisterKind kind) {
368 int index = GetNextSpillIndex(kind);
370 return LDoubleStackSlot::Create(index, zone());
373 return LStackSlot::Create(index, zone());
378 void LStoreNamedField::PrintDataTo(StringStream* stream) {
379 object()->PrintTo(stream);
380 hydrogen()->access().PrintTo(stream);
382 value()->PrintTo(stream);
386 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
387 object()->PrintTo(stream);
391 value()->PrintTo(stream);
399 if (hydrogen()->IsDehoisted()) {
411 if (hydrogen()->IsDehoisted()) {
414 stream->Add(
"] <- ");
418 ASSERT(hydrogen()->IsConstantHoleStore() &&
419 hydrogen()->
value()->representation().IsDouble());
420 stream->Add(
"<the hole(nan)>");
427 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
428 object()->PrintTo(stream);
430 key()->PrintTo(stream);
431 stream->Add(
"] <- ");
432 value()->PrintTo(stream);
436 void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
437 object()->PrintTo(stream);
438 stream->Add(
" %p -> %p", *original_map(), *transitioned_map());
442 LPlatformChunk* LChunkBuilder::Build() {
444 chunk_ =
new(zone()) LPlatformChunk(
info(), graph());
445 LPhase phase(
"L_Building chunk", chunk_);
450 if (graph()->has_osr()) {
451 for (
int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
456 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
457 for (
int i = 0; i < blocks->length(); i++) {
458 HBasicBlock* next =
NULL;
459 if (i < blocks->length() - 1) next = blocks->at(i + 1);
460 DoBasicBlock(blocks->at(i), next);
461 if (is_aborted())
return NULL;
469 info()->set_bailout_reason(reason);
474 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
480 LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
486 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
487 return Use(value, ToUnallocated(fixed_register));
491 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) {
492 return Use(value, ToUnallocated(reg));
496 LOperand* LChunkBuilder::UseRegister(HValue* value) {
501 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
508 LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
513 LOperand* LChunkBuilder::UseTempRegisterOrConstant(HValue* value) {
514 return value->IsConstant()
515 ? chunk_->DefineConstantOperand(HConstant::cast(value))
516 : UseTempRegister(value);
520 LOperand* LChunkBuilder::Use(HValue* value) {
525 LOperand* LChunkBuilder::UseAtStart(HValue* value) {
531 LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
532 return value->IsConstant()
533 ? chunk_->DefineConstantOperand(HConstant::cast(value))
538 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
539 return value->IsConstant()
540 ? chunk_->DefineConstantOperand(HConstant::cast(value))
545 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
546 return value->IsConstant()
547 ? chunk_->DefineConstantOperand(HConstant::cast(value))
548 : UseRegister(value);
552 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
553 return value->IsConstant()
554 ? chunk_->DefineConstantOperand(HConstant::cast(value))
555 : UseRegisterAtStart(value);
559 LOperand* LChunkBuilder::UseConstant(HValue* value) {
560 return chunk_->DefineConstantOperand(HConstant::cast(value));
564 LOperand* LChunkBuilder::UseAny(HValue* value) {
565 return value->IsConstant()
566 ? chunk_->DefineConstantOperand(HConstant::cast(value))
571 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
572 if (value->EmitAtUses()) {
574 VisitInstruction(instr);
576 operand->set_virtual_register(value->id());
581 LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr,
582 LUnallocated* result) {
583 result->set_virtual_register(current_instruction_->id());
584 instr->set_result(result);
589 LInstruction* LChunkBuilder::DefineAsRegister(
590 LTemplateResultInstruction<1>* instr) {
596 LInstruction* LChunkBuilder::DefineAsSpilled(
597 LTemplateResultInstruction<1>* instr,
604 LInstruction* LChunkBuilder::DefineSameAsFirst(
605 LTemplateResultInstruction<1>* instr) {
611 LInstruction* LChunkBuilder::DefineFixed(LTemplateResultInstruction<1>* instr,
613 return Define(instr, ToUnallocated(reg));
617 LInstruction* LChunkBuilder::DefineFixedDouble(
618 LTemplateResultInstruction<1>* instr,
620 return Define(instr, ToUnallocated(reg));
624 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
625 HEnvironment* hydrogen_env = current_block_->last_environment();
626 int argument_index_accumulator = 0;
627 ZoneList<HValue*> objects_to_materialize(0, zone());
628 instr->set_environment(CreateEnvironment(hydrogen_env,
629 &argument_index_accumulator,
630 &objects_to_materialize));
635 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
636 HInstruction* hinstr,
637 CanDeoptimize can_deoptimize) {
638 info()->MarkAsNonDeferredCalling();
644 instr = AssignPointerMap(instr);
650 bool needs_environment =
651 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
652 !hinstr->HasObservableSideEffects();
653 if (needs_environment && !instr->HasEnvironment()) {
654 instr = AssignEnvironment(instr);
661 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
662 ASSERT(!instr->HasPointerMap());
663 instr->set_pointer_map(
new(zone()) LPointerMap(zone()));
668 LUnallocated* LChunkBuilder::TempRegister() {
669 LUnallocated* operand =
671 int vreg = allocator_->GetVirtualRegister();
672 if (!allocator_->AllocationOk()) {
673 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
676 operand->set_virtual_register(vreg);
681 LOperand* LChunkBuilder::FixedTemp(Register reg) {
682 LUnallocated* operand = ToUnallocated(reg);
683 ASSERT(operand->HasFixedPolicy());
688 LOperand* LChunkBuilder::FixedTemp(XMMRegister reg) {
689 LUnallocated* operand = ToUnallocated(reg);
690 ASSERT(operand->HasFixedPolicy());
695 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
696 return new(zone()) LLabel(instr->block());
700 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
701 return DefineAsRegister(
new(zone()) LDummyUse(UseAny(instr->value())));
705 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
711 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
712 return AssignEnvironment(
new(zone()) LDeoptimize);
717 HBitwiseBinaryOperation* instr) {
718 if (instr->representation().IsSmiOrInteger32()) {
719 ASSERT(instr->left()->representation().Equals(instr->representation()));
720 ASSERT(instr->right()->representation().Equals(instr->representation()));
721 LOperand* left = UseRegisterAtStart(instr->left());
723 HValue* right_value = instr->right();
724 LOperand* right =
NULL;
725 int constant_value = 0;
726 if (right_value->IsConstant()) {
727 HConstant* constant = HConstant::cast(right_value);
728 right = chunk_->DefineConstantOperand(constant);
729 constant_value = constant->Integer32Value() & 0x1f;
731 right = UseFixed(right_value,
rcx);
736 bool does_deopt =
false;
737 if (op == Token::SHR && constant_value == 0) {
738 if (FLAG_opt_safe_uint32_operations) {
745 LInstruction* result =
746 DefineSameAsFirst(
new(zone()) LShiftI(op, left, right, does_deopt));
747 return does_deopt ? AssignEnvironment(result) : result;
749 return DoArithmeticT(op, instr);
754 LInstruction* LChunkBuilder::DoArithmeticD(
Token::Value op,
755 HArithmeticBinaryOperation* instr) {
756 ASSERT(instr->representation().IsDouble());
757 ASSERT(instr->left()->representation().IsDouble());
758 ASSERT(instr->right()->representation().IsDouble());
759 if (op == Token::MOD) {
760 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
761 LOperand* right = UseFixedDouble(instr->BetterRightOperand(),
xmm1);
762 LArithmeticD* result =
new(zone()) LArithmeticD(op, left, right);
763 return MarkAsCall(DefineSameAsFirst(result), instr);
765 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
766 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
767 LArithmeticD* result =
new(zone()) LArithmeticD(op, left, right);
768 return DefineSameAsFirst(result);
773 LInstruction* LChunkBuilder::DoArithmeticT(
Token::Value op,
774 HBinaryOperation* instr) {
775 HValue* left = instr->left();
776 HValue* right = instr->right();
777 ASSERT(left->representation().IsTagged());
778 ASSERT(right->representation().IsTagged());
779 LOperand* context = UseFixed(instr->context(),
rsi);
780 LOperand* left_operand = UseFixed(left,
rdx);
781 LOperand* right_operand = UseFixed(right,
rax);
782 LArithmeticT* result =
783 new(zone()) LArithmeticT(op, context, left_operand, right_operand);
784 return MarkAsCall(DefineFixed(result,
rax), instr);
788 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
790 current_block_ = block;
791 next_block_ = next_block;
792 if (block->IsStartBlock()) {
793 block->UpdateEnvironment(graph_->start_environment());
795 }
else if (block->predecessors()->length() == 1) {
798 ASSERT(block->phis()->length() == 0);
799 HBasicBlock* pred = block->predecessors()->at(0);
800 HEnvironment* last_environment = pred->last_environment();
803 if (pred->end()->SecondSuccessor() ==
NULL) {
804 ASSERT(pred->end()->FirstSuccessor() == block);
806 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
807 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
808 last_environment = last_environment->Copy();
811 block->UpdateEnvironment(last_environment);
812 ASSERT(pred->argument_count() >= 0);
813 argument_count_ = pred->argument_count();
816 HBasicBlock* pred = block->predecessors()->at(0);
818 HEnvironment* last_environment = pred->last_environment();
819 for (
int i = 0; i < block->phis()->length(); ++i) {
820 HPhi* phi = block->phis()->at(i);
821 if (phi->HasMergedIndex()) {
822 last_environment->SetValueAt(phi->merged_index(), phi);
825 for (
int i = 0; i < block->deleted_phis()->length(); ++i) {
826 if (block->deleted_phis()->at(i) < last_environment->length()) {
827 last_environment->SetValueAt(block->deleted_phis()->at(i),
828 graph_->GetConstantUndefined());
831 block->UpdateEnvironment(last_environment);
833 argument_count_ = pred->argument_count();
835 HInstruction* current = block->first();
836 int start = chunk_->instructions()->length();
837 while (current !=
NULL && !is_aborted()) {
839 if (!current->EmitAtUses()) {
840 VisitInstruction(current);
842 current = current->next();
844 int end = chunk_->instructions()->length() - 1;
846 block->set_first_instruction_index(start);
847 block->set_last_instruction_index(end);
849 block->set_argument_count(argument_count_);
851 current_block_ =
NULL;
855 void LChunkBuilder::VisitInstruction(HInstruction* current) {
856 HInstruction* old_current = current_instruction_;
857 current_instruction_ = current;
859 LInstruction* instr =
NULL;
860 if (current->CanReplaceWithDummyUses()) {
861 if (current->OperandCount() == 0) {
862 instr = DefineAsRegister(
new(zone()) LDummy());
864 ASSERT(!current->OperandAt(0)->IsControlInstruction());
865 instr = DefineAsRegister(
new(zone())
866 LDummyUse(UseAny(current->OperandAt(0))));
868 for (
int i = 1; i < current->OperandCount(); ++i) {
869 if (current->OperandAt(i)->IsControlInstruction())
continue;
870 LInstruction* dummy =
871 new(zone()) LDummyUse(UseAny(current->OperandAt(i)));
872 dummy->set_hydrogen_value(current);
873 chunk_->AddInstruction(dummy, current_block_);
876 instr = current->CompileToLithium(
this);
879 argument_count_ += current->argument_delta();
880 ASSERT(argument_count_ >= 0);
885 instr->set_hydrogen_value(current);
898 if (!(instr->ClobbersRegisters() && instr->ClobbersDoubleRegisters())) {
900 int used_at_start = 0;
901 for (UseIterator it(instr); !it.Done(); it.Advance()) {
903 if (operand->IsUsedAtStart()) ++used_at_start;
905 if (instr->Output() !=
NULL) {
908 for (TempIterator it(instr); !it.Done(); it.Advance()) {
910 if (operand->HasFixedPolicy()) ++fixed;
912 ASSERT(fixed == 0 || used_at_start == 0);
916 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
917 instr = AssignPointerMap(instr);
919 if (FLAG_stress_environments && !instr->HasEnvironment()) {
920 instr = AssignEnvironment(instr);
922 chunk_->AddInstruction(instr, current_block_);
924 if (instr->IsCall()) {
925 HValue* hydrogen_value_for_lazy_bailout = current;
926 LInstruction* instruction_needing_environment =
NULL;
927 if (current->HasObservableSideEffects()) {
928 HSimulate* sim = HSimulate::cast(current->next());
929 instruction_needing_environment = instr;
930 sim->ReplayEnvironment(current_block_->last_environment());
931 hydrogen_value_for_lazy_bailout = sim;
933 LInstruction* bailout = AssignEnvironment(
new(zone()) LLazyBailout());
934 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
935 chunk_->AddInstruction(bailout, current_block_);
936 if (instruction_needing_environment !=
NULL) {
939 instruction_needing_environment->
940 SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
944 current_instruction_ = old_current;
948 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
949 return new(zone()) LGoto(instr->FirstSuccessor());
953 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
954 return new(zone()) LDebugBreak();
958 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
959 LInstruction* goto_instr = CheckElideControlInstruction(instr);
960 if (goto_instr !=
NULL)
return goto_instr;
962 HValue* value = instr->value();
963 Representation r = value->representation();
964 HType type = value->type();
965 ToBooleanStub::Types expected = instr->expected_input_types();
968 bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() ||
969 type.IsJSArray() || type.IsHeapNumber() || type.IsString();
970 LInstruction* branch =
new(zone()) LBranch(UseRegister(value));
973 !expected.IsGeneric())) {
974 branch = AssignEnvironment(branch);
980 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
981 LInstruction* goto_instr = CheckElideControlInstruction(instr);
982 if (goto_instr !=
NULL)
return goto_instr;
984 ASSERT(instr->value()->representation().IsTagged());
985 LOperand* value = UseRegisterAtStart(instr->value());
986 return new(zone()) LCmpMapAndBranch(value);
990 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
991 info()->MarkAsRequiresFrame();
992 return DefineAsRegister(
new(zone()) LArgumentsLength(Use(length->value())));
996 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
997 info()->MarkAsRequiresFrame();
998 return DefineAsRegister(
new(zone()) LArgumentsElements);
1002 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
1003 LOperand* left = UseFixed(instr->left(),
rax);
1004 LOperand* right = UseFixed(instr->right(),
rdx);
1005 LOperand* context = UseFixed(instr->context(),
rsi);
1006 LInstanceOf* result =
new(zone()) LInstanceOf(context, left, right);
1007 return MarkAsCall(DefineFixed(result,
rax), instr);
1011 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1012 HInstanceOfKnownGlobal* instr) {
1013 LInstanceOfKnownGlobal* result =
1014 new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->context(),
rsi),
1015 UseFixed(instr->left(),
rax),
1017 return MarkAsCall(DefineFixed(result,
rax), instr);
1021 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
1022 LOperand* receiver = UseRegister(instr->receiver());
1023 LOperand*
function = UseRegisterAtStart(instr->function());
1024 LWrapReceiver* result =
new(zone()) LWrapReceiver(receiver,
function);
1025 return AssignEnvironment(DefineSameAsFirst(result));
1029 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1030 LOperand*
function = UseFixed(instr->function(),
rdi);
1031 LOperand* receiver = UseFixed(instr->receiver(),
rax);
1032 LOperand* length = UseFixed(instr->length(),
rbx);
1033 LOperand* elements = UseFixed(instr->elements(),
rcx);
1034 LApplyArguments* result =
new(zone()) LApplyArguments(
function,
1038 return MarkAsCall(DefineFixed(result,
rax), instr, CAN_DEOPTIMIZE_EAGERLY);
1042 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
1043 LOperand* argument = UseOrConstant(instr->argument());
1044 return new(zone()) LPushArgument(argument);
1048 LInstruction* LChunkBuilder::DoStoreCodeEntry(
1049 HStoreCodeEntry* store_code_entry) {
1050 LOperand*
function = UseRegister(store_code_entry->function());
1051 LOperand* code_object = UseTempRegister(store_code_entry->code_object());
1052 return new(zone()) LStoreCodeEntry(
function, code_object);
1056 LInstruction* LChunkBuilder::DoInnerAllocatedObject(
1057 HInnerAllocatedObject* instr) {
1058 LOperand* base_object = UseRegisterAtStart(instr->base_object());
1059 LOperand* offset = UseRegisterOrConstantAtStart(instr->offset());
1060 return DefineAsRegister(
1061 new(zone()) LInnerAllocatedObject(base_object, offset));
1065 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
1066 return instr->HasNoUses()
1068 : DefineAsRegister(
new(zone()) LThisFunction);
1072 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1073 if (instr->HasNoUses())
return NULL;
1075 if (
info()->IsStub()) {
1076 return DefineFixed(
new(zone()) LContext,
rsi);
1079 return DefineAsRegister(
new(zone()) LContext);
1083 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1084 LOperand* context = UseFixed(instr->context(),
rsi);
1085 return MarkAsCall(
new(zone()) LDeclareGlobals(context), instr);
1089 LInstruction* LChunkBuilder::DoCallJSFunction(
1090 HCallJSFunction* instr) {
1091 LOperand*
function = UseFixed(instr->function(),
rdi);
1093 LCallJSFunction* result =
new(zone()) LCallJSFunction(
function);
1095 return MarkAsCall(DefineFixed(result,
rax), instr);
1099 LInstruction* LChunkBuilder::DoCallWithDescriptor(
1100 HCallWithDescriptor* instr) {
1101 const CallInterfaceDescriptor* descriptor = instr->descriptor();
1103 LOperand* target = UseRegisterOrConstantAtStart(instr->target());
1104 ZoneList<LOperand*> ops(instr->OperandCount(), zone());
1105 ops.Add(target, zone());
1106 for (
int i = 1; i < instr->OperandCount(); i++) {
1107 LOperand* op = UseFixed(instr->OperandAt(i),
1108 descriptor->GetParameterRegister(i - 1));
1109 ops.Add(op, zone());
1112 LCallWithDescriptor* result =
new(zone()) LCallWithDescriptor(
1113 descriptor, ops, zone());
1114 return MarkAsCall(DefineFixed(result,
rax), instr);
1118 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1119 LOperand* context = UseFixed(instr->context(),
rsi);
1120 LOperand*
function = UseFixed(instr->function(),
rdi);
1121 LInvokeFunction* result =
new(zone()) LInvokeFunction(context,
function);
1122 return MarkAsCall(DefineFixed(result,
rax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1126 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1127 switch (instr->op()) {
1128 case kMathFloor:
return DoMathFloor(instr);
1129 case kMathRound:
return DoMathRound(instr);
1130 case kMathAbs:
return DoMathAbs(instr);
1131 case kMathLog:
return DoMathLog(instr);
1132 case kMathExp:
return DoMathExp(instr);
1133 case kMathSqrt:
return DoMathSqrt(instr);
1143 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
1144 LOperand* input = UseRegisterAtStart(instr->value());
1145 LMathFloor* result =
new(zone()) LMathFloor(input);
1146 return AssignEnvironment(DefineAsRegister(result));
1150 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
1151 LOperand* input = UseRegister(instr->value());
1152 LOperand* temp = FixedTemp(
xmm4);
1153 LMathRound* result =
new(zone()) LMathRound(input, temp);
1154 return AssignEnvironment(DefineAsRegister(result));
1158 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1159 LOperand* context = UseAny(instr->context());
1160 LOperand* input = UseRegisterAtStart(instr->value());
1161 LInstruction* result =
1162 DefineSameAsFirst(
new(zone()) LMathAbs(context, input));
1163 Representation r = instr->value()->representation();
1164 if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result);
1165 if (!r.IsDouble()) result = AssignEnvironment(result);
1170 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
1171 ASSERT(instr->representation().IsDouble());
1172 ASSERT(instr->value()->representation().IsDouble());
1173 LOperand* input = UseRegisterAtStart(instr->value());
1174 return MarkAsCall(DefineSameAsFirst(
new(zone()) LMathLog(input)), instr);
1178 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
1179 LOperand* input = UseRegisterAtStart(instr->value());
1180 LMathClz32* result =
new(zone()) LMathClz32(input);
1181 return DefineAsRegister(result);
1185 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1186 ASSERT(instr->representation().IsDouble());
1187 ASSERT(instr->value()->representation().IsDouble());
1188 LOperand* value = UseTempRegister(instr->value());
1189 LOperand* temp1 = TempRegister();
1190 LOperand* temp2 = TempRegister();
1191 LMathExp* result =
new(zone()) LMathExp(value, temp1, temp2);
1192 return DefineAsRegister(result);
1196 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
1197 LOperand* input = UseRegisterAtStart(instr->value());
1198 LMathSqrt* result =
new(zone()) LMathSqrt(input);
1199 return DefineSameAsFirst(result);
1203 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) {
1204 LOperand* input = UseRegisterAtStart(instr->value());
1205 LMathPowHalf* result =
new(zone()) LMathPowHalf(input);
1206 return DefineSameAsFirst(result);
1210 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1211 LOperand* context = UseFixed(instr->context(),
rsi);
1212 LOperand* constructor = UseFixed(instr->constructor(),
rdi);
1213 LCallNew* result =
new(zone()) LCallNew(context, constructor);
1214 return MarkAsCall(DefineFixed(result,
rax), instr);
1218 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1219 LOperand* context = UseFixed(instr->context(),
rsi);
1220 LOperand* constructor = UseFixed(instr->constructor(),
rdi);
1221 LCallNewArray* result =
new(zone()) LCallNewArray(context, constructor);
1222 return MarkAsCall(DefineFixed(result,
rax), instr);
1226 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1227 LOperand* context = UseFixed(instr->context(),
rsi);
1228 LOperand*
function = UseFixed(instr->function(),
rdi);
1229 LCallFunction* call =
new(zone()) LCallFunction(context,
function);
1230 return MarkAsCall(DefineFixed(call,
rax), instr);
1234 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1235 LOperand* context = UseFixed(instr->context(),
rsi);
1236 LCallRuntime* result =
new(zone()) LCallRuntime(context);
1237 return MarkAsCall(DefineFixed(result,
rax), instr);
1241 LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1246 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1247 return DoShift(Token::SHR, instr);
1251 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1252 return DoShift(Token::SAR, instr);
1256 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1257 return DoShift(Token::SHL, instr);
1261 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1262 if (instr->representation().IsSmiOrInteger32()) {
1263 ASSERT(instr->left()->representation().Equals(instr->representation()));
1264 ASSERT(instr->right()->representation().Equals(instr->representation()));
1267 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1268 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1269 return DefineSameAsFirst(
new(zone()) LBitI(left, right));
1271 return DoArithmeticT(instr->op(), instr);
1276 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) {
1277 ASSERT(instr->representation().IsSmiOrInteger32());
1278 ASSERT(instr->left()->representation().Equals(instr->representation()));
1279 ASSERT(instr->right()->representation().Equals(instr->representation()));
1280 LOperand* dividend = UseRegister(instr->left());
1281 int32_t divisor = instr->right()->GetInteger32Constant();
1282 LInstruction* result = DefineAsRegister(
new(zone()) LDivByPowerOf2I(
1283 dividend, divisor));
1287 divisor != 1 && divisor != -1)) {
1288 result = AssignEnvironment(result);
1294 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) {
1295 ASSERT(instr->representation().IsInteger32());
1296 ASSERT(instr->left()->representation().Equals(instr->representation()));
1297 ASSERT(instr->right()->representation().Equals(instr->representation()));
1298 LOperand* dividend = UseRegister(instr->left());
1299 int32_t divisor = instr->right()->GetInteger32Constant();
1300 LOperand* temp1 = FixedTemp(
rax);
1301 LOperand* temp2 = FixedTemp(
rdx);
1302 LInstruction* result = DefineFixed(
new(zone()) LDivByConstI(
1303 dividend, divisor, temp1, temp2),
rdx);
1307 result = AssignEnvironment(result);
1313 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) {
1314 ASSERT(instr->representation().IsSmiOrInteger32());
1315 ASSERT(instr->left()->representation().Equals(instr->representation()));
1316 ASSERT(instr->right()->representation().Equals(instr->representation()));
1317 LOperand* dividend = UseFixed(instr->left(),
rax);
1318 LOperand* divisor = UseRegister(instr->right());
1319 LOperand* temp = FixedTemp(
rdx);
1320 LInstruction* result = DefineFixed(
new(zone()) LDivI(
1321 dividend, divisor, temp),
rax);
1325 (!instr->IsMathFloorOfDiv() &&
1327 result = AssignEnvironment(result);
1333 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1334 if (instr->representation().IsSmiOrInteger32()) {
1335 if (instr->RightIsPowerOf2()) {
1336 return DoDivByPowerOf2I(instr);
1337 }
else if (instr->right()->IsConstant()) {
1338 return DoDivByConstI(instr);
1340 return DoDivI(instr);
1342 }
else if (instr->representation().IsDouble()) {
1350 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
1351 LOperand* dividend = UseRegisterAtStart(instr->left());
1352 int32_t divisor = instr->right()->GetInteger32Constant();
1353 LInstruction* result = DefineSameAsFirst(
new(zone()) LFlooringDivByPowerOf2I(
1354 dividend, divisor));
1357 result = AssignEnvironment(result);
1363 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
1364 ASSERT(instr->representation().IsInteger32());
1365 ASSERT(instr->left()->representation().Equals(instr->representation()));
1366 ASSERT(instr->right()->representation().Equals(instr->representation()));
1367 LOperand* dividend = UseRegister(instr->left());
1368 int32_t divisor = instr->right()->GetInteger32Constant();
1369 LOperand* temp1 = FixedTemp(
rax);
1370 LOperand* temp2 = FixedTemp(
rdx);
1374 NULL : TempRegister();
1375 LInstruction* result =
1376 DefineFixed(
new(zone()) LFlooringDivByConstI(dividend,
1384 result = AssignEnvironment(result);
1390 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1391 if (instr->RightIsPowerOf2()) {
1392 return DoFlooringDivByPowerOf2I(instr);
1393 }
else if (instr->right()->IsConstant()) {
1394 return DoFlooringDivByConstI(instr);
1396 return DoDivI(instr);
1401 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
1402 ASSERT(instr->representation().IsSmiOrInteger32());
1403 ASSERT(instr->left()->representation().Equals(instr->representation()));
1404 ASSERT(instr->right()->representation().Equals(instr->representation()));
1405 LOperand* dividend = UseRegisterAtStart(instr->left());
1406 int32_t divisor = instr->right()->GetInteger32Constant();
1407 LInstruction* result = DefineSameAsFirst(
new(zone()) LModByPowerOf2I(
1408 dividend, divisor));
1410 result = AssignEnvironment(result);
1416 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) {
1417 ASSERT(instr->representation().IsSmiOrInteger32());
1418 ASSERT(instr->left()->representation().Equals(instr->representation()));
1419 ASSERT(instr->right()->representation().Equals(instr->representation()));
1420 LOperand* dividend = UseRegister(instr->left());
1421 int32_t divisor = instr->right()->GetInteger32Constant();
1422 LOperand* temp1 = FixedTemp(
rax);
1423 LOperand* temp2 = FixedTemp(
rdx);
1424 LInstruction* result = DefineFixed(
new(zone()) LModByConstI(
1425 dividend, divisor, temp1, temp2),
rax);
1427 result = AssignEnvironment(result);
1433 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
1434 ASSERT(instr->representation().IsSmiOrInteger32());
1435 ASSERT(instr->left()->representation().Equals(instr->representation()));
1436 ASSERT(instr->right()->representation().Equals(instr->representation()));
1437 LOperand* dividend = UseFixed(instr->left(),
rax);
1438 LOperand* divisor = UseRegister(instr->right());
1439 LOperand* temp = FixedTemp(
rdx);
1440 LInstruction* result = DefineFixed(
new(zone()) LModI(
1441 dividend, divisor, temp),
rdx);
1444 result = AssignEnvironment(result);
1450 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1451 if (instr->representation().IsSmiOrInteger32()) {
1452 if (instr->RightIsPowerOf2()) {
1453 return DoModByPowerOf2I(instr);
1454 }
else if (instr->right()->IsConstant()) {
1455 return DoModByConstI(instr);
1457 return DoModI(instr);
1459 }
else if (instr->representation().IsDouble()) {
1460 return DoArithmeticD(Token::MOD, instr);
1462 return DoArithmeticT(Token::MOD, instr);
1467 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1468 if (instr->representation().IsSmiOrInteger32()) {
1469 ASSERT(instr->left()->representation().Equals(instr->representation()));
1470 ASSERT(instr->right()->representation().Equals(instr->representation()));
1471 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1472 LOperand* right = UseOrConstant(instr->BetterRightOperand());
1473 LMulI* mul =
new(zone()) LMulI(left, right);
1476 AssignEnvironment(mul);
1478 return DefineSameAsFirst(mul);
1479 }
else if (instr->representation().IsDouble()) {
1487 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1488 if (instr->representation().IsSmiOrInteger32()) {
1489 ASSERT(instr->left()->representation().Equals(instr->representation()));
1490 ASSERT(instr->right()->representation().Equals(instr->representation()));
1491 LOperand* left = UseRegisterAtStart(instr->left());
1492 LOperand* right = UseOrConstantAtStart(instr->right());
1493 LSubI* sub =
new(zone()) LSubI(left, right);
1494 LInstruction* result = DefineSameAsFirst(sub);
1496 result = AssignEnvironment(result);
1499 }
else if (instr->representation().IsDouble()) {
1507 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1508 if (instr->representation().IsSmiOrInteger32()) {
1513 bool use_lea = LAddI::UseLea(instr);
1514 ASSERT(instr->left()->representation().Equals(instr->representation()));
1515 ASSERT(instr->right()->representation().Equals(instr->representation()));
1516 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1517 HValue* right_candidate = instr->BetterRightOperand();
1518 LOperand* right = use_lea
1519 ? UseRegisterOrConstantAtStart(right_candidate)
1520 : UseOrConstantAtStart(right_candidate);
1521 LAddI* add =
new(zone()) LAddI(left, right);
1523 LInstruction* result = use_lea
1524 ? DefineAsRegister(add)
1525 : DefineSameAsFirst(add);
1527 result = AssignEnvironment(result);
1530 }
else if (instr->representation().IsExternal()) {
1531 ASSERT(instr->left()->representation().IsExternal());
1532 ASSERT(instr->right()->representation().IsInteger32());
1534 bool use_lea = LAddI::UseLea(instr);
1535 LOperand* left = UseRegisterAtStart(instr->left());
1536 HValue* right_candidate = instr->right();
1537 LOperand* right = use_lea
1538 ? UseRegisterOrConstantAtStart(right_candidate)
1539 : UseOrConstantAtStart(right_candidate);
1540 LAddI* add =
new(zone()) LAddI(left, right);
1541 LInstruction* result = use_lea
1542 ? DefineAsRegister(add)
1543 : DefineSameAsFirst(add);
1545 }
else if (instr->representation().IsDouble()) {
1554 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1555 LOperand* left =
NULL;
1556 LOperand* right =
NULL;
1557 ASSERT(instr->left()->representation().Equals(instr->representation()));
1558 ASSERT(instr->right()->representation().Equals(instr->representation()));
1559 if (instr->representation().IsSmi()) {
1560 left = UseRegisterAtStart(instr->BetterLeftOperand());
1561 right = UseAtStart(instr->BetterRightOperand());
1562 }
else if (instr->representation().IsInteger32()) {
1563 left = UseRegisterAtStart(instr->BetterLeftOperand());
1564 right = UseOrConstantAtStart(instr->BetterRightOperand());
1566 ASSERT(instr->representation().IsDouble());
1567 left = UseRegisterAtStart(instr->left());
1568 right = UseRegisterAtStart(instr->right());
1570 LMathMinMax* minmax =
new(zone()) LMathMinMax(left, right);
1571 return DefineSameAsFirst(minmax);
1575 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1576 ASSERT(instr->representation().IsDouble());
1579 Representation exponent_type = instr->right()->representation();
1580 ASSERT(instr->left()->representation().IsDouble());
1581 LOperand* left = UseFixedDouble(instr->left(),
xmm2);
1582 LOperand* right = exponent_type.IsDouble() ?
1583 UseFixedDouble(instr->right(),
xmm1) : UseFixed(instr->right(),
rdx);
1584 LPower* result =
new(zone()) LPower(left, right);
1585 return MarkAsCall(DefineFixedDouble(result,
xmm3), instr,
1586 CAN_DEOPTIMIZE_EAGERLY);
1590 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1591 ASSERT(instr->left()->representation().IsTagged());
1592 ASSERT(instr->right()->representation().IsTagged());
1593 LOperand* context = UseFixed(instr->context(),
rsi);
1594 LOperand* left = UseFixed(instr->left(),
rdx);
1595 LOperand* right = UseFixed(instr->right(),
rax);
1596 LCmpT* result =
new(zone()) LCmpT(context, left, right);
1597 return MarkAsCall(DefineFixed(result,
rax), instr);
1601 LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
1602 HCompareNumericAndBranch* instr) {
1603 Representation r = instr->representation();
1604 if (r.IsSmiOrInteger32()) {
1605 ASSERT(instr->left()->representation().Equals(r));
1606 ASSERT(instr->right()->representation().Equals(r));
1607 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1608 LOperand* right = UseOrConstantAtStart(instr->right());
1609 return new(zone()) LCompareNumericAndBranch(left, right);
1612 ASSERT(instr->left()->representation().IsDouble());
1613 ASSERT(instr->right()->representation().IsDouble());
1616 if (instr->left()->IsConstant() && instr->right()->IsConstant()) {
1617 left = UseRegisterOrConstantAtStart(instr->left());
1618 right = UseRegisterOrConstantAtStart(instr->right());
1620 left = UseRegisterAtStart(instr->left());
1621 right = UseRegisterAtStart(instr->right());
1623 return new(zone()) LCompareNumericAndBranch(left, right);
1628 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1629 HCompareObjectEqAndBranch* instr) {
1630 LInstruction* goto_instr = CheckElideControlInstruction(instr);
1631 if (goto_instr !=
NULL)
return goto_instr;
1632 LOperand* left = UseRegisterAtStart(instr->left());
1633 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
1634 return new(zone()) LCmpObjectEqAndBranch(left, right);
1638 LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1639 HCompareHoleAndBranch* instr) {
1640 LOperand* value = UseRegisterAtStart(instr->value());
1641 return new(zone()) LCmpHoleAndBranch(value);
1645 LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
1646 HCompareMinusZeroAndBranch* instr) {
1647 LInstruction* goto_instr = CheckElideControlInstruction(instr);
1648 if (goto_instr !=
NULL)
return goto_instr;
1649 LOperand* value = UseRegister(instr->value());
1650 return new(zone()) LCompareMinusZeroAndBranch(value);
1654 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1655 ASSERT(instr->value()->representation().IsTagged());
1656 return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()));
1660 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1661 ASSERT(instr->value()->representation().IsTagged());
1662 LOperand* value = UseRegisterAtStart(instr->value());
1663 LOperand* temp = TempRegister();
1664 return new(zone()) LIsStringAndBranch(value, temp);
1668 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1669 ASSERT(instr->value()->representation().IsTagged());
1670 return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1674 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1675 HIsUndetectableAndBranch* instr) {
1676 ASSERT(instr->value()->representation().IsTagged());
1677 LOperand* value = UseRegisterAtStart(instr->value());
1678 LOperand* temp = TempRegister();
1679 return new(zone()) LIsUndetectableAndBranch(value, temp);
1683 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1684 HStringCompareAndBranch* instr) {
1686 ASSERT(instr->left()->representation().IsTagged());
1687 ASSERT(instr->right()->representation().IsTagged());
1688 LOperand* context = UseFixed(instr->context(),
rsi);
1689 LOperand* left = UseFixed(instr->left(),
rdx);
1690 LOperand* right = UseFixed(instr->right(),
rax);
1691 LStringCompareAndBranch* result =
1692 new(zone()) LStringCompareAndBranch(context, left, right);
1694 return MarkAsCall(result, instr);
1698 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1699 HHasInstanceTypeAndBranch* instr) {
1700 ASSERT(instr->value()->representation().IsTagged());
1701 LOperand* value = UseRegisterAtStart(instr->value());
1702 return new(zone()) LHasInstanceTypeAndBranch(value);
1706 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1707 HGetCachedArrayIndex* instr) {
1708 ASSERT(instr->value()->representation().IsTagged());
1709 LOperand* value = UseRegisterAtStart(instr->value());
1711 return DefineAsRegister(
new(zone()) LGetCachedArrayIndex(value));
1715 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1716 HHasCachedArrayIndexAndBranch* instr) {
1717 ASSERT(instr->value()->representation().IsTagged());
1718 LOperand* value = UseRegisterAtStart(instr->value());
1719 return new(zone()) LHasCachedArrayIndexAndBranch(value);
1723 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1724 HClassOfTestAndBranch* instr) {
1725 LOperand* value = UseRegister(instr->value());
1726 return new(zone()) LClassOfTestAndBranch(value,
1732 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1733 LOperand*
map = UseRegisterAtStart(instr->value());
1734 return DefineAsRegister(
new(zone()) LMapEnumLength(map));
1738 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1739 LOperand*
object = UseFixed(instr->value(),
rax);
1740 LDateField* result =
new(zone()) LDateField(
object, instr->index());
1741 return MarkAsCall(DefineFixed(result,
rax), instr, CAN_DEOPTIMIZE_EAGERLY);
1745 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
1746 LOperand*
string = UseRegisterAtStart(instr->string());
1747 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1748 return DefineAsRegister(
new(zone()) LSeqStringGetChar(
string, index));
1752 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1753 LOperand*
string = UseRegisterAtStart(instr->string());
1754 LOperand* index = FLAG_debug_code
1755 ? UseRegisterAtStart(instr->index())
1756 : UseRegisterOrConstantAtStart(instr->index());
1757 LOperand* value = FLAG_debug_code
1758 ? UseRegisterAtStart(instr->value())
1759 : UseRegisterOrConstantAtStart(instr->value());
1760 LOperand* context = FLAG_debug_code ? UseFixed(instr->context(),
rsi) :
NULL;
1761 LInstruction* result =
new(zone()) LSeqStringSetChar(context,
string,
1763 if (FLAG_debug_code) {
1764 result = MarkAsCall(result, instr);
1770 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1771 LOperand* value = UseRegisterOrConstantAtStart(instr->index());
1772 LOperand* length = Use(instr->length());
1773 return AssignEnvironment(
new(zone()) LBoundsCheck(value, length));
1777 LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
1778 HBoundsCheckBaseIndexInformation* instr) {
1784 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1791 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1796 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1804 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1805 Representation from = instr->from();
1806 Representation to = instr->to();
1808 if (to.IsTagged()) {
1809 LOperand* value = UseRegister(instr->value());
1810 return DefineSameAsFirst(
new(zone()) LDummyUse(value));
1817 if (from.IsTagged()) {
1818 if (to.IsDouble()) {
1819 LOperand* value = UseRegister(instr->value());
1820 LInstruction* res = DefineAsRegister(
new(zone()) LNumberUntagD(value));
1821 if (!instr->value()->representation().IsSmi()) {
1822 res = AssignEnvironment(res);
1825 }
else if (to.IsSmi()) {
1826 HValue* val = instr->value();
1827 LOperand* value = UseRegister(val);
1828 if (val->type().IsSmi()) {
1829 return DefineSameAsFirst(
new(zone()) LDummyUse(value));
1831 return AssignEnvironment(DefineSameAsFirst(
new(zone()) LCheckSmi(value)));
1833 ASSERT(to.IsInteger32());
1834 HValue* val = instr->value();
1835 LOperand* value = UseRegister(val);
1836 if (val->type().IsSmi() || val->representation().IsSmi()) {
1837 return DefineSameAsFirst(
new(zone()) LSmiUntag(value,
false));
1839 bool truncating = instr->CanTruncateToInt32();
1840 LOperand* xmm_temp = truncating ?
NULL : FixedTemp(
xmm1);
1842 DefineSameAsFirst(
new(zone()) LTaggedToI(value, xmm_temp));
1843 if (!instr->value()->representation().IsSmi()) {
1845 res = AssignEnvironment(res);
1850 }
else if (from.IsDouble()) {
1851 if (to.IsTagged()) {
1852 info()->MarkAsDeferredCalling();
1853 LOperand* value = UseRegister(instr->value());
1854 LOperand* temp = TempRegister();
1857 LUnallocated* result_temp = TempRegister();
1858 LNumberTagD* result =
new(zone()) LNumberTagD(value, temp);
1859 return AssignPointerMap(Define(result, result_temp));
1860 }
else if (to.IsSmi()) {
1861 LOperand* value = UseRegister(instr->value());
1862 return AssignEnvironment(
1863 DefineAsRegister(
new(zone()) LDoubleToSmi(value)));
1865 ASSERT(to.IsInteger32());
1866 LOperand* value = UseRegister(instr->value());
1867 LInstruction* result = DefineAsRegister(
new(zone()) LDoubleToI(value));
1868 if (!instr->CanTruncateToInt32()) {
1869 result = AssignEnvironment(result);
1873 }
else if (from.IsInteger32()) {
1874 info()->MarkAsDeferredCalling();
1875 if (to.IsTagged()) {
1876 HValue* val = instr->value();
1877 LOperand* value = UseRegister(val);
1879 return DefineAsRegister(
new(zone()) LSmiTag(value));
1881 LOperand* temp1 = TempRegister();
1882 LOperand* temp2 = FixedTemp(
xmm1);
1883 LNumberTagU* result =
new(zone()) LNumberTagU(value, temp1, temp2);
1884 return AssignPointerMap(DefineSameAsFirst(result));
1886 LNumberTagI* result =
new(zone()) LNumberTagI(value);
1887 return AssignPointerMap(DefineSameAsFirst(result));
1889 }
else if (to.IsSmi()) {
1890 HValue* val = instr->value();
1891 LOperand* value = UseRegister(val);
1892 LInstruction* result = DefineAsRegister(
new(zone()) LSmiTag(value));
1895 result = AssignEnvironment(result);
1900 LOperand* temp = FixedTemp(
xmm1);
1901 return DefineAsRegister(
1902 new(zone()) LUint32ToDouble(UseRegister(instr->value()), temp));
1905 LOperand* value = Use(instr->value());
1906 return DefineAsRegister(
new(zone()) LInteger32ToDouble(value));
1915 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
1916 LOperand* value = UseRegisterAtStart(instr->value());
1917 return AssignEnvironment(
new(zone()) LCheckNonSmi(value));
1921 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1922 LOperand* value = UseRegisterAtStart(instr->value());
1923 return AssignEnvironment(
new(zone()) LCheckSmi(value));
1927 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1928 LOperand* value = UseRegisterAtStart(instr->value());
1929 LCheckInstanceType* result =
new(zone()) LCheckInstanceType(value);
1930 return AssignEnvironment(result);
1934 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
1935 LOperand* value = UseRegisterAtStart(instr->value());
1936 return AssignEnvironment(
new(zone()) LCheckValue(value));
1940 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
1941 LOperand* value =
NULL;
1942 if (!instr->CanOmitMapChecks()) {
1943 value = UseRegisterAtStart(instr->value());
1944 if (instr->has_migration_target())
info()->MarkAsDeferredCalling();
1946 LCheckMaps* result =
new(zone()) LCheckMaps(value);
1947 if (!instr->CanOmitMapChecks()) {
1949 AssignEnvironment(result);
1950 if (instr->has_migration_target())
return AssignPointerMap(result);
1956 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1957 HValue* value = instr->value();
1958 Representation input_rep = value->representation();
1959 LOperand* reg = UseRegister(value);
1960 if (input_rep.IsDouble()) {
1961 return DefineAsRegister(
new(zone()) LClampDToUint8(reg));
1962 }
else if (input_rep.IsInteger32()) {
1963 return DefineSameAsFirst(
new(zone()) LClampIToUint8(reg));
1965 ASSERT(input_rep.IsSmiOrTagged());
1968 LClampTToUint8* result =
new(zone()) LClampTToUint8(reg,
1970 return AssignEnvironment(DefineSameAsFirst(result));
1975 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) {
1976 HValue* value = instr->value();
1977 ASSERT(value->representation().IsDouble());
1978 return DefineAsRegister(
new(zone()) LDoubleBits(UseRegister(value)));
1982 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
1983 LOperand*
lo = UseRegister(instr->lo());
1984 LOperand*
hi = UseRegister(instr->hi());
1985 return DefineAsRegister(
new(zone()) LConstructDouble(hi, lo));
1989 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1990 LOperand* context =
info()->IsStub() ? UseFixed(instr->context(),
rsi) :
NULL;
1991 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
1992 return new(zone()) LReturn(
1993 UseFixed(instr->value(),
rax), context, parameter_count);
1997 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1998 Representation r = instr->representation();
2000 return DefineAsRegister(
new(zone()) LConstantS);
2001 }
else if (r.IsInteger32()) {
2002 return DefineAsRegister(
new(zone()) LConstantI);
2003 }
else if (r.IsDouble()) {
2004 LOperand* temp = TempRegister();
2005 return DefineAsRegister(
new(zone()) LConstantD(temp));
2006 }
else if (r.IsExternal()) {
2007 return DefineAsRegister(
new(zone()) LConstantE);
2008 }
else if (r.IsTagged()) {
2009 return DefineAsRegister(
new(zone()) LConstantT);
2017 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
2018 LLoadGlobalCell* result =
new(zone()) LLoadGlobalCell;
2019 return instr->RequiresHoleCheck()
2020 ? AssignEnvironment(DefineAsRegister(result))
2021 : DefineAsRegister(result);
2025 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
2026 LOperand* context = UseFixed(instr->context(),
rsi);
2027 LOperand* global_object = UseFixed(instr->global_object(),
rax);
2028 LLoadGlobalGeneric* result =
2029 new(zone()) LLoadGlobalGeneric(context, global_object);
2030 return MarkAsCall(DefineFixed(result,
rax), instr);
2034 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
2035 LOperand* value = UseRegister(instr->value());
2038 return instr->RequiresHoleCheck()
2039 ? AssignEnvironment(
new(zone()) LStoreGlobalCell(value, TempRegister()))
2040 : new(zone()) LStoreGlobalCell(value,
NULL);
2044 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
2045 LOperand* context = UseRegisterAtStart(instr->value());
2046 LInstruction* result =
2047 DefineAsRegister(
new(zone()) LLoadContextSlot(context));
2048 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
2049 result = AssignEnvironment(result);
2055 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
2059 context = UseRegister(instr->context());
2060 if (instr->NeedsWriteBarrier()) {
2061 value = UseTempRegister(instr->value());
2062 temp = TempRegister();
2064 value = UseRegister(instr->value());
2067 LInstruction* result =
new(zone()) LStoreContextSlot(context, value, temp);
2068 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
2069 result = AssignEnvironment(result);
2075 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
2078 if (instr->access().IsExternalMemory() &&
2079 instr->access().offset() == 0 &&
2080 (instr->access().representation().IsSmi() ||
2081 instr->access().representation().IsTagged() ||
2082 instr->access().representation().IsHeapObject() ||
2083 instr->access().representation().IsExternal())) {
2084 LOperand*
obj = UseRegisterOrConstantAtStart(instr->object());
2085 return DefineFixed(
new(zone()) LLoadNamedField(obj),
rax);
2087 LOperand* obj = UseRegisterAtStart(instr->object());
2088 return DefineAsRegister(
new(zone()) LLoadNamedField(obj));
2092 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
2093 LOperand* context = UseFixed(instr->context(),
rsi);
2094 LOperand*
object = UseFixed(instr->object(),
rax);
2095 LLoadNamedGeneric* result =
new(zone()) LLoadNamedGeneric(context,
object);
2096 return MarkAsCall(DefineFixed(result,
rax), instr);
2100 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
2101 HLoadFunctionPrototype* instr) {
2102 return AssignEnvironment(DefineAsRegister(
2103 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
2107 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
2108 return DefineAsRegister(
new(zone()) LLoadRoot);
2112 void LChunkBuilder::FindDehoistedKeyDefinitions(HValue* candidate) {
2113 BitVector* dehoisted_key_ids = chunk_->GetDehoistedKeyIds();
2114 if (dehoisted_key_ids->Contains(candidate->id()))
return;
2115 dehoisted_key_ids->Add(candidate->id());
2116 if (!candidate->IsPhi())
return;
2117 for (
int i = 0; i < candidate->OperandCount(); ++i) {
2118 FindDehoistedKeyDefinitions(candidate->OperandAt(i));
2123 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
2124 ASSERT(instr->key()->representation().IsInteger32());
2126 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
2127 LInstruction* result =
NULL;
2129 if (instr->IsDehoisted()) {
2130 FindDehoistedKeyDefinitions(instr->key());
2133 if (!instr->is_typed_elements()) {
2134 LOperand* obj = UseRegisterAtStart(instr->elements());
2135 result = DefineAsRegister(
new(zone()) LLoadKeyed(obj, key));
2138 (instr->representation().IsInteger32() &&
2140 (instr->representation().IsDouble() &&
2142 LOperand* backing_store = UseRegister(instr->elements());
2143 result = DefineAsRegister(
new(zone()) LLoadKeyed(backing_store, key));
2146 if ((instr->is_external() || instr->is_fixed_typed_array()) ?
2153 instr->RequiresHoleCheck()) {
2154 result = AssignEnvironment(result);
2160 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
2161 LOperand* context = UseFixed(instr->context(),
rsi);
2162 LOperand*
object = UseFixed(instr->object(),
rdx);
2163 LOperand* key = UseFixed(instr->key(),
rax);
2165 LLoadKeyedGeneric* result =
2166 new(zone()) LLoadKeyedGeneric(context,
object, key);
2167 return MarkAsCall(DefineFixed(result,
rax), instr);
2171 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
2174 if (instr->IsDehoisted()) {
2175 FindDehoistedKeyDefinitions(instr->key());
2178 if (!instr->is_typed_elements()) {
2179 ASSERT(instr->elements()->representation().IsTagged());
2180 bool needs_write_barrier = instr->NeedsWriteBarrier();
2181 LOperand*
object =
NULL;
2182 LOperand* key =
NULL;
2183 LOperand* val =
NULL;
2185 Representation value_representation = instr->value()->representation();
2186 if (value_representation.IsDouble()) {
2187 object = UseRegisterAtStart(instr->elements());
2188 val = UseRegisterAtStart(instr->value());
2189 key = UseRegisterOrConstantAtStart(instr->key());
2191 ASSERT(value_representation.IsSmiOrTagged() ||
2192 value_representation.IsInteger32());
2193 if (needs_write_barrier) {
2194 object = UseTempRegister(instr->elements());
2195 val = UseTempRegister(instr->value());
2196 key = UseTempRegister(instr->key());
2198 object = UseRegisterAtStart(instr->elements());
2199 val = UseRegisterOrConstantAtStart(instr->value());
2200 key = UseRegisterOrConstantAtStart(instr->key());
2204 return new(zone()) LStoreKeyed(
object, key, val);
2208 (instr->value()->representation().IsInteger32() &&
2210 (instr->value()->representation().IsDouble() &&
2212 ASSERT((instr->is_fixed_typed_array() &&
2213 instr->elements()->representation().IsTagged()) ||
2214 (instr->is_external() &&
2215 instr->elements()->representation().IsExternal()));
2216 bool val_is_temp_register =
2220 LOperand* val = val_is_temp_register ? UseTempRegister(instr->value())
2221 : UseRegister(instr->value());
2222 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
2223 LOperand* backing_store = UseRegister(instr->elements());
2224 return new(zone()) LStoreKeyed(backing_store, key, val);
2228 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
2229 LOperand* context = UseFixed(instr->context(),
rsi);
2230 LOperand*
object = UseFixed(instr->object(),
rdx);
2231 LOperand* key = UseFixed(instr->key(),
rcx);
2232 LOperand* value = UseFixed(instr->value(),
rax);
2234 ASSERT(instr->object()->representation().IsTagged());
2235 ASSERT(instr->key()->representation().IsTagged());
2236 ASSERT(instr->value()->representation().IsTagged());
2238 LStoreKeyedGeneric* result =
2239 new(zone()) LStoreKeyedGeneric(context,
object, key, value);
2240 return MarkAsCall(result, instr);
2244 LInstruction* LChunkBuilder::DoTransitionElementsKind(
2245 HTransitionElementsKind* instr) {
2246 LOperand*
object = UseRegister(instr->object());
2248 LOperand*
object = UseRegister(instr->object());
2249 LOperand* new_map_reg = TempRegister();
2250 LOperand* temp_reg = TempRegister();
2251 LTransitionElementsKind* result =
new(zone()) LTransitionElementsKind(
2252 object,
NULL, new_map_reg, temp_reg);
2255 LOperand* context = UseFixed(instr->context(),
rsi);
2256 LTransitionElementsKind* result =
2257 new(zone()) LTransitionElementsKind(
object, context,
NULL,
NULL);
2258 return AssignPointerMap(result);
2263 LInstruction* LChunkBuilder::DoTrapAllocationMemento(
2264 HTrapAllocationMemento* instr) {
2265 LOperand*
object = UseRegister(instr->object());
2266 LOperand* temp = TempRegister();
2267 LTrapAllocationMemento* result =
2268 new(zone()) LTrapAllocationMemento(
object, temp);
2269 return AssignEnvironment(result);
2273 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2274 bool is_in_object = instr->access().IsInobject();
2275 bool is_external_location = instr->access().IsExternalMemory() &&
2276 instr->access().offset() == 0;
2277 bool needs_write_barrier = instr->NeedsWriteBarrier();
2278 bool needs_write_barrier_for_map = instr->has_transition() &&
2279 instr->NeedsWriteBarrierForMap();
2282 if (needs_write_barrier) {
2284 ? UseRegister(instr->object())
2285 : UseTempRegister(instr->object());
2286 }
else if (is_external_location) {
2288 ASSERT(!needs_write_barrier);
2289 ASSERT(!needs_write_barrier_for_map);
2290 obj = UseRegisterOrConstant(instr->object());
2292 obj = needs_write_barrier_for_map
2293 ? UseRegister(instr->object())
2294 : UseRegisterAtStart(instr->object());
2297 bool can_be_constant = instr->value()->IsConstant() &&
2298 HConstant::cast(instr->value())->NotInNewSpace() &&
2299 !instr->field_representation().IsDouble();
2302 if (needs_write_barrier) {
2303 val = UseTempRegister(instr->value());
2304 }
else if (is_external_location) {
2305 val = UseFixed(instr->value(),
rax);
2306 }
else if (can_be_constant) {
2307 val = UseRegisterOrConstant(instr->value());
2308 }
else if (instr->field_representation().IsSmi()) {
2309 val = UseRegister(instr->value());
2310 }
else if (instr->field_representation().IsDouble()) {
2311 val = UseRegisterAtStart(instr->value());
2313 val = UseRegister(instr->value());
2318 LOperand* temp = (!is_in_object || needs_write_barrier ||
2319 needs_write_barrier_for_map) ? TempRegister() :
NULL;
2321 LInstruction* result =
new(zone()) LStoreNamedField(obj, val, temp);
2322 if (!instr->access().IsExternalMemory() &&
2323 instr->field_representation().IsHeapObject() &&
2324 (val->IsConstantOperand()
2325 ? HConstant::cast(instr->value())->HasSmiValue()
2326 : !instr->value()->type().IsHeapObject())) {
2327 result = AssignEnvironment(result);
2333 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2334 LOperand* context = UseFixed(instr->context(),
rsi);
2335 LOperand*
object = UseFixed(instr->object(),
rdx);
2336 LOperand* value = UseFixed(instr->value(),
rax);
2338 LStoreNamedGeneric* result =
2339 new(zone()) LStoreNamedGeneric(context,
object, value);
2340 return MarkAsCall(result, instr);
2344 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2345 LOperand* context = UseFixed(instr->context(),
rsi);
2346 LOperand* left = UseFixed(instr->left(),
rdx);
2347 LOperand* right = UseFixed(instr->right(),
rax);
2349 DefineFixed(
new(zone()) LStringAdd(context, left, right),
rax), instr);
2353 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2354 LOperand*
string = UseTempRegister(instr->string());
2355 LOperand* index = UseTempRegister(instr->index());
2356 LOperand* context = UseAny(instr->context());
2357 LStringCharCodeAt* result =
2358 new(zone()) LStringCharCodeAt(context,
string, index);
2359 return AssignPointerMap(DefineAsRegister(result));
2363 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2364 LOperand* char_code = UseRegister(instr->value());
2365 LOperand* context = UseAny(instr->context());
2366 LStringCharFromCode* result =
2367 new(zone()) LStringCharFromCode(context, char_code);
2368 return AssignPointerMap(DefineAsRegister(result));
2372 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
2373 info()->MarkAsDeferredCalling();
2374 LOperand* context = UseAny(instr->context());
2375 LOperand*
size = instr->size()->IsConstant()
2376 ? UseConstant(instr->size())
2377 : UseTempRegister(instr->size());
2378 LOperand* temp = TempRegister();
2379 LAllocate* result =
new(zone()) LAllocate(context, size, temp);
2380 return AssignPointerMap(DefineAsRegister(result));
2384 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2385 LOperand* context = UseFixed(instr->context(),
rsi);
2386 LRegExpLiteral* result =
new(zone()) LRegExpLiteral(context);
2387 return MarkAsCall(DefineFixed(result,
rax), instr);
2391 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2392 LOperand* context = UseFixed(instr->context(),
rsi);
2393 LFunctionLiteral* result =
new(zone()) LFunctionLiteral(context);
2394 return MarkAsCall(DefineFixed(result,
rax), instr);
2398 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2399 ASSERT(argument_count_ == 0);
2400 allocator_->MarkAsOsrEntry();
2401 current_block_->last_environment()->set_ast_id(instr->ast_id());
2402 return AssignEnvironment(
new(zone()) LOsrEntry);
2406 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2407 LParameter* result =
new(zone()) LParameter;
2408 if (instr->kind() == HParameter::STACK_PARAMETER) {
2409 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2410 return DefineAsSpilled(result, spill_index);
2413 CodeStubInterfaceDescriptor* descriptor =
2414 info()->code_stub()->GetInterfaceDescriptor(
info()->isolate());
2415 int index =
static_cast<int>(instr->index());
2416 Register reg = descriptor->GetParameterRegister(index);
2417 return DefineFixed(result, reg);
2422 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2425 int env_index = instr->index();
2426 int spill_index = 0;
2427 if (instr->environment()->is_parameter_index(env_index)) {
2428 spill_index = chunk()->GetParameterStackSlot(env_index);
2430 spill_index = env_index - instr->environment()->first_local_index();
2432 Abort(kTooManySpillSlotsNeededForOSR);
2436 return DefineAsSpilled(
new(zone()) LUnknownOSRValue, spill_index);
2440 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2441 LOperand* context = UseFixed(instr->context(),
rsi);
2442 LCallStub* result =
new(zone()) LCallStub(context);
2443 return MarkAsCall(DefineFixed(result,
rax), instr);
2447 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2456 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
2457 instr->ReplayEnvironment(current_block_->last_environment());
2464 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2465 info()->MarkAsRequiresFrame();
2466 LOperand* args = UseRegister(instr->arguments());
2469 if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
2470 length = UseRegisterOrConstant(instr->length());
2471 index = UseOrConstant(instr->index());
2473 length = UseTempRegister(instr->length());
2474 index = Use(instr->index());
2476 return DefineAsRegister(
new(zone()) LAccessArgumentsAt(args, length, index));
2480 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2481 LOperand*
object = UseFixed(instr->value(),
rax);
2482 LToFastProperties* result =
new(zone()) LToFastProperties(
object);
2483 return MarkAsCall(DefineFixed(result,
rax), instr);
2487 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2488 LOperand* context = UseFixed(instr->context(),
rsi);
2489 LOperand* value = UseAtStart(instr->value());
2490 LTypeof* result =
new(zone()) LTypeof(context, value);
2491 return MarkAsCall(DefineFixed(result,
rax), instr);
2495 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2496 LInstruction* goto_instr = CheckElideControlInstruction(instr);
2497 if (goto_instr !=
NULL)
return goto_instr;
2499 return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
2503 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2504 HIsConstructCallAndBranch* instr) {
2505 return new(zone()) LIsConstructCallAndBranch(TempRegister());
2509 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2510 instr->ReplayEnvironment(current_block_->last_environment());
2515 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2516 info()->MarkAsDeferredCalling();
2517 if (instr->is_function_entry()) {
2518 LOperand* context = UseFixed(instr->context(),
rsi);
2519 return MarkAsCall(
new(zone()) LStackCheck(context), instr);
2521 ASSERT(instr->is_backwards_branch());
2522 LOperand* context = UseAny(instr->context());
2523 return AssignEnvironment(
2524 AssignPointerMap(
new(zone()) LStackCheck(context)));
2529 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2530 HEnvironment* outer = current_block_->last_environment();
2531 HConstant* undefined = graph()->GetConstantUndefined();
2532 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2533 instr->arguments_count(),
2536 instr->inlining_kind());
2538 if (instr->arguments_var() !=
NULL && instr->arguments_object()->IsLinked()) {
2539 inner->Bind(instr->arguments_var(), instr->arguments_object());
2541 inner->set_entry(instr);
2542 current_block_->UpdateEnvironment(inner);
2543 chunk_->AddInlinedClosure(instr->closure());
2548 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2549 LInstruction* pop =
NULL;
2551 HEnvironment* env = current_block_->last_environment();
2553 if (env->entry()->arguments_pushed()) {
2554 int argument_count = env->arguments_environment()->parameter_count();
2555 pop =
new(zone()) LDrop(argument_count);
2556 ASSERT(instr->argument_delta() == -argument_count);
2559 HEnvironment* outer = current_block_->last_environment()->
2560 DiscardInlined(
false);
2561 current_block_->UpdateEnvironment(outer);
2567 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2568 LOperand* context = UseFixed(instr->context(),
rsi);
2569 LOperand*
object = UseFixed(instr->enumerable(),
rax);
2570 LForInPrepareMap* result =
new(zone()) LForInPrepareMap(context,
object);
2571 return MarkAsCall(DefineFixed(result,
rax), instr, CAN_DEOPTIMIZE_EAGERLY);
2575 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2576 LOperand* map = UseRegister(instr->map());
2577 return AssignEnvironment(DefineAsRegister(
2578 new(zone()) LForInCacheArray(map)));
2582 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2583 LOperand* value = UseRegisterAtStart(instr->value());
2584 LOperand* map = UseRegisterAtStart(instr->map());
2585 return AssignEnvironment(
new(zone()) LCheckMapValue(value, map));
2589 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2590 LOperand*
object = UseRegister(instr->object());
2591 LOperand* index = UseTempRegister(instr->index());
2592 return DefineSameAsFirst(
new(zone()) LLoadFieldByIndex(
object, index));
2598 #endif // V8_TARGET_ARCH_X64
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
#define DEFINE_COMPILE(type)
static LUnallocated * cast(LOperand *op)
friend class TempIterator
const char * ToCString(const v8::String::Utf8Value &value)
void PrintDataTo(StringStream *stream) V8_OVERRIDE
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf map
virtual void PrintDataTo(StringStream *stream) V8_OVERRIDE
static String * cast(Object *obj)
virtual void PrintOutputOperandTo(StringStream *stream)
LEnvironment * environment() const
#define ASSERT(condition)
virtual const char * Mnemonic() const =0
virtual void PrintDataTo(StringStream *stream)
bool IsSimpleMapChangeTransition(ElementsKind from_kind, ElementsKind to_kind)
#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
virtual LOperand * result() const =0
static const int kMaxFixedSlotIndex
uint32_t additional_index() const
virtual bool HasResult() const =0
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
static const char * String(Value tok)
bool HasEnvironment() const
static int ToAllocationIndex(Register reg)
uint32_t additional_index() const
virtual void PrintTo(StringStream *stream)
LPointerMap * pointer_map() const
static int ToAllocationIndex(XMMRegister reg)
const char * ElementsKindToString(ElementsKind kind)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
void PrintDataTo(StringStream *stream) V8_OVERRIDE
virtual bool MustSignExtendResult(LPlatformChunk *chunk) const V8_FINAL V8_OVERRIDE
bool IsDoubleOrFloatElementsKind(ElementsKind kind)
bool HasPointerMap() const
static Representation Tagged()
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV 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 expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
static HValue * cast(HValue *value)
void PrintTo(StringStream *stream)