37 #define DEFINE_COMPILE(type) \
38 void L##type::CompileToNative(LCodeGen* generator) { \
39 generator->Do##type(this); \
46 register_spills_[i] =
NULL;
49 double_register_spills_[i] =
NULL;
55 LOperand* spill_operand) {
56 ASSERT(spill_operand->IsStackSlot());
57 ASSERT(register_spills_[allocation_index] ==
NULL);
58 register_spills_[allocation_index] = spill_operand;
63 void LInstruction::VerifyCall() {
71 for (UseIterator it(
this); !it.Done(); it.Advance()) {
73 ASSERT(operand->HasFixedPolicy() ||
74 operand->IsUsedAtStart());
78 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
85 LOperand* spill_operand) {
86 ASSERT(spill_operand->IsDoubleStackSlot());
87 ASSERT(double_register_spills_[allocation_index] ==
NULL);
88 double_register_spills_[allocation_index] = spill_operand;
93 stream->Add(
"%s ", this->
Mnemonic());
113 for (
int i = 0; i < InputCount(); i++) {
114 if (i > 0) stream->Add(
" ");
129 stream->Add(
" Dead block replaced with B%d", rep->block_id());
135 for (
int i = 0; i < 4; i++) {
136 if (parallel_moves_[i] !=
NULL && !parallel_moves_[i]->
IsRedundant()) {
146 for (
int i = 0; i < 4; i++) {
148 if (parallel_moves_[i] !=
NULL) {
162 case Token::MOD:
return "mod-d";
175 case Token::MOD:
return "mod-t";
177 case Token::BIT_AND:
return "bit-and-t";
178 case Token::BIT_OR:
return "bit-or-t";
179 case Token::BIT_XOR:
return "bit-xor-t";
180 case Token::SHL:
return "sll-t";
181 case Token::SAR:
return "sra-t";
182 case Token::SHR:
return "srl-t";
220 stream->Add(
"if is_object(");
227 stream->Add(
"if is_string(");
234 stream->Add(
"if is_smi(");
241 stream->Add(
"if is_undetectable(");
248 stream->Add(
"if string_compare(");
256 stream->Add(
"if has_instance_type(");
263 stream->Add(
"if has_cached_array_index(");
270 stream->Add(
"if class_of_test(");
272 stream->Add(
", \"%o\") then B%d else B%d",
273 *hydrogen()->class_name(),
280 stream->Add(
"if typeof ");
282 stream->Add(
" == \"%s\" then B%d else B%d",
289 stream->Add(
"#%d / ",
arity());
294 stream->Add(
"/%s ", hydrogen()->OpName());
315 stream->Add(
" #%d / ",
arity());
320 stream->Add(
"[a2] #%d / ",
arity());
325 SmartArrayPointer<char> name_string =
name()->ToCString();
326 stream->Add(
"%s #%d / ", *name_string,
arity());
331 SmartArrayPointer<char> name_string =
name()->ToCString();
332 stream->Add(
"%s #%d / ", *name_string,
arity());
337 stream->Add(
"#%d / ",
arity());
344 stream->Add(
" #%d / ",
arity());
350 stream->Add(
" length ");
352 stream->Add(
" index ");
379 stream->Add(
"] <- ");
388 stream->Add(
"] <- ");
397 stream->Add(
"] <- ");
425 LPlatformChunk* LChunkBuilder::Build() {
427 chunk_ =
new(zone()) LPlatformChunk(info(), graph());
428 HPhase phase(
"L_Building chunk", chunk_);
430 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
431 for (
int i = 0; i < blocks->length(); i++) {
432 HBasicBlock* next =
NULL;
433 if (i < blocks->length() - 1) next = blocks->at(i + 1);
434 DoBasicBlock(blocks->at(i), next);
435 if (is_aborted())
return NULL;
442 void LCodeGen::Abort(
const char* reason) {
443 info()->set_bailout_reason(reason);
448 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
460 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
461 return Use(value, ToUnallocated(fixed_register));
465 LOperand* LChunkBuilder::UseFixedDouble(HValue* value,
DoubleRegister reg) {
466 return Use(value, ToUnallocated(reg));
470 LOperand* LChunkBuilder::UseRegister(HValue* value) {
475 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
482 LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
487 LOperand* LChunkBuilder::Use(HValue* value) {
492 LOperand* LChunkBuilder::UseAtStart(HValue* value) {
498 LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
499 return value->IsConstant()
505 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
506 return value->IsConstant()
512 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
513 return value->IsConstant()
515 : UseRegister(value);
519 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
520 return value->IsConstant()
522 : UseRegisterAtStart(value);
526 LOperand* LChunkBuilder::UseAny(HValue* value) {
527 return value->IsConstant()
533 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
534 if (value->EmitAtUses()) {
536 VisitInstruction(instr);
538 operand->set_virtual_register(value->id());
543 template<
int I,
int T>
544 LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
545 LUnallocated* result) {
546 result->set_virtual_register(current_instruction_->id());
547 instr->set_result(result);
552 template<
int I,
int T>
553 LInstruction* LChunkBuilder::DefineAsRegister(
554 LTemplateInstruction<1, I, T>* instr) {
560 template<
int I,
int T>
561 LInstruction* LChunkBuilder::DefineAsSpilled(
562 LTemplateInstruction<1, I, T>* instr,
int index) {
568 template<
int I,
int T>
569 LInstruction* LChunkBuilder::DefineSameAsFirst(
570 LTemplateInstruction<1, I, T>* instr) {
576 template<
int I,
int T>
577 LInstruction* LChunkBuilder::DefineFixed(
578 LTemplateInstruction<1, I, T>* instr, Register reg) {
579 return Define(instr, ToUnallocated(reg));
583 template<
int I,
int T>
584 LInstruction* LChunkBuilder::DefineFixedDouble(
586 return Define(instr, ToUnallocated(reg));
590 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
591 HEnvironment* hydrogen_env = current_block_->last_environment();
592 int argument_index_accumulator = 0;
593 instr->set_environment(CreateEnvironment(hydrogen_env,
594 &argument_index_accumulator));
599 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
600 HInstruction* hinstr,
601 CanDeoptimize can_deoptimize) {
606 instr = AssignPointerMap(instr);
608 if (hinstr->HasObservableSideEffects()) {
609 ASSERT(hinstr->next()->IsSimulate());
611 ASSERT(instruction_pending_deoptimization_environment_ ==
NULL);
612 ASSERT(pending_deoptimization_ast_id_.IsNone());
613 instruction_pending_deoptimization_environment_ = instr;
614 pending_deoptimization_ast_id_ = sim->ast_id();
621 bool needs_environment =
622 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
623 !hinstr->HasObservableSideEffects();
624 if (needs_environment && !instr->HasEnvironment()) {
625 instr = AssignEnvironment(instr);
632 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
633 ASSERT(!instr->HasPointerMap());
634 instr->set_pointer_map(
new(zone()) LPointerMap(position_, zone()));
639 LUnallocated* LChunkBuilder::TempRegister() {
640 LUnallocated* operand =
642 operand->set_virtual_register(allocator_->GetVirtualRegister());
643 if (!allocator_->AllocationOk()) Abort(
"Not enough virtual registers.");
648 LOperand* LChunkBuilder::FixedTemp(Register reg) {
649 LUnallocated* operand = ToUnallocated(reg);
650 ASSERT(operand->HasFixedPolicy());
656 LUnallocated* operand = ToUnallocated(reg);
657 ASSERT(operand->HasFixedPolicy());
662 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
663 return new(zone()) LLabel(instr->block());
667 LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
668 return AssignEnvironment(
new(zone()) LDeoptimize);
672 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
673 return AssignEnvironment(
new(zone()) LDeoptimize);
678 HBitwiseBinaryOperation* instr) {
679 if (instr->representation().IsTagged()) {
680 ASSERT(instr->left()->representation().IsTagged());
681 ASSERT(instr->right()->representation().IsTagged());
683 LOperand* left = UseFixed(instr->left(), a1);
684 LOperand* right = UseFixed(instr->right(), a0);
685 LArithmeticT* result =
new(zone()) LArithmeticT(op, left, right);
686 return MarkAsCall(DefineFixed(result, v0), instr);
689 ASSERT(instr->representation().IsInteger32());
690 ASSERT(instr->left()->representation().IsInteger32());
691 ASSERT(instr->right()->representation().IsInteger32());
692 LOperand* left = UseRegisterAtStart(instr->left());
694 HValue* right_value = instr->right();
695 LOperand* right =
NULL;
696 int constant_value = 0;
697 if (right_value->IsConstant()) {
699 right = chunk_->DefineConstantOperand(constant);
700 constant_value = constant->Integer32Value() & 0x1f;
702 right = UseRegisterAtStart(right_value);
705 bool does_deopt =
false;
707 if (FLAG_opt_safe_uint32_operations) {
712 bool may_deopt = (op == Token::SHR && constant_value == 0);
714 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
723 LInstruction* result =
724 DefineAsRegister(
new(zone()) LShiftI(op, left, right, does_deopt));
725 return does_deopt ? AssignEnvironment(result) : result;
729 LInstruction* LChunkBuilder::DoArithmeticD(
Token::Value op,
730 HArithmeticBinaryOperation* instr) {
731 ASSERT(instr->representation().IsDouble());
732 ASSERT(instr->left()->representation().IsDouble());
733 ASSERT(instr->right()->representation().IsDouble());
735 LOperand* left = UseRegisterAtStart(instr->left());
736 LOperand* right = UseRegisterAtStart(instr->right());
737 LArithmeticD* result =
new(zone()) LArithmeticD(op, left, right);
738 return DefineAsRegister(result);
742 LInstruction* LChunkBuilder::DoArithmeticT(
Token::Value op,
743 HArithmeticBinaryOperation* instr) {
749 HValue* left = instr->left();
750 HValue* right = instr->right();
751 ASSERT(left->representation().IsTagged());
752 ASSERT(right->representation().IsTagged());
753 LOperand* left_operand = UseFixed(left, a1);
754 LOperand* right_operand = UseFixed(right, a0);
755 LArithmeticT* result =
756 new(zone()) LArithmeticT(op, left_operand, right_operand);
757 return MarkAsCall(DefineFixed(result, v0), instr);
761 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
763 current_block_ = block;
764 next_block_ = next_block;
765 if (block->IsStartBlock()) {
766 block->UpdateEnvironment(graph_->start_environment());
768 }
else if (block->predecessors()->length() == 1) {
771 ASSERT(block->phis()->length() == 0);
772 HBasicBlock* pred = block->predecessors()->at(0);
773 HEnvironment* last_environment = pred->last_environment();
776 if (pred->end()->SecondSuccessor() ==
NULL) {
777 ASSERT(pred->end()->FirstSuccessor() == block);
779 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
780 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
781 last_environment = last_environment->Copy();
784 block->UpdateEnvironment(last_environment);
785 ASSERT(pred->argument_count() >= 0);
786 argument_count_ = pred->argument_count();
789 HBasicBlock* pred = block->predecessors()->at(0);
791 HEnvironment* last_environment = pred->last_environment();
792 for (
int i = 0; i < block->phis()->length(); ++i) {
793 HPhi* phi = block->phis()->at(i);
794 last_environment->SetValueAt(phi->merged_index(), phi);
796 for (
int i = 0; i < block->deleted_phis()->length(); ++i) {
797 last_environment->SetValueAt(block->deleted_phis()->at(i),
798 graph_->GetConstantUndefined());
800 block->UpdateEnvironment(last_environment);
802 argument_count_ = pred->argument_count();
804 HInstruction* current = block->first();
805 int start = chunk_->instructions()->length();
806 while (current !=
NULL && !is_aborted()) {
808 if (!current->EmitAtUses()) {
809 VisitInstruction(current);
811 current = current->next();
813 int end = chunk_->instructions()->length() - 1;
815 block->set_first_instruction_index(start);
816 block->set_last_instruction_index(end);
818 block->set_argument_count(argument_count_);
820 current_block_ =
NULL;
824 void LChunkBuilder::VisitInstruction(HInstruction* current) {
825 HInstruction* old_current = current_instruction_;
826 current_instruction_ = current;
827 if (current->has_position()) position_ = current->position();
828 LInstruction* instr = current->CompileToLithium(
this);
831 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
832 instr = AssignPointerMap(instr);
834 if (FLAG_stress_environments && !instr->HasEnvironment()) {
835 instr = AssignEnvironment(instr);
837 instr->set_hydrogen_value(current);
838 chunk_->AddInstruction(instr, current_block_);
840 current_instruction_ = old_current;
844 LEnvironment* LChunkBuilder::CreateEnvironment(
845 HEnvironment* hydrogen_env,
846 int* argument_index_accumulator) {
847 if (hydrogen_env ==
NULL)
return NULL;
849 LEnvironment* outer =
850 CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
851 BailoutId ast_id = hydrogen_env->ast_id();
852 ASSERT(!ast_id.IsNone() ||
854 int value_count = hydrogen_env->length();
855 LEnvironment* result =
new(zone()) LEnvironment(
856 hydrogen_env->closure(),
857 hydrogen_env->frame_type(),
859 hydrogen_env->parameter_count(),
863 hydrogen_env->entry(),
865 int argument_index = *argument_index_accumulator;
866 for (
int i = 0; i < value_count; ++i) {
867 if (hydrogen_env->is_special_index(i))
continue;
869 HValue* value = hydrogen_env->values()->at(i);
871 if (value->IsArgumentsObject()) {
873 }
else if (value->IsPushArgument()) {
874 op =
new(zone()) LArgument(argument_index++);
879 value->representation(),
884 *argument_index_accumulator = argument_index;
891 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
892 return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
896 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
897 HValue* value = instr->value();
898 if (value->EmitAtUses()) {
900 ? instr->FirstSuccessor()
901 : instr->SecondSuccessor();
902 return new(zone()) LGoto(successor->block_id());
905 LBranch* result =
new(zone()) LBranch(UseRegister(value));
909 HType type = value->type();
910 if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean()) {
911 return AssignEnvironment(result);
917 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
918 ASSERT(instr->value()->representation().IsTagged());
919 LOperand* value = UseRegisterAtStart(instr->value());
920 LOperand* temp = TempRegister();
921 return new(zone()) LCmpMapAndBranch(value, temp);
925 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
926 return DefineAsRegister(
927 new(zone()) LArgumentsLength(UseRegister(length->value())));
931 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
932 return DefineAsRegister(
new(zone()) LArgumentsElements);
936 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
937 LInstanceOf* result =
938 new(zone()) LInstanceOf(UseFixed(instr->left(), a0),
939 UseFixed(instr->right(), a1));
940 return MarkAsCall(DefineFixed(result, v0), instr);
944 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
945 HInstanceOfKnownGlobal* instr) {
946 LInstanceOfKnownGlobal* result =
947 new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), a0),
949 return MarkAsCall(DefineFixed(result, v0), instr);
953 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
954 LOperand* receiver = UseRegisterAtStart(instr->receiver());
955 LOperand*
function = UseRegisterAtStart(instr->function());
956 LWrapReceiver* result =
new(zone()) LWrapReceiver(receiver,
function);
957 return AssignEnvironment(DefineSameAsFirst(result));
961 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
962 LOperand*
function = UseFixed(instr->function(), a1);
963 LOperand* receiver = UseFixed(instr->receiver(), a0);
964 LOperand* length = UseFixed(instr->length(), a2);
965 LOperand* elements = UseFixed(instr->elements(), a3);
966 LApplyArguments* result =
new(zone()) LApplyArguments(
function,
970 return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY);
974 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
976 LOperand* argument = Use(instr->argument());
977 return new(zone()) LPushArgument(argument);
981 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
982 return instr->HasNoUses()
984 : DefineAsRegister(
new(zone()) LThisFunction);
988 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
989 return instr->HasNoUses() ?
NULL : DefineAsRegister(
new(zone()) LContext);
993 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
994 LOperand* context = UseRegisterAtStart(instr->value());
995 return DefineAsRegister(
new(zone()) LOuterContext(context));
999 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1000 return MarkAsCall(
new(zone()) LDeclareGlobals, instr);
1004 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
1005 LOperand* context = UseRegisterAtStart(instr->value());
1006 return DefineAsRegister(
new(zone()) LGlobalObject(context));
1010 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
1011 LOperand* global_object = UseRegisterAtStart(instr->value());
1012 return DefineAsRegister(
new(zone()) LGlobalReceiver(global_object));
1016 LInstruction* LChunkBuilder::DoCallConstantFunction(
1017 HCallConstantFunction* instr) {
1018 argument_count_ -= instr->argument_count();
1019 return MarkAsCall(DefineFixed(
new(zone()) LCallConstantFunction, v0), instr);
1023 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1024 LOperand*
function = UseFixed(instr->function(), a1);
1025 argument_count_ -= instr->argument_count();
1026 LInvokeFunction* result =
new(zone()) LInvokeFunction(
function);
1027 return MarkAsCall(DefineFixed(result, v0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1031 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1033 if (op == kMathLog || op == kMathSin || op == kMathCos || op == kMathTan) {
1034 LOperand* input = UseFixedDouble(instr->value(),
f4);
1035 LUnaryMathOperation* result =
new(zone()) LUnaryMathOperation(input,
NULL);
1036 return MarkAsCall(DefineFixedDouble(result,
f4), instr);
1040 LOperand* input = UseFixedDouble(instr->value(),
f8);
1041 LOperand* temp = FixedTemp(
f6);
1042 LUnaryMathOperation* result =
new(zone()) LUnaryMathOperation(input, temp);
1043 return DefineFixedDouble(result,
f4);
1045 LOperand* input = UseRegisterAtStart(instr->value());
1046 LOperand* temp = (op == kMathFloor) ? TempRegister() :
NULL;
1047 LUnaryMathOperation* result =
new(zone()) LUnaryMathOperation(input, temp);
1050 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1052 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1054 return DefineAsRegister(result);
1056 return AssignEnvironment(DefineAsRegister(result));
1065 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1066 ASSERT(instr->key()->representation().IsTagged());
1067 argument_count_ -= instr->argument_count();
1068 LOperand* key = UseFixed(instr->key(), a2);
1069 return MarkAsCall(DefineFixed(
new(zone()) LCallKeyed(key), v0), instr);
1073 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1074 argument_count_ -= instr->argument_count();
1075 return MarkAsCall(DefineFixed(
new(zone()) LCallNamed, v0), instr);
1079 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1080 argument_count_ -= instr->argument_count();
1081 return MarkAsCall(DefineFixed(
new(zone()) LCallGlobal, v0), instr);
1085 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1086 argument_count_ -= instr->argument_count();
1087 return MarkAsCall(DefineFixed(
new(zone()) LCallKnownGlobal, v0), instr);
1091 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1092 LOperand* constructor = UseFixed(instr->constructor(), a1);
1093 argument_count_ -= instr->argument_count();
1094 LCallNew* result =
new(zone()) LCallNew(constructor);
1095 return MarkAsCall(DefineFixed(result, v0), instr);
1099 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1100 LOperand*
function = UseFixed(instr->function(), a1);
1101 argument_count_ -= instr->argument_count();
1102 return MarkAsCall(DefineFixed(
new(zone()) LCallFunction(
function), v0),
1107 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1108 argument_count_ -= instr->argument_count();
1109 return MarkAsCall(DefineFixed(
new(zone()) LCallRuntime, v0), instr);
1113 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1114 return DoShift(Token::SHR, instr);
1118 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1119 return DoShift(Token::SAR, instr);
1123 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1124 return DoShift(Token::SHL, instr);
1128 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1129 if (instr->representation().IsInteger32()) {
1130 ASSERT(instr->left()->representation().IsInteger32());
1131 ASSERT(instr->right()->representation().IsInteger32());
1133 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1134 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1135 return DefineAsRegister(
new(zone()) LBitI(left, right));
1137 ASSERT(instr->representation().IsTagged());
1138 ASSERT(instr->left()->representation().IsTagged());
1139 ASSERT(instr->right()->representation().IsTagged());
1141 LOperand* left = UseFixed(instr->left(), a1);
1142 LOperand* right = UseFixed(instr->right(), a0);
1143 LArithmeticT* result =
new(zone()) LArithmeticT(instr->op(), left, right);
1144 return MarkAsCall(DefineFixed(result, v0), instr);
1149 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1150 ASSERT(instr->value()->representation().IsInteger32());
1151 ASSERT(instr->representation().IsInteger32());
1152 if (instr->HasNoUses())
return NULL;
1153 LOperand* value = UseRegisterAtStart(instr->value());
1154 return DefineAsRegister(
new(zone()) LBitNotI(value));
1158 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1159 if (instr->representation().IsDouble()) {
1161 }
else if (instr->representation().IsInteger32()) {
1167 LOperand* dividend = UseFixed(instr->left(), a0);
1168 LOperand* divisor = UseFixed(instr->right(), a1);
1169 return AssignEnvironment(AssignPointerMap(
1170 DefineFixed(
new(zone()) LDivI(dividend, divisor), v0)));
1177 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1183 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1184 if (instr->representation().IsInteger32()) {
1185 ASSERT(instr->left()->representation().IsInteger32());
1186 ASSERT(instr->right()->representation().IsInteger32());
1189 if (instr->HasPowerOf2Divisor()) {
1191 LOperand* value = UseRegisterAtStart(instr->left());
1192 mod =
new(zone()) LModI(value, UseOrConstant(instr->right()));
1194 LOperand* dividend = UseRegister(instr->left());
1195 LOperand* divisor = UseRegister(instr->right());
1196 mod =
new(zone()) LModI(dividend,
1205 return AssignEnvironment(DefineAsRegister(mod));
1207 return DefineAsRegister(mod);
1209 }
else if (instr->representation().IsTagged()) {
1210 return DoArithmeticT(Token::MOD, instr);
1212 ASSERT(instr->representation().IsDouble());
1216 LOperand* left = UseFixedDouble(instr->left(),
f2);
1217 LOperand* right = UseFixedDouble(instr->right(),
f4);
1218 LArithmeticD* result =
new(zone()) LArithmeticD(Token::MOD, left, right);
1219 return MarkAsCall(DefineFixedDouble(result,
f2), instr);
1224 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1225 if (instr->representation().IsInteger32()) {
1226 ASSERT(instr->left()->representation().IsInteger32());
1227 ASSERT(instr->right()->representation().IsInteger32());
1229 LOperand* right = UseOrConstant(instr->MostConstantOperand());
1230 LOperand* temp =
NULL;
1233 !right->IsConstantOperand())) {
1234 left = UseRegister(instr->LeastConstantOperand());
1235 temp = TempRegister();
1237 left = UseRegisterAtStart(instr->LeastConstantOperand());
1239 LMulI* mul =
new(zone()) LMulI(left, right, temp);
1242 AssignEnvironment(mul);
1244 return DefineAsRegister(mul);
1246 }
else if (instr->representation().IsDouble()) {
1255 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1256 if (instr->representation().IsInteger32()) {
1257 ASSERT(instr->left()->representation().IsInteger32());
1258 ASSERT(instr->right()->representation().IsInteger32());
1259 LOperand* left = UseRegisterAtStart(instr->left());
1260 LOperand* right = UseOrConstantAtStart(instr->right());
1261 LSubI* sub =
new(zone()) LSubI(left, right);
1262 LInstruction* result = DefineAsRegister(sub);
1264 result = AssignEnvironment(result);
1267 }
else if (instr->representation().IsDouble()) {
1275 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1276 if (instr->representation().IsInteger32()) {
1277 ASSERT(instr->left()->representation().IsInteger32());
1278 ASSERT(instr->right()->representation().IsInteger32());
1279 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1280 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1281 LAddI* add =
new(zone()) LAddI(left, right);
1282 LInstruction* result = DefineAsRegister(add);
1284 result = AssignEnvironment(result);
1287 }
else if (instr->representation().IsDouble()) {
1290 ASSERT(instr->representation().IsTagged());
1296 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1297 LOperand* left =
NULL;
1298 LOperand* right =
NULL;
1299 if (instr->representation().IsInteger32()) {
1300 ASSERT(instr->left()->representation().IsInteger32());
1301 ASSERT(instr->right()->representation().IsInteger32());
1302 left = UseRegisterAtStart(instr->LeastConstantOperand());
1303 right = UseOrConstantAtStart(instr->MostConstantOperand());
1305 ASSERT(instr->representation().IsDouble());
1306 ASSERT(instr->left()->representation().IsDouble());
1307 ASSERT(instr->right()->representation().IsDouble());
1308 left = UseRegisterAtStart(instr->left());
1309 right = UseRegisterAtStart(instr->right());
1311 return DefineAsRegister(
new(zone()) LMathMinMax(left, right));
1315 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1316 ASSERT(instr->representation().IsDouble());
1319 Representation exponent_type = instr->right()->representation();
1320 ASSERT(instr->left()->representation().IsDouble());
1321 LOperand* left = UseFixedDouble(instr->left(),
f2);
1322 LOperand* right = exponent_type.IsDouble() ?
1323 UseFixedDouble(instr->right(),
f4) :
1324 UseFixed(instr->right(), a2);
1325 LPower* result =
new(zone()) LPower(left, right);
1326 return MarkAsCall(DefineFixedDouble(result,
f0),
1328 CAN_DEOPTIMIZE_EAGERLY);
1332 LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
1333 ASSERT(instr->representation().IsDouble());
1334 ASSERT(instr->global_object()->representation().IsTagged());
1335 LOperand* global_object = UseFixed(instr->global_object(), a0);
1336 LRandom* result =
new(zone()) LRandom(global_object);
1337 return MarkAsCall(DefineFixedDouble(result,
f0), instr);
1341 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1342 ASSERT(instr->left()->representation().IsTagged());
1343 ASSERT(instr->right()->representation().IsTagged());
1344 LOperand* left = UseFixed(instr->left(), a1);
1345 LOperand* right = UseFixed(instr->right(), a0);
1346 LCmpT* result =
new(zone()) LCmpT(left, right);
1347 return MarkAsCall(DefineFixed(result, v0), instr);
1351 LInstruction* LChunkBuilder::DoCompareIDAndBranch(
1352 HCompareIDAndBranch* instr) {
1353 Representation r = instr->GetInputRepresentation();
1354 if (r.IsInteger32()) {
1355 ASSERT(instr->left()->representation().IsInteger32());
1356 ASSERT(instr->right()->representation().IsInteger32());
1357 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1358 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
1359 return new(zone()) LCmpIDAndBranch(left, right);
1362 ASSERT(instr->left()->representation().IsDouble());
1363 ASSERT(instr->right()->representation().IsDouble());
1364 LOperand* left = UseRegisterAtStart(instr->left());
1365 LOperand* right = UseRegisterAtStart(instr->right());
1366 return new(zone()) LCmpIDAndBranch(left, right);
1371 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1372 HCompareObjectEqAndBranch* instr) {
1373 LOperand* left = UseRegisterAtStart(instr->left());
1374 LOperand* right = UseRegisterAtStart(instr->right());
1375 return new(zone()) LCmpObjectEqAndBranch(left, right);
1379 LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
1380 HCompareConstantEqAndBranch* instr) {
1381 return new(zone()) LCmpConstantEqAndBranch(
1382 UseRegisterAtStart(instr->value()));
1386 LInstruction* LChunkBuilder::DoIsNilAndBranch(HIsNilAndBranch* instr) {
1387 ASSERT(instr->value()->representation().IsTagged());
1388 return new(zone()) LIsNilAndBranch(UseRegisterAtStart(instr->value()));
1392 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1393 ASSERT(instr->value()->representation().IsTagged());
1394 LOperand* temp = TempRegister();
1395 return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()),
1400 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1401 ASSERT(instr->value()->representation().IsTagged());
1402 LOperand* temp = TempRegister();
1403 return new(zone()) LIsStringAndBranch(UseRegisterAtStart(instr->value()),
1408 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1409 ASSERT(instr->value()->representation().IsTagged());
1410 return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1414 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1415 HIsUndetectableAndBranch* instr) {
1416 ASSERT(instr->value()->representation().IsTagged());
1417 return new(zone()) LIsUndetectableAndBranch(
1418 UseRegisterAtStart(instr->value()), TempRegister());
1422 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1423 HStringCompareAndBranch* instr) {
1424 ASSERT(instr->left()->representation().IsTagged());
1425 ASSERT(instr->right()->representation().IsTagged());
1426 LOperand* left = UseFixed(instr->left(), a1);
1427 LOperand* right = UseFixed(instr->right(), a0);
1428 LStringCompareAndBranch* result =
1429 new(zone()) LStringCompareAndBranch(left, right);
1430 return MarkAsCall(result, instr);
1434 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1435 HHasInstanceTypeAndBranch* instr) {
1436 ASSERT(instr->value()->representation().IsTagged());
1437 LOperand* value = UseRegisterAtStart(instr->value());
1438 return new(zone()) LHasInstanceTypeAndBranch(value);
1442 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1443 HGetCachedArrayIndex* instr) {
1444 ASSERT(instr->value()->representation().IsTagged());
1445 LOperand* value = UseRegisterAtStart(instr->value());
1447 return DefineAsRegister(
new(zone()) LGetCachedArrayIndex(value));
1451 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1452 HHasCachedArrayIndexAndBranch* instr) {
1453 ASSERT(instr->value()->representation().IsTagged());
1454 return new(zone()) LHasCachedArrayIndexAndBranch(
1455 UseRegisterAtStart(instr->value()));
1459 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1460 HClassOfTestAndBranch* instr) {
1461 ASSERT(instr->value()->representation().IsTagged());
1462 return new(zone()) LClassOfTestAndBranch(UseRegister(instr->value()),
1467 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1468 LOperand* array = UseRegisterAtStart(instr->value());
1469 return DefineAsRegister(
new(zone()) LJSArrayLength(array));
1473 LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
1474 HFixedArrayBaseLength* instr) {
1475 LOperand* array = UseRegisterAtStart(instr->value());
1476 return DefineAsRegister(
new(zone()) LFixedArrayBaseLength(array));
1480 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1481 LOperand* map = UseRegisterAtStart(instr->value());
1482 return DefineAsRegister(
new(zone()) LMapEnumLength(map));
1486 LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1487 LOperand*
object = UseRegisterAtStart(instr->value());
1488 return DefineAsRegister(
new(zone()) LElementsKind(
object));
1492 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1493 LOperand*
object = UseRegister(instr->value());
1494 LValueOf* result =
new(zone()) LValueOf(
object, TempRegister());
1495 return DefineAsRegister(result);
1499 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1500 LOperand*
object = UseFixed(instr->value(), a0);
1501 LDateField* result =
1502 new(zone()) LDateField(
object, FixedTemp(a1), instr->index());
1503 return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY);
1507 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1508 LOperand* value = UseRegisterOrConstantAtStart(instr->index());
1509 LOperand* length = UseRegister(instr->length());
1510 return AssignEnvironment(
new(zone()) LBoundsCheck(value, length));
1514 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1521 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1522 LOperand* value = UseFixed(instr->value(), a0);
1523 return MarkAsCall(
new(zone()) LThrow(value), instr);
1527 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1532 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1540 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1541 Representation from = instr->from();
1542 Representation to = instr->to();
1543 if (from.IsTagged()) {
1544 if (to.IsDouble()) {
1545 LOperand* value = UseRegister(instr->value());
1546 LNumberUntagD* res =
new(zone()) LNumberUntagD(value);
1547 return AssignEnvironment(DefineAsRegister(res));
1549 ASSERT(to.IsInteger32());
1550 LOperand* value = UseRegisterAtStart(instr->value());
1551 LInstruction* res =
NULL;
1552 if (instr->value()->type().IsSmi()) {
1553 res = DefineAsRegister(
new(zone()) LSmiUntag(value,
false));
1555 LOperand* temp1 = TempRegister();
1556 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
1558 LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(
f22)
1560 res = DefineSameAsFirst(
new(zone()) LTaggedToI(value,
1564 res = AssignEnvironment(res);
1568 }
else if (from.IsDouble()) {
1569 if (to.IsTagged()) {
1570 LOperand* value = UseRegister(instr->value());
1571 LOperand* temp1 = TempRegister();
1572 LOperand* temp2 = TempRegister();
1576 LUnallocated* result_temp = TempRegister();
1577 LNumberTagD* result =
new(zone()) LNumberTagD(value, temp1, temp2);
1578 Define(result, result_temp);
1579 return AssignPointerMap(result);
1581 ASSERT(to.IsInteger32());
1582 LOperand* value = UseRegister(instr->value());
1583 LOperand* temp1 = TempRegister();
1584 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() :
NULL;
1585 LDoubleToI* res =
new(zone()) LDoubleToI(value, temp1, temp2);
1586 return AssignEnvironment(DefineAsRegister(res));
1588 }
else if (from.IsInteger32()) {
1589 if (to.IsTagged()) {
1590 HValue* val = instr->value();
1591 LOperand* value = UseRegisterAtStart(val);
1593 LNumberTagU* result =
new(zone()) LNumberTagU(value);
1594 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1595 }
else if (val->HasRange() && val->range()->IsInSmiRange()) {
1596 return DefineAsRegister(
new(zone()) LSmiTag(value));
1598 LNumberTagI* result =
new(zone()) LNumberTagI(value);
1599 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1604 return DefineAsRegister(
1605 new(zone()) LUint32ToDouble(UseRegister(instr->value())));
1607 return DefineAsRegister(
1608 new(zone()) LInteger32ToDouble(Use(instr->value())));
1617 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1618 LOperand* value = UseRegisterAtStart(instr->value());
1619 return AssignEnvironment(
new(zone()) LCheckNonSmi(value));
1623 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1624 LOperand* value = UseRegisterAtStart(instr->value());
1625 LInstruction* result =
new(zone()) LCheckInstanceType(value);
1626 return AssignEnvironment(result);
1630 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
1631 LOperand* temp1 = TempRegister();
1632 LOperand* temp2 = TempRegister();
1633 LInstruction* result =
new(zone()) LCheckPrototypeMaps(temp1, temp2);
1634 return AssignEnvironment(result);
1638 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1639 LOperand* value = UseRegisterAtStart(instr->value());
1640 return AssignEnvironment(
new(zone()) LCheckSmi(value));
1644 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1645 LOperand* value = UseRegisterAtStart(instr->value());
1646 return AssignEnvironment(
new(zone()) LCheckFunction(value));
1650 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
1651 LOperand* value = UseRegisterAtStart(instr->value());
1652 LInstruction* result =
new(zone()) LCheckMaps(value);
1653 return AssignEnvironment(result);
1657 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1658 HValue* value = instr->value();
1659 Representation input_rep = value->representation();
1660 LOperand* reg = UseRegister(value);
1661 if (input_rep.IsDouble()) {
1663 return DefineAsRegister(
new(zone()) LClampDToUint8(reg, FixedTemp(
f22)));
1664 }
else if (input_rep.IsInteger32()) {
1665 return DefineAsRegister(
new(zone()) LClampIToUint8(reg));
1667 ASSERT(input_rep.IsTagged());
1670 LClampTToUint8* result =
new(zone()) LClampTToUint8(reg, FixedTemp(
f22));
1671 return AssignEnvironment(DefineAsRegister(result));
1676 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1677 return new(zone()) LReturn(UseFixed(instr->value(), v0));
1681 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1682 Representation r = instr->representation();
1683 if (r.IsInteger32()) {
1684 return DefineAsRegister(
new(zone()) LConstantI);
1685 }
else if (r.IsDouble()) {
1686 return DefineAsRegister(
new(zone()) LConstantD);
1687 }
else if (r.IsTagged()) {
1688 return DefineAsRegister(
new(zone()) LConstantT);
1696 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
1697 LLoadGlobalCell* result =
new(zone()) LLoadGlobalCell;
1698 return instr->RequiresHoleCheck()
1699 ? AssignEnvironment(DefineAsRegister(result))
1700 : DefineAsRegister(result);
1704 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1705 LOperand* global_object = UseFixed(instr->global_object(), a0);
1706 LLoadGlobalGeneric* result =
new(zone()) LLoadGlobalGeneric(global_object);
1707 return MarkAsCall(DefineFixed(result, v0), instr);
1711 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
1712 LOperand* value = UseRegister(instr->value());
1715 return instr->RequiresHoleCheck()
1716 ? AssignEnvironment(
new(zone()) LStoreGlobalCell(value, TempRegister()))
1717 : new(zone()) LStoreGlobalCell(value,
NULL);
1721 LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
1722 LOperand* global_object = UseFixed(instr->global_object(), a1);
1723 LOperand* value = UseFixed(instr->value(), a0);
1724 LStoreGlobalGeneric* result =
1725 new(zone()) LStoreGlobalGeneric(global_object, value);
1726 return MarkAsCall(result, instr);
1730 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1731 LOperand* context = UseRegisterAtStart(instr->value());
1732 LInstruction* result =
1733 DefineAsRegister(
new(zone()) LLoadContextSlot(context));
1734 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1738 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
1741 if (instr->NeedsWriteBarrier()) {
1742 context = UseTempRegister(instr->context());
1743 value = UseTempRegister(instr->value());
1745 context = UseRegister(instr->context());
1746 value = UseRegister(instr->value());
1748 LInstruction* result =
new(zone()) LStoreContextSlot(context, value);
1749 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1753 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1754 return DefineAsRegister(
1755 new(zone()) LLoadNamedField(UseRegisterAtStart(instr->object())));
1759 LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
1760 HLoadNamedFieldPolymorphic* instr) {
1761 ASSERT(instr->representation().IsTagged());
1762 if (instr->need_generic()) {
1763 LOperand* obj = UseFixed(instr->object(), a0);
1764 LLoadNamedFieldPolymorphic* result =
1765 new(zone()) LLoadNamedFieldPolymorphic(obj);
1766 return MarkAsCall(DefineFixed(result, v0), instr);
1768 LOperand* obj = UseRegisterAtStart(instr->object());
1769 LLoadNamedFieldPolymorphic* result =
1770 new(zone()) LLoadNamedFieldPolymorphic(obj);
1771 return AssignEnvironment(DefineAsRegister(result));
1776 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1777 LOperand*
object = UseFixed(instr->object(), a0);
1778 LInstruction* result = DefineFixed(
new(zone()) LLoadNamedGeneric(
object), v0);
1779 return MarkAsCall(result, instr);
1783 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1784 HLoadFunctionPrototype* instr) {
1785 return AssignEnvironment(DefineAsRegister(
1786 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
1790 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1791 LOperand* input = UseRegisterAtStart(instr->value());
1792 return DefineAsRegister(
new(zone()) LLoadElements(input));
1796 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
1797 HLoadExternalArrayPointer* instr) {
1798 LOperand* input = UseRegisterAtStart(instr->value());
1799 return DefineAsRegister(
new(zone()) LLoadExternalArrayPointer(input));
1803 LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1804 HLoadKeyedFastElement* instr) {
1805 ASSERT(instr->representation().IsTagged());
1806 ASSERT(instr->key()->representation().IsInteger32() ||
1807 instr->key()->representation().IsTagged());
1808 LOperand* obj = UseRegisterAtStart(instr->object());
1809 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1810 LLoadKeyedFastElement* result =
new(zone()) LLoadKeyedFastElement(obj, key);
1811 if (instr->RequiresHoleCheck()) AssignEnvironment(result);
1812 return DefineAsRegister(result);
1816 LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
1817 HLoadKeyedFastDoubleElement* instr) {
1818 ASSERT(instr->representation().IsDouble());
1819 ASSERT(instr->key()->representation().IsInteger32() ||
1820 instr->key()->representation().IsTagged());
1821 LOperand* elements = UseTempRegister(instr->elements());
1822 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1823 LLoadKeyedFastDoubleElement* result =
1824 new(zone()) LLoadKeyedFastDoubleElement(elements, key);
1825 return AssignEnvironment(DefineAsRegister(result));
1829 LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
1830 HLoadKeyedSpecializedArrayElement* instr) {
1833 (instr->representation().IsInteger32() &&
1836 (instr->representation().IsDouble() &&
1839 ASSERT(instr->key()->representation().IsInteger32() ||
1840 instr->key()->representation().IsTagged());
1841 LOperand* external_pointer = UseRegister(instr->external_pointer());
1842 LOperand* key = UseRegisterOrConstant(instr->key());
1843 LLoadKeyedSpecializedArrayElement* result =
1844 new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
1845 LInstruction* load_instr = DefineAsRegister(result);
1849 AssignEnvironment(load_instr) : load_instr;
1853 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1854 LOperand*
object = UseFixed(instr->object(), a1);
1855 LOperand* key = UseFixed(instr->key(), a0);
1857 LInstruction* result =
1858 DefineFixed(
new(zone()) LLoadKeyedGeneric(
object, key), v0);
1859 return MarkAsCall(result, instr);
1863 LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
1864 HStoreKeyedFastElement* instr) {
1865 bool needs_write_barrier = instr->NeedsWriteBarrier();
1866 ASSERT(instr->value()->representation().IsTagged());
1867 ASSERT(instr->object()->representation().IsTagged());
1868 ASSERT(instr->key()->representation().IsInteger32() ||
1869 instr->key()->representation().IsTagged());
1871 LOperand* obj = UseTempRegister(instr->object());
1872 LOperand* val = needs_write_barrier
1873 ? UseTempRegister(instr->value())
1874 : UseRegisterAtStart(instr->value());
1875 LOperand* key = needs_write_barrier
1876 ? UseTempRegister(instr->key())
1877 : UseRegisterOrConstantAtStart(instr->key());
1878 return new(zone()) LStoreKeyedFastElement(obj, key, val);
1882 LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
1883 HStoreKeyedFastDoubleElement* instr) {
1884 ASSERT(instr->value()->representation().IsDouble());
1885 ASSERT(instr->elements()->representation().IsTagged());
1886 ASSERT(instr->key()->representation().IsInteger32() ||
1887 instr->key()->representation().IsTagged());
1889 LOperand* elements = UseRegisterAtStart(instr->elements());
1890 LOperand* val = UseTempRegister(instr->value());
1891 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1893 return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
1897 LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
1898 HStoreKeyedSpecializedArrayElement* instr) {
1901 (instr->value()->representation().IsInteger32() &&
1904 (instr->value()->representation().IsDouble() &&
1907 ASSERT(instr->external_pointer()->representation().IsExternal());
1908 ASSERT(instr->key()->representation().IsInteger32() ||
1909 instr->key()->representation().IsTagged());
1911 LOperand* external_pointer = UseRegister(instr->external_pointer());
1912 bool val_is_temp_register =
1915 LOperand* val = val_is_temp_register
1916 ? UseTempRegister(instr->value())
1917 : UseRegister(instr->value());
1918 LOperand* key = UseRegisterOrConstant(instr->key());
1920 return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
1926 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
1927 LOperand* obj = UseFixed(instr->object(), a2);
1928 LOperand* key = UseFixed(instr->key(), a1);
1929 LOperand* val = UseFixed(instr->value(), a0);
1931 ASSERT(instr->object()->representation().IsTagged());
1932 ASSERT(instr->key()->representation().IsTagged());
1933 ASSERT(instr->value()->representation().IsTagged());
1935 return MarkAsCall(
new(zone()) LStoreKeyedGeneric(obj, key, val), instr);
1939 LInstruction* LChunkBuilder::DoTransitionElementsKind(
1940 HTransitionElementsKind* instr) {
1941 ElementsKind from_kind = instr->original_map()->elements_kind();
1942 ElementsKind to_kind = instr->transitioned_map()->elements_kind();
1944 LOperand*
object = UseRegister(instr->object());
1945 LOperand* new_map_reg = TempRegister();
1946 LTransitionElementsKind* result =
1947 new(zone()) LTransitionElementsKind(
object, new_map_reg,
NULL);
1948 return DefineSameAsFirst(result);
1950 LOperand*
object = UseFixed(instr->object(), a0);
1951 LOperand* fixed_object_reg = FixedTemp(a2);
1952 LOperand* new_map_reg = FixedTemp(a3);
1953 LTransitionElementsKind* result =
1954 new(zone()) LTransitionElementsKind(
object,
1957 return MarkAsCall(DefineFixed(result, v0), instr);
1962 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
1963 bool needs_write_barrier = instr->NeedsWriteBarrier();
1964 bool needs_write_barrier_for_map = !instr->transition().is_null() &&
1965 instr->NeedsWriteBarrierForMap();
1968 if (needs_write_barrier) {
1969 obj = instr->is_in_object()
1970 ? UseRegister(instr->object())
1971 : UseTempRegister(instr->object());
1973 obj = needs_write_barrier_for_map
1974 ? UseRegister(instr->object())
1975 : UseRegisterAtStart(instr->object());
1978 LOperand* val = needs_write_barrier
1979 ? UseTempRegister(instr->value())
1980 : UseRegister(instr->value());
1983 LOperand* temp = needs_write_barrier_for_map ? TempRegister() :
NULL;
1985 return new(zone()) LStoreNamedField(obj, val, temp);
1989 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
1990 LOperand* obj = UseFixed(instr->object(), a1);
1991 LOperand* val = UseFixed(instr->value(), a0);
1993 LInstruction* result =
new(zone()) LStoreNamedGeneric(obj, val);
1994 return MarkAsCall(result, instr);
1998 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
1999 LOperand* left = UseRegisterAtStart(instr->left());
2000 LOperand* right = UseRegisterAtStart(instr->right());
2001 return MarkAsCall(DefineFixed(
new(zone()) LStringAdd(left, right), v0),
2006 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2007 LOperand*
string = UseTempRegister(instr->string());
2008 LOperand* index = UseTempRegister(instr->index());
2009 LStringCharCodeAt* result =
new(zone()) LStringCharCodeAt(
string, index);
2010 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2014 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2015 LOperand* char_code = UseRegister(instr->value());
2016 LStringCharFromCode* result =
new(zone()) LStringCharFromCode(char_code);
2017 return AssignPointerMap(DefineAsRegister(result));
2021 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
2022 LOperand*
string = UseRegisterAtStart(instr->value());
2023 return DefineAsRegister(
new(zone()) LStringLength(
string));
2027 LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
2028 LAllocateObject* result =
2029 new(zone()) LAllocateObject(TempRegister(), TempRegister());
2030 return AssignPointerMap(DefineAsRegister(result));
2034 LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
2035 return MarkAsCall(DefineFixed(
new(zone()) LFastLiteral, v0), instr);
2039 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
2040 return MarkAsCall(DefineFixed(
new(zone()) LArrayLiteral, v0), instr);
2044 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
2045 return MarkAsCall(DefineFixed(
new(zone()) LObjectLiteral, v0), instr);
2049 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2050 return MarkAsCall(DefineFixed(
new(zone()) LRegExpLiteral, v0), instr);
2054 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2055 return MarkAsCall(DefineFixed(
new(zone()) LFunctionLiteral, v0), instr);
2059 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
2060 LOperand*
object = UseFixed(instr->object(), a0);
2061 LOperand* key = UseFixed(instr->key(), a1);
2062 LDeleteProperty* result =
new(zone()) LDeleteProperty(
object, key);
2063 return MarkAsCall(DefineFixed(result, v0), instr);
2067 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2068 ASSERT(argument_count_ == 0);
2069 allocator_->MarkAsOsrEntry();
2070 current_block_->last_environment()->set_ast_id(instr->ast_id());
2071 return AssignEnvironment(
new(zone()) LOsrEntry);
2075 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2076 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2077 return DefineAsSpilled(
new(zone()) LParameter, spill_index);
2081 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2082 int spill_index = chunk()->GetNextSpillIndex(
false);
2084 Abort(
"Too many spill slots needed for OSR");
2087 return DefineAsSpilled(
new(zone()) LUnknownOSRValue, spill_index);
2091 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2092 argument_count_ -= instr->argument_count();
2093 return MarkAsCall(DefineFixed(
new(zone()) LCallStub, v0), instr);
2097 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2106 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2107 LOperand* args = UseRegister(instr->arguments());
2108 LOperand* length = UseTempRegister(instr->length());
2109 LOperand* index = UseRegister(instr->index());
2110 return DefineAsRegister(
new(zone()) LAccessArgumentsAt(args, length, index));
2114 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2115 LOperand*
object = UseFixed(instr->value(), a0);
2116 LToFastProperties* result =
new(zone()) LToFastProperties(
object);
2117 return MarkAsCall(DefineFixed(result, v0), instr);
2121 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2122 LTypeof* result =
new(zone()) LTypeof(UseFixed(instr->value(), a0));
2123 return MarkAsCall(DefineFixed(result, v0), instr);
2127 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2128 return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
2132 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2133 HIsConstructCallAndBranch* instr) {
2134 return new(zone()) LIsConstructCallAndBranch(TempRegister());
2138 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2139 HEnvironment* env = current_block_->last_environment();
2142 env->set_ast_id(instr->ast_id());
2144 env->Drop(instr->pop_count());
2145 for (
int i = 0; i < instr->values()->length(); ++i) {
2146 HValue* value = instr->values()->at(i);
2147 if (instr->HasAssignedIndexAt(i)) {
2148 env->Bind(instr->GetAssignedIndexAt(i), value);
2156 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
2157 LInstruction* result =
new(zone()) LLazyBailout;
2158 result = AssignEnvironment(result);
2161 instruction_pending_deoptimization_environment_->
2162 SetDeferredLazyDeoptimizationEnvironment(result->environment());
2163 instruction_pending_deoptimization_environment_ =
NULL;
2172 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2173 if (instr->is_function_entry()) {
2174 return MarkAsCall(
new(zone()) LStackCheck, instr);
2176 ASSERT(instr->is_backwards_branch());
2177 return AssignEnvironment(AssignPointerMap(
new(zone()) LStackCheck));
2182 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2183 HEnvironment* outer = current_block_->last_environment();
2184 HConstant* undefined = graph()->GetConstantUndefined();
2185 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2186 instr->arguments_count(),
2190 instr->inlining_kind());
2191 if (instr->arguments_var() !=
NULL) {
2192 inner->Bind(instr->arguments_var(), graph()->GetArgumentsObject());
2194 inner->set_entry(instr);
2195 current_block_->UpdateEnvironment(inner);
2196 chunk_->AddInlinedClosure(instr->closure());
2201 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2202 LInstruction* pop =
NULL;
2204 HEnvironment* env = current_block_->last_environment();
2206 if (env->entry()->arguments_pushed()) {
2207 int argument_count = env->arguments_environment()->parameter_count();
2208 pop =
new(zone()) LDrop(argument_count);
2209 argument_count_ -= argument_count;
2212 HEnvironment* outer = current_block_->last_environment()->
2213 DiscardInlined(
false);
2214 current_block_->UpdateEnvironment(outer);
2220 LInstruction* LChunkBuilder::DoIn(HIn* instr) {
2221 LOperand* key = UseRegisterAtStart(instr->key());
2222 LOperand*
object = UseRegisterAtStart(instr->object());
2223 LIn* result =
new(zone()) LIn(key,
object);
2224 return MarkAsCall(DefineFixed(result, v0), instr);
2228 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2229 LOperand*
object = UseFixed(instr->enumerable(), a0);
2230 LForInPrepareMap* result =
new(zone()) LForInPrepareMap(
object);
2231 return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY);
2235 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2236 LOperand* map = UseRegister(instr->map());
2237 return AssignEnvironment(DefineAsRegister(
new(zone()) LForInCacheArray(map)));
2241 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2242 LOperand* value = UseRegisterAtStart(instr->value());
2243 LOperand* map = UseRegisterAtStart(instr->map());
2244 return AssignEnvironment(
new(zone()) LCheckMapValue(value, map));
2248 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2249 LOperand*
object = UseRegister(instr->object());
2250 LOperand* index = UseRegister(instr->index());
2251 return DefineAsRegister(
new(zone()) LLoadFieldByIndex(
object, index));
static LUnallocated * cast(LOperand *op)
friend class TempIterator
Handle< Map > transitioned_map()
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
Handle< Object > name() const
const char * ToCString(const v8::String::Utf8Value &value)
static String * cast(Object *obj)
virtual void PrintOutputOperandTo(StringStream *stream)
void MarkSpilledDoubleRegister(int allocation_index, LOperand *spill_operand)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
LLabel(HBasicBlock *block)
Handle< String > name() const
static const int kNumAllocatableRegisters
Handle< Object > name() const
LEnvironment * environment() const
#define ASSERT(condition)
virtual const char * Mnemonic() const =0
virtual void PrintDataTo(StringStream *stream)
void PrintTo(StringStream *stream)
bool IsSimpleMapChangeTransition(ElementsKind from_kind, ElementsKind to_kind)
#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
Representation representation() const
EqualityKind kind() const
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
virtual bool HasResult() const =0
virtual void PrintDataTo(StringStream *stream)
DwVfpRegister DoubleRegister
void PrintTo(StringStream *stream)
#define DEFINE_COMPILE(type)
LLabel * replacement() const
virtual const char * Mnemonic() const
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
void MarkSpilledRegister(int allocation_index, LOperand *spill_operand)
static const char * String(Value tok)
static LDoubleStackSlot * Create(int index, Zone *zone)
virtual void PrintDataTo(StringStream *stream)
bool HasEnvironment() const
virtual void PrintDataTo(StringStream *stream)
virtual LOperand * result()=0
virtual void PrintDataTo(StringStream *stream)
static int ToAllocationIndex(Register reg)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
static LStackSlot * Create(int index, Zone *zone)
virtual void PrintDataTo(StringStream *stream)
static const int kMaxFixedIndex
LPointerMap * pointer_map() const
virtual void PrintDataTo(StringStream *stream)
virtual DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,"string-compare-and-branch") Token void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
void PrintDataTo(StringStream *stream) const
virtual const char * Mnemonic() const
static int ToAllocationIndex(DwVfpRegister reg)
static const int kNumAllocatableRegisters
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
Handle< String > name() const
virtual void PrintDataTo(StringStream *stream)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit 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 SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available 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 MIPS FPU instructions if NULL
bool HasPointerMap() const
virtual void PrintDataTo(StringStream *stream)
static HValue * cast(HValue *value)
Handle< String > type_literal()
void PrintTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
Handle< Map > original_map()
virtual void PrintDataTo(StringStream *stream)