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;
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()) {
78 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
86 ASSERT(spill_operand->IsDoubleStackSlot());
87 ASSERT(double_register_spills_[allocation_index] ==
NULL);
88 double_register_spills_[allocation_index] = spill_operand;
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 "shl-t";
181 case Token::SAR:
return "sar-t";
182 case Token::SHR:
return "shr-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",
294 stream->
Add(
"/%s ", hydrogen()->OpName());
320 stream->
Add(
"[r2] #%d / ",
arity());
326 stream->
Add(
"%s #%d / ", *name_string,
arity());
332 stream->
Add(
"%s #%d / ", *name_string,
arity());
350 stream->
Add(
" length ");
352 stream->
Add(
" index ");
379 stream->
Add(
"] <- ");
388 stream->Add(
"] <- ");
397 stream->
Add(
"] <- ");
428 HPhase phase(
"L_Building chunk", chunk_);
431 for (
int i = 0; i < blocks->length(); i++) {
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 LChunkBuilder::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(),
r1);
684 LOperand* right = UseFixed(instr->right(),
r0);
685 LArithmeticT* result =
new(zone()) LArithmeticT(op, left, right);
686 return MarkAsCall(DefineFixed(result,
r0), 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);
707 bool does_deopt =
false;
708 if (op == Token::SHR && constant_value == 0) {
709 if (FLAG_opt_safe_uint32_operations) {
712 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
721 LInstruction* result =
722 DefineAsRegister(
new(zone()) LShiftI(op, left, right, does_deopt));
723 return does_deopt ? AssignEnvironment(result) : result;
727 LInstruction* LChunkBuilder::DoArithmeticD(
Token::Value op,
728 HArithmeticBinaryOperation* instr) {
729 ASSERT(instr->representation().IsDouble());
730 ASSERT(instr->left()->representation().IsDouble());
731 ASSERT(instr->right()->representation().IsDouble());
733 LOperand* left = UseRegisterAtStart(instr->left());
734 LOperand* right = UseRegisterAtStart(instr->right());
735 LArithmeticD* result =
new(zone()) LArithmeticD(op, left, right);
736 return DefineAsRegister(result);
740 LInstruction* LChunkBuilder::DoArithmeticT(
Token::Value op,
741 HArithmeticBinaryOperation* instr) {
747 HValue* left = instr->left();
748 HValue* right = instr->right();
749 ASSERT(left->representation().IsTagged());
750 ASSERT(right->representation().IsTagged());
751 LOperand* left_operand = UseFixed(left,
r1);
752 LOperand* right_operand = UseFixed(right,
r0);
753 LArithmeticT* result =
754 new(zone()) LArithmeticT(op, left_operand, right_operand);
755 return MarkAsCall(DefineFixed(result,
r0), instr);
759 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
761 current_block_ = block;
762 next_block_ = next_block;
763 if (block->IsStartBlock()) {
764 block->UpdateEnvironment(graph_->start_environment());
766 }
else if (block->predecessors()->length() == 1) {
769 ASSERT(block->phis()->length() == 0);
770 HBasicBlock* pred = block->predecessors()->at(0);
771 HEnvironment* last_environment = pred->last_environment();
774 if (pred->end()->SecondSuccessor() ==
NULL) {
775 ASSERT(pred->end()->FirstSuccessor() == block);
777 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
778 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
779 last_environment = last_environment->Copy();
782 block->UpdateEnvironment(last_environment);
783 ASSERT(pred->argument_count() >= 0);
784 argument_count_ = pred->argument_count();
787 HBasicBlock* pred = block->predecessors()->at(0);
789 HEnvironment* last_environment = pred->last_environment();
790 for (
int i = 0; i < block->phis()->length(); ++i) {
791 HPhi* phi = block->phis()->at(i);
792 last_environment->SetValueAt(phi->merged_index(), phi);
794 for (
int i = 0; i < block->deleted_phis()->length(); ++i) {
795 last_environment->SetValueAt(block->deleted_phis()->at(i),
796 graph_->GetConstantUndefined());
798 block->UpdateEnvironment(last_environment);
800 argument_count_ = pred->argument_count();
802 HInstruction* current = block->first();
803 int start = chunk_->instructions()->length();
804 while (current !=
NULL && !is_aborted()) {
806 if (!current->EmitAtUses()) {
807 VisitInstruction(current);
809 current = current->next();
811 int end = chunk_->instructions()->length() - 1;
813 block->set_first_instruction_index(start);
814 block->set_last_instruction_index(end);
816 block->set_argument_count(argument_count_);
818 current_block_ =
NULL;
822 void LChunkBuilder::VisitInstruction(HInstruction* current) {
823 HInstruction* old_current = current_instruction_;
824 current_instruction_ = current;
825 if (current->has_position()) position_ = current->position();
826 LInstruction* instr = current->CompileToLithium(
this);
829 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
830 instr = AssignPointerMap(instr);
832 if (FLAG_stress_environments && !instr->HasEnvironment()) {
833 instr = AssignEnvironment(instr);
835 instr->set_hydrogen_value(current);
836 chunk_->AddInstruction(instr, current_block_);
838 current_instruction_ = old_current;
842 LEnvironment* LChunkBuilder::CreateEnvironment(
843 HEnvironment* hydrogen_env,
844 int* argument_index_accumulator) {
845 if (hydrogen_env ==
NULL)
return NULL;
847 LEnvironment* outer =
848 CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
849 BailoutId ast_id = hydrogen_env->ast_id();
850 ASSERT(!ast_id.IsNone() ||
852 int value_count = hydrogen_env->length();
853 LEnvironment* result =
new(zone()) LEnvironment(
854 hydrogen_env->closure(),
855 hydrogen_env->frame_type(),
857 hydrogen_env->parameter_count(),
861 hydrogen_env->entry(),
863 int argument_index = *argument_index_accumulator;
864 for (
int i = 0; i < value_count; ++i) {
865 if (hydrogen_env->is_special_index(i))
continue;
867 HValue* value = hydrogen_env->values()->at(i);
869 if (value->IsArgumentsObject()) {
871 }
else if (value->IsPushArgument()) {
872 op =
new(zone()) LArgument(argument_index++);
877 value->representation(),
882 *argument_index_accumulator = argument_index;
889 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
890 return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
894 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
895 HValue* value = instr->value();
896 if (value->EmitAtUses()) {
898 ? instr->FirstSuccessor()
899 : instr->SecondSuccessor();
900 return new(zone()) LGoto(successor->block_id());
903 LBranch* result =
new(zone()) LBranch(UseRegister(value));
907 HType type = value->type();
908 if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean()) {
909 return AssignEnvironment(result);
916 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
917 ASSERT(instr->value()->representation().IsTagged());
918 LOperand* value = UseRegisterAtStart(instr->value());
919 LOperand* temp = TempRegister();
920 return new(zone()) LCmpMapAndBranch(value, temp);
924 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) {
925 LOperand* value = UseRegister(instr->value());
926 return DefineAsRegister(
new(zone()) LArgumentsLength(value));
930 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
931 return DefineAsRegister(
new(zone()) LArgumentsElements);
935 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
936 LInstanceOf* result =
937 new(zone()) LInstanceOf(UseFixed(instr->left(),
r0),
938 UseFixed(instr->right(),
r1));
939 return MarkAsCall(DefineFixed(result,
r0), instr);
943 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
944 HInstanceOfKnownGlobal* instr) {
945 LInstanceOfKnownGlobal* result =
946 new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(),
r0),
948 return MarkAsCall(DefineFixed(result,
r0), instr);
952 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
953 LOperand* receiver = UseRegisterAtStart(instr->receiver());
954 LOperand*
function = UseRegisterAtStart(instr->function());
955 LWrapReceiver* result =
new(zone()) LWrapReceiver(receiver,
function);
956 return AssignEnvironment(DefineSameAsFirst(result));
960 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
961 LOperand*
function = UseFixed(instr->function(),
r1);
962 LOperand* receiver = UseFixed(instr->receiver(),
r0);
963 LOperand* length = UseFixed(instr->length(),
r2);
964 LOperand* elements = UseFixed(instr->elements(),
r3);
965 LApplyArguments* result =
new(zone()) LApplyArguments(
function,
969 return MarkAsCall(DefineFixed(result,
r0), instr, CAN_DEOPTIMIZE_EAGERLY);
973 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
975 LOperand* argument = Use(instr->argument());
976 return new(zone()) LPushArgument(argument);
980 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
981 return instr->HasNoUses()
983 : DefineAsRegister(
new(zone()) LThisFunction);
987 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
988 return instr->HasNoUses() ?
NULL : DefineAsRegister(
new(zone()) LContext);
992 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
993 LOperand* context = UseRegisterAtStart(instr->value());
994 return DefineAsRegister(
new(zone()) LOuterContext(context));
998 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
999 return MarkAsCall(
new(zone()) LDeclareGlobals, instr);
1003 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
1004 LOperand* context = UseRegisterAtStart(instr->value());
1005 return DefineAsRegister(
new(zone()) LGlobalObject(context));
1009 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
1010 LOperand* global_object = UseRegisterAtStart(instr->value());
1011 return DefineAsRegister(
new(zone()) LGlobalReceiver(global_object));
1015 LInstruction* LChunkBuilder::DoCallConstantFunction(
1016 HCallConstantFunction* instr) {
1017 argument_count_ -= instr->argument_count();
1018 return MarkAsCall(DefineFixed(
new(zone()) LCallConstantFunction,
r0), instr);
1022 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1023 LOperand*
function = UseFixed(instr->function(),
r1);
1024 argument_count_ -= instr->argument_count();
1025 LInvokeFunction* result =
new(zone()) LInvokeFunction(
function);
1026 return MarkAsCall(DefineFixed(result,
r0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1030 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1032 if (op == kMathLog || op == kMathSin || op == kMathCos || op == kMathTan) {
1033 LOperand* input = UseFixedDouble(instr->value(),
d2);
1034 LUnaryMathOperation* result =
new(zone()) LUnaryMathOperation(input,
NULL);
1035 return MarkAsCall(DefineFixedDouble(result,
d2), instr);
1037 LOperand* input = UseFixedDouble(instr->value(),
d2);
1038 LOperand* temp = FixedTemp(
d3);
1039 LUnaryMathOperation* result =
new(zone()) LUnaryMathOperation(input, temp);
1040 return DefineFixedDouble(result,
d2);
1042 LOperand* input = UseRegisterAtStart(instr->value());
1044 LOperand* temp = (op == kMathRound) ? FixedTemp(
d3) :
NULL;
1045 LUnaryMathOperation* result =
new(zone()) LUnaryMathOperation(input, temp);
1048 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1050 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1052 return DefineAsRegister(result);
1054 return AssignEnvironment(DefineAsRegister(result));
1063 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1064 ASSERT(instr->key()->representation().IsTagged());
1065 argument_count_ -= instr->argument_count();
1066 LOperand* key = UseFixed(instr->key(),
r2);
1067 return MarkAsCall(DefineFixed(
new(zone()) LCallKeyed(key),
r0), instr);
1071 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1072 argument_count_ -= instr->argument_count();
1073 return MarkAsCall(DefineFixed(
new(zone()) LCallNamed,
r0), instr);
1077 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1078 argument_count_ -= instr->argument_count();
1079 return MarkAsCall(DefineFixed(
new(zone()) LCallGlobal,
r0), instr);
1083 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1084 argument_count_ -= instr->argument_count();
1085 return MarkAsCall(DefineFixed(
new(zone()) LCallKnownGlobal,
r0), instr);
1089 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1090 LOperand* constructor = UseFixed(instr->constructor(),
r1);
1091 argument_count_ -= instr->argument_count();
1092 LCallNew* result =
new(zone()) LCallNew(constructor);
1093 return MarkAsCall(DefineFixed(result,
r0), instr);
1097 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1098 LOperand*
function = UseFixed(instr->function(),
r1);
1099 argument_count_ -= instr->argument_count();
1100 return MarkAsCall(DefineFixed(
new(zone()) LCallFunction(
function),
r0),
1105 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1106 argument_count_ -= instr->argument_count();
1107 return MarkAsCall(DefineFixed(
new(zone()) LCallRuntime,
r0), instr);
1111 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1112 return DoShift(Token::SHR, instr);
1116 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1117 return DoShift(Token::SAR, instr);
1121 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1122 return DoShift(Token::SHL, instr);
1126 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1127 if (instr->representation().IsInteger32()) {
1128 ASSERT(instr->left()->representation().IsInteger32());
1129 ASSERT(instr->right()->representation().IsInteger32());
1131 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1132 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1133 return DefineAsRegister(
new(zone()) LBitI(left, right));
1135 ASSERT(instr->representation().IsTagged());
1136 ASSERT(instr->left()->representation().IsTagged());
1137 ASSERT(instr->right()->representation().IsTagged());
1139 LOperand* left = UseFixed(instr->left(),
r1);
1140 LOperand* right = UseFixed(instr->right(),
r0);
1141 LArithmeticT* result =
new(zone()) LArithmeticT(instr->op(), left, right);
1142 return MarkAsCall(DefineFixed(result,
r0), instr);
1147 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1148 ASSERT(instr->value()->representation().IsInteger32());
1149 ASSERT(instr->representation().IsInteger32());
1150 if (instr->HasNoUses())
return NULL;
1151 LOperand* value = UseRegisterAtStart(instr->value());
1152 return DefineAsRegister(
new(zone()) LBitNotI(value));
1156 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1157 if (instr->representation().IsDouble()) {
1159 }
else if (instr->representation().IsInteger32()) {
1165 LOperand* dividend = UseFixed(instr->left(),
r0);
1166 LOperand* divisor = UseFixed(instr->right(),
r1);
1167 return AssignEnvironment(AssignPointerMap(
1168 DefineFixed(
new(zone()) LDivI(dividend, divisor),
r0)));
1175 bool LChunkBuilder::HasMagicNumberForDivisor(
int32_t divisor) {
1176 uint32_t divisor_abs = abs(divisor);
1193 CompilerIntrinsics::CountTrailingZeros(divisor_abs);
1194 DivMagicNumbers magic_numbers =
1202 HValue* LChunkBuilder::SimplifiedDividendForMathFloorOfDiv(HValue* dividend) {
1204 if (dividend->representation().IsInteger32()) {
1207 }
else if (dividend->IsChange() &&
1215 HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
1219 if (divisor->IsConstant() &&
1222 int32_t int32_val = constant_val->Integer32Value();
1223 if (LChunkBuilder::HasMagicNumberForDivisor(int32_val)) {
1225 divisor->block()->zone());
1232 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1233 HValue* right = instr->right();
1234 LOperand* dividend = UseRegister(instr->left());
1235 LOperand* divisor = UseRegisterOrConstant(right);
1236 LOperand* remainder = TempRegister();
1237 ASSERT(right->IsConstant() &&
1240 return AssignEnvironment(DefineAsRegister(
1241 new(zone()) LMathFloorOfDiv(dividend, divisor, remainder)));
1245 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1246 if (instr->representation().IsInteger32()) {
1247 ASSERT(instr->left()->representation().IsInteger32());
1248 ASSERT(instr->right()->representation().IsInteger32());
1251 if (instr->HasPowerOf2Divisor()) {
1253 LOperand* value = UseRegisterAtStart(instr->left());
1254 mod =
new(zone()) LModI(value, UseOrConstant(instr->right()));
1256 LOperand* dividend = UseRegister(instr->left());
1257 LOperand* divisor = UseRegister(instr->right());
1258 mod =
new(zone()) LModI(dividend,
1267 return AssignEnvironment(DefineAsRegister(mod));
1269 return DefineAsRegister(mod);
1271 }
else if (instr->representation().IsTagged()) {
1272 return DoArithmeticT(Token::MOD, instr);
1274 ASSERT(instr->representation().IsDouble());
1278 LOperand* left = UseFixedDouble(instr->left(),
d1);
1279 LOperand* right = UseFixedDouble(instr->right(),
d2);
1280 LArithmeticD* result =
new(zone()) LArithmeticD(Token::MOD, left, right);
1281 return MarkAsCall(DefineFixedDouble(result,
d1), instr);
1286 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1287 if (instr->representation().IsInteger32()) {
1288 ASSERT(instr->left()->representation().IsInteger32());
1289 ASSERT(instr->right()->representation().IsInteger32());
1291 LOperand* right = UseOrConstant(instr->MostConstantOperand());
1292 LOperand* temp =
NULL;
1295 !right->IsConstantOperand())) {
1296 left = UseRegister(instr->LeastConstantOperand());
1297 temp = TempRegister();
1299 left = UseRegisterAtStart(instr->LeastConstantOperand());
1301 LMulI* mul =
new(zone()) LMulI(left, right, temp);
1304 AssignEnvironment(mul);
1306 return DefineAsRegister(mul);
1308 }
else if (instr->representation().IsDouble()) {
1317 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1318 if (instr->representation().IsInteger32()) {
1319 ASSERT(instr->left()->representation().IsInteger32());
1320 ASSERT(instr->right()->representation().IsInteger32());
1321 LOperand* left = UseRegisterAtStart(instr->left());
1322 LOperand* right = UseOrConstantAtStart(instr->right());
1323 LSubI* sub =
new(zone()) LSubI(left, right);
1324 LInstruction* result = DefineAsRegister(sub);
1326 result = AssignEnvironment(result);
1329 }
else if (instr->representation().IsDouble()) {
1337 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1338 if (instr->representation().IsInteger32()) {
1339 ASSERT(instr->left()->representation().IsInteger32());
1340 ASSERT(instr->right()->representation().IsInteger32());
1341 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1342 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1343 LAddI* add =
new(zone()) LAddI(left, right);
1344 LInstruction* result = DefineAsRegister(add);
1346 result = AssignEnvironment(result);
1349 }
else if (instr->representation().IsDouble()) {
1352 ASSERT(instr->representation().IsTagged());
1358 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1359 LOperand* left =
NULL;
1360 LOperand* right =
NULL;
1361 if (instr->representation().IsInteger32()) {
1362 ASSERT(instr->left()->representation().IsInteger32());
1363 ASSERT(instr->right()->representation().IsInteger32());
1364 left = UseRegisterAtStart(instr->LeastConstantOperand());
1365 right = UseOrConstantAtStart(instr->MostConstantOperand());
1367 ASSERT(instr->representation().IsDouble());
1368 ASSERT(instr->left()->representation().IsDouble());
1369 ASSERT(instr->right()->representation().IsDouble());
1370 left = UseRegisterAtStart(instr->left());
1371 right = UseRegisterAtStart(instr->right());
1373 return DefineAsRegister(
new(zone()) LMathMinMax(left, right));
1377 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1378 ASSERT(instr->representation().IsDouble());
1381 Representation exponent_type = instr->right()->representation();
1382 ASSERT(instr->left()->representation().IsDouble());
1383 LOperand* left = UseFixedDouble(instr->left(),
d1);
1384 LOperand* right = exponent_type.IsDouble() ?
1385 UseFixedDouble(instr->right(),
d2) :
1386 UseFixed(instr->right(),
r2);
1387 LPower* result =
new(zone()) LPower(left, right);
1388 return MarkAsCall(DefineFixedDouble(result,
d3),
1390 CAN_DEOPTIMIZE_EAGERLY);
1394 LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
1395 ASSERT(instr->representation().IsDouble());
1396 ASSERT(instr->global_object()->representation().IsTagged());
1397 LOperand* global_object = UseFixed(instr->global_object(),
r0);
1398 LRandom* result =
new(zone()) LRandom(global_object);
1399 return MarkAsCall(DefineFixedDouble(result,
d7), instr);
1403 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1404 ASSERT(instr->left()->representation().IsTagged());
1405 ASSERT(instr->right()->representation().IsTagged());
1406 LOperand* left = UseFixed(instr->left(),
r1);
1407 LOperand* right = UseFixed(instr->right(),
r0);
1408 LCmpT* result =
new(zone()) LCmpT(left, right);
1409 return MarkAsCall(DefineFixed(result,
r0), instr);
1413 LInstruction* LChunkBuilder::DoCompareIDAndBranch(
1414 HCompareIDAndBranch* instr) {
1415 Representation r = instr->GetInputRepresentation();
1416 if (r.IsInteger32()) {
1417 ASSERT(instr->left()->representation().IsInteger32());
1418 ASSERT(instr->right()->representation().IsInteger32());
1419 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1420 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
1421 return new(zone()) LCmpIDAndBranch(left, right);
1424 ASSERT(instr->left()->representation().IsDouble());
1425 ASSERT(instr->right()->representation().IsDouble());
1426 LOperand* left = UseRegisterAtStart(instr->left());
1427 LOperand* right = UseRegisterAtStart(instr->right());
1428 return new(zone()) LCmpIDAndBranch(left, right);
1433 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1434 HCompareObjectEqAndBranch* instr) {
1435 LOperand* left = UseRegisterAtStart(instr->left());
1436 LOperand* right = UseRegisterAtStart(instr->right());
1437 return new(zone()) LCmpObjectEqAndBranch(left, right);
1441 LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
1442 HCompareConstantEqAndBranch* instr) {
1443 LOperand* value = UseRegisterAtStart(instr->value());
1444 return new(zone()) LCmpConstantEqAndBranch(value);
1448 LInstruction* LChunkBuilder::DoIsNilAndBranch(HIsNilAndBranch* instr) {
1449 ASSERT(instr->value()->representation().IsTagged());
1450 return new(zone()) LIsNilAndBranch(UseRegisterAtStart(instr->value()));
1454 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1455 ASSERT(instr->value()->representation().IsTagged());
1456 LOperand* value = UseRegisterAtStart(instr->value());
1457 LOperand* temp = TempRegister();
1458 return new(zone()) LIsObjectAndBranch(value, temp);
1462 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1463 ASSERT(instr->value()->representation().IsTagged());
1464 LOperand* value = UseRegisterAtStart(instr->value());
1465 LOperand* temp = TempRegister();
1466 return new(zone()) LIsStringAndBranch(value, temp);
1470 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1471 ASSERT(instr->value()->representation().IsTagged());
1472 return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1476 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1477 HIsUndetectableAndBranch* instr) {
1478 ASSERT(instr->value()->representation().IsTagged());
1479 LOperand* value = UseRegisterAtStart(instr->value());
1480 return new(zone()) LIsUndetectableAndBranch(value, TempRegister());
1484 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1485 HStringCompareAndBranch* instr) {
1486 ASSERT(instr->left()->representation().IsTagged());
1487 ASSERT(instr->right()->representation().IsTagged());
1488 LOperand* left = UseFixed(instr->left(),
r1);
1489 LOperand* right = UseFixed(instr->right(),
r0);
1490 LStringCompareAndBranch* result =
1491 new(zone()) LStringCompareAndBranch(left, right);
1492 return MarkAsCall(result, instr);
1496 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1497 HHasInstanceTypeAndBranch* instr) {
1498 ASSERT(instr->value()->representation().IsTagged());
1499 LOperand* value = UseRegisterAtStart(instr->value());
1500 return new(zone()) LHasInstanceTypeAndBranch(value);
1504 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1505 HGetCachedArrayIndex* instr) {
1506 ASSERT(instr->value()->representation().IsTagged());
1507 LOperand* value = UseRegisterAtStart(instr->value());
1509 return DefineAsRegister(
new(zone()) LGetCachedArrayIndex(value));
1513 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1514 HHasCachedArrayIndexAndBranch* instr) {
1515 ASSERT(instr->value()->representation().IsTagged());
1516 return new(zone()) LHasCachedArrayIndexAndBranch(
1517 UseRegisterAtStart(instr->value()));
1521 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1522 HClassOfTestAndBranch* instr) {
1523 ASSERT(instr->value()->representation().IsTagged());
1524 LOperand* value = UseRegister(instr->value());
1525 return new(zone()) LClassOfTestAndBranch(value, TempRegister());
1529 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1530 LOperand* array = UseRegisterAtStart(instr->value());
1531 return DefineAsRegister(
new(zone()) LJSArrayLength(array));
1535 LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
1536 HFixedArrayBaseLength* instr) {
1537 LOperand* array = UseRegisterAtStart(instr->value());
1538 return DefineAsRegister(
new(zone()) LFixedArrayBaseLength(array));
1542 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1543 LOperand* map = UseRegisterAtStart(instr->value());
1544 return DefineAsRegister(
new(zone()) LMapEnumLength(map));
1548 LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1549 LOperand*
object = UseRegisterAtStart(instr->value());
1550 return DefineAsRegister(
new(zone()) LElementsKind(
object));
1554 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1555 LOperand*
object = UseRegister(instr->value());
1556 LValueOf* result =
new(zone()) LValueOf(
object, TempRegister());
1557 return DefineAsRegister(result);
1561 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1562 LOperand*
object = UseFixed(instr->value(),
r0);
1563 LDateField* result =
1564 new(zone()) LDateField(
object, FixedTemp(
r1), instr->index());
1565 return MarkAsCall(DefineFixed(result,
r0), instr, CAN_DEOPTIMIZE_EAGERLY);
1569 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1570 LOperand* value = UseRegisterOrConstantAtStart(instr->index());
1571 LOperand* length = UseRegister(instr->length());
1572 return AssignEnvironment(
new(zone()) LBoundsCheck(value, length));
1576 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1583 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1584 LOperand* value = UseFixed(instr->value(),
r0);
1585 return MarkAsCall(
new(zone()) LThrow(value), instr);
1589 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1594 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1602 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1603 Representation from = instr->from();
1604 Representation to = instr->to();
1605 if (from.IsTagged()) {
1606 if (to.IsDouble()) {
1607 LOperand* value = UseRegister(instr->value());
1608 LNumberUntagD* res =
new(zone()) LNumberUntagD(value);
1609 return AssignEnvironment(DefineAsRegister(res));
1611 ASSERT(to.IsInteger32());
1612 LOperand* value = UseRegisterAtStart(instr->value());
1613 LInstruction* res =
NULL;
1614 if (instr->value()->type().IsSmi()) {
1615 res = DefineAsRegister(
new(zone()) LSmiUntag(value,
false));
1617 LOperand* temp1 = TempRegister();
1618 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
1620 LOperand* temp3 = FixedTemp(
d11);
1621 res = DefineSameAsFirst(
new(zone()) LTaggedToI(value,
1625 res = AssignEnvironment(res);
1629 }
else if (from.IsDouble()) {
1630 if (to.IsTagged()) {
1631 LOperand* value = UseRegister(instr->value());
1632 LOperand* temp1 = TempRegister();
1633 LOperand* temp2 = TempRegister();
1637 LUnallocated* result_temp = TempRegister();
1638 LNumberTagD* result =
new(zone()) LNumberTagD(value, temp1, temp2);
1639 Define(result, result_temp);
1640 return AssignPointerMap(result);
1642 ASSERT(to.IsInteger32());
1643 LOperand* value = UseRegister(instr->value());
1644 LOperand* temp1 = TempRegister();
1645 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() :
NULL;
1646 LDoubleToI* res =
new(zone()) LDoubleToI(value, temp1, temp2);
1647 return AssignEnvironment(DefineAsRegister(res));
1649 }
else if (from.IsInteger32()) {
1650 if (to.IsTagged()) {
1651 HValue* val = instr->value();
1652 LOperand* value = UseRegisterAtStart(val);
1654 LNumberTagU* result =
new(zone()) LNumberTagU(value);
1655 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1656 }
else if (val->HasRange() && val->range()->IsInSmiRange()) {
1657 return DefineAsRegister(
new(zone()) LSmiTag(value));
1659 LNumberTagI* result =
new(zone()) LNumberTagI(value);
1660 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1665 return DefineAsRegister(
1666 new(zone()) LUint32ToDouble(UseRegister(instr->value())));
1668 return DefineAsRegister(
1669 new(zone()) LInteger32ToDouble(Use(instr->value())));
1678 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1679 LOperand* value = UseRegisterAtStart(instr->value());
1680 return AssignEnvironment(
new(zone()) LCheckNonSmi(value));
1684 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1685 LOperand* value = UseRegisterAtStart(instr->value());
1686 LInstruction* result =
new(zone()) LCheckInstanceType(value);
1687 return AssignEnvironment(result);
1691 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
1692 LOperand* temp1 = TempRegister();
1693 LOperand* temp2 = TempRegister();
1694 LInstruction* result =
new(zone()) LCheckPrototypeMaps(temp1, temp2);
1695 return AssignEnvironment(result);
1699 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1700 LOperand* value = UseRegisterAtStart(instr->value());
1701 return AssignEnvironment(
new(zone()) LCheckSmi(value));
1705 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1706 LOperand* value = UseRegisterAtStart(instr->value());
1707 return AssignEnvironment(
new(zone()) LCheckFunction(value));
1711 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
1712 LOperand* value = UseRegisterAtStart(instr->value());
1713 LInstruction* result =
new(zone()) LCheckMaps(value);
1714 return AssignEnvironment(result);
1718 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1719 HValue* value = instr->value();
1720 Representation input_rep = value->representation();
1721 LOperand* reg = UseRegister(value);
1722 if (input_rep.IsDouble()) {
1723 return DefineAsRegister(
new(zone()) LClampDToUint8(reg, FixedTemp(
d11)));
1724 }
else if (input_rep.IsInteger32()) {
1725 return DefineAsRegister(
new(zone()) LClampIToUint8(reg));
1727 ASSERT(input_rep.IsTagged());
1730 LClampTToUint8* result =
new(zone()) LClampTToUint8(reg, FixedTemp(
d11));
1731 return AssignEnvironment(DefineAsRegister(result));
1736 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1737 return new(zone()) LReturn(UseFixed(instr->value(),
r0));
1741 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1742 Representation r = instr->representation();
1743 if (r.IsInteger32()) {
1744 return DefineAsRegister(
new(zone()) LConstantI);
1745 }
else if (r.IsDouble()) {
1746 return DefineAsRegister(
new(zone()) LConstantD);
1747 }
else if (r.IsTagged()) {
1748 return DefineAsRegister(
new(zone()) LConstantT);
1756 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
1757 LLoadGlobalCell* result =
new(zone()) LLoadGlobalCell;
1758 return instr->RequiresHoleCheck()
1759 ? AssignEnvironment(DefineAsRegister(result))
1760 : DefineAsRegister(result);
1764 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1765 LOperand* global_object = UseFixed(instr->global_object(),
r0);
1766 LLoadGlobalGeneric* result =
new(zone()) LLoadGlobalGeneric(global_object);
1767 return MarkAsCall(DefineFixed(result,
r0), instr);
1771 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
1772 LOperand* value = UseRegister(instr->value());
1775 return instr->RequiresHoleCheck()
1776 ? AssignEnvironment(
new(zone()) LStoreGlobalCell(value, TempRegister()))
1777 : new(zone()) LStoreGlobalCell(value,
NULL);
1781 LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
1782 LOperand* global_object = UseFixed(instr->global_object(),
r1);
1783 LOperand* value = UseFixed(instr->value(),
r0);
1784 LStoreGlobalGeneric* result =
1785 new(zone()) LStoreGlobalGeneric(global_object, value);
1786 return MarkAsCall(result, instr);
1790 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1791 LOperand* context = UseRegisterAtStart(instr->value());
1792 LInstruction* result =
1793 DefineAsRegister(
new(zone()) LLoadContextSlot(context));
1794 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1798 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
1801 if (instr->NeedsWriteBarrier()) {
1802 context = UseTempRegister(instr->context());
1803 value = UseTempRegister(instr->value());
1805 context = UseRegister(instr->context());
1806 value = UseRegister(instr->value());
1808 LInstruction* result =
new(zone()) LStoreContextSlot(context, value);
1809 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1813 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1814 return DefineAsRegister(
1815 new(zone()) LLoadNamedField(UseRegisterAtStart(instr->object())));
1819 LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
1820 HLoadNamedFieldPolymorphic* instr) {
1821 ASSERT(instr->representation().IsTagged());
1822 if (instr->need_generic()) {
1823 LOperand* obj = UseFixed(instr->object(),
r0);
1824 LLoadNamedFieldPolymorphic* result =
1825 new(zone()) LLoadNamedFieldPolymorphic(obj);
1826 return MarkAsCall(DefineFixed(result,
r0), instr);
1828 LOperand* obj = UseRegisterAtStart(instr->object());
1829 LLoadNamedFieldPolymorphic* result =
1830 new(zone()) LLoadNamedFieldPolymorphic(obj);
1831 return AssignEnvironment(DefineAsRegister(result));
1836 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1837 LOperand*
object = UseFixed(instr->object(),
r0);
1838 LInstruction* result = DefineFixed(
new(zone()) LLoadNamedGeneric(
object),
r0);
1839 return MarkAsCall(result, instr);
1843 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1844 HLoadFunctionPrototype* instr) {
1845 return AssignEnvironment(DefineAsRegister(
1846 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
1850 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1851 LOperand* input = UseRegisterAtStart(instr->value());
1852 return DefineAsRegister(
new(zone()) LLoadElements(input));
1856 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
1857 HLoadExternalArrayPointer* instr) {
1858 LOperand* input = UseRegisterAtStart(instr->value());
1859 return DefineAsRegister(
new(zone()) LLoadExternalArrayPointer(input));
1863 LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1864 HLoadKeyedFastElement* instr) {
1865 ASSERT(instr->representation().IsTagged());
1866 ASSERT(instr->key()->representation().IsInteger32() ||
1867 instr->key()->representation().IsTagged());
1868 LOperand* obj = UseRegisterAtStart(instr->object());
1869 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1870 LLoadKeyedFastElement* result =
new(zone()) LLoadKeyedFastElement(obj, key);
1871 if (instr->RequiresHoleCheck()) AssignEnvironment(result);
1872 return DefineAsRegister(result);
1876 LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
1877 HLoadKeyedFastDoubleElement* instr) {
1878 ASSERT(instr->representation().IsDouble());
1879 ASSERT(instr->key()->representation().IsInteger32() ||
1880 instr->key()->representation().IsTagged());
1881 LOperand* elements = UseTempRegister(instr->elements());
1882 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1883 LLoadKeyedFastDoubleElement* result =
1884 new(zone()) LLoadKeyedFastDoubleElement(elements, key);
1885 return AssignEnvironment(DefineAsRegister(result));
1889 LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
1890 HLoadKeyedSpecializedArrayElement* instr) {
1893 (instr->representation().IsInteger32() &&
1896 (instr->representation().IsDouble() &&
1899 ASSERT(instr->key()->representation().IsInteger32() ||
1900 instr->key()->representation().IsTagged());
1901 LOperand* external_pointer = UseRegister(instr->external_pointer());
1902 LOperand* key = UseRegisterOrConstant(instr->key());
1903 LLoadKeyedSpecializedArrayElement* result =
1904 new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
1905 LInstruction* load_instr = DefineAsRegister(result);
1909 AssignEnvironment(load_instr) : load_instr;
1913 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1914 LOperand*
object = UseFixed(instr->object(),
r1);
1915 LOperand* key = UseFixed(instr->key(),
r0);
1917 LInstruction* result =
1918 DefineFixed(
new(zone()) LLoadKeyedGeneric(
object, key),
r0);
1919 return MarkAsCall(result, instr);
1923 LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
1924 HStoreKeyedFastElement* instr) {
1925 bool needs_write_barrier = instr->NeedsWriteBarrier();
1926 ASSERT(instr->value()->representation().IsTagged());
1927 ASSERT(instr->object()->representation().IsTagged());
1928 ASSERT(instr->key()->representation().IsInteger32() ||
1929 instr->key()->representation().IsTagged());
1931 LOperand* obj = UseTempRegister(instr->object());
1932 LOperand* val = needs_write_barrier
1933 ? UseTempRegister(instr->value())
1934 : UseRegisterAtStart(instr->value());
1935 LOperand* key = needs_write_barrier
1936 ? UseTempRegister(instr->key())
1937 : UseRegisterOrConstantAtStart(instr->key());
1938 return new(zone()) LStoreKeyedFastElement(obj, key, val);
1942 LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
1943 HStoreKeyedFastDoubleElement* instr) {
1944 ASSERT(instr->value()->representation().IsDouble());
1945 ASSERT(instr->elements()->representation().IsTagged());
1946 ASSERT(instr->key()->representation().IsInteger32() ||
1947 instr->key()->representation().IsTagged());
1949 LOperand* elements = UseRegisterAtStart(instr->elements());
1950 LOperand* val = UseTempRegister(instr->value());
1951 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1953 return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
1957 LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
1958 HStoreKeyedSpecializedArrayElement* instr) {
1961 (instr->value()->representation().IsInteger32() &&
1964 (instr->value()->representation().IsDouble() &&
1967 ASSERT(instr->external_pointer()->representation().IsExternal());
1968 ASSERT(instr->key()->representation().IsInteger32() ||
1969 instr->key()->representation().IsTagged());
1971 LOperand* external_pointer = UseRegister(instr->external_pointer());
1972 bool val_is_temp_register =
1975 LOperand* val = val_is_temp_register
1976 ? UseTempRegister(instr->value())
1977 : UseRegister(instr->value());
1978 LOperand* key = UseRegisterOrConstant(instr->key());
1980 return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
1986 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
1987 LOperand* obj = UseFixed(instr->object(),
r2);
1988 LOperand* key = UseFixed(instr->key(),
r1);
1989 LOperand* val = UseFixed(instr->value(),
r0);
1991 ASSERT(instr->object()->representation().IsTagged());
1992 ASSERT(instr->key()->representation().IsTagged());
1993 ASSERT(instr->value()->representation().IsTagged());
1995 return MarkAsCall(
new(zone()) LStoreKeyedGeneric(obj, key, val), instr);
1999 LInstruction* LChunkBuilder::DoTransitionElementsKind(
2000 HTransitionElementsKind* instr) {
2001 ElementsKind from_kind = instr->original_map()->elements_kind();
2002 ElementsKind to_kind = instr->transitioned_map()->elements_kind();
2004 LOperand*
object = UseRegister(instr->object());
2005 LOperand* new_map_reg = TempRegister();
2006 LTransitionElementsKind* result =
2007 new(zone()) LTransitionElementsKind(
object, new_map_reg,
NULL);
2008 return DefineSameAsFirst(result);
2010 LOperand*
object = UseFixed(instr->object(),
r0);
2011 LOperand* fixed_object_reg = FixedTemp(
r2);
2012 LOperand* new_map_reg = FixedTemp(
r3);
2013 LTransitionElementsKind* result =
2014 new(zone()) LTransitionElementsKind(
object,
2017 return MarkAsCall(DefineFixed(result,
r0), instr);
2022 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2023 bool needs_write_barrier = instr->NeedsWriteBarrier();
2024 bool needs_write_barrier_for_map = !instr->transition().is_null() &&
2025 instr->NeedsWriteBarrierForMap();
2028 if (needs_write_barrier) {
2029 obj = instr->is_in_object()
2030 ? UseRegister(instr->object())
2031 : UseTempRegister(instr->object());
2033 obj = needs_write_barrier_for_map
2034 ? UseRegister(instr->object())
2035 : UseRegisterAtStart(instr->object());
2038 LOperand* val = needs_write_barrier
2039 ? UseTempRegister(instr->value())
2040 : UseRegister(instr->value());
2043 LOperand* temp = needs_write_barrier_for_map ? TempRegister() :
NULL;
2045 return new(zone()) LStoreNamedField(obj, val, temp);
2049 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2050 LOperand* obj = UseFixed(instr->object(),
r1);
2051 LOperand* val = UseFixed(instr->value(),
r0);
2053 LInstruction* result =
new(zone()) LStoreNamedGeneric(obj, val);
2054 return MarkAsCall(result, instr);
2058 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2059 LOperand* left = UseRegisterAtStart(instr->left());
2060 LOperand* right = UseRegisterAtStart(instr->right());
2061 return MarkAsCall(DefineFixed(
new(zone()) LStringAdd(left, right),
r0),
2066 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2067 LOperand*
string = UseTempRegister(instr->string());
2068 LOperand* index = UseTempRegister(instr->index());
2069 LStringCharCodeAt* result =
new(zone()) LStringCharCodeAt(
string, index);
2070 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2074 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2075 LOperand* char_code = UseRegister(instr->value());
2076 LStringCharFromCode* result =
new(zone()) LStringCharFromCode(char_code);
2077 return AssignPointerMap(DefineAsRegister(result));
2081 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
2082 LOperand*
string = UseRegisterAtStart(instr->value());
2083 return DefineAsRegister(
new(zone()) LStringLength(
string));
2087 LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
2088 LAllocateObject* result =
2089 new(zone()) LAllocateObject(TempRegister(), TempRegister());
2090 return AssignPointerMap(DefineAsRegister(result));
2094 LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
2095 return MarkAsCall(DefineFixed(
new(zone()) LFastLiteral,
r0), instr);
2099 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
2100 return MarkAsCall(DefineFixed(
new(zone()) LArrayLiteral,
r0), instr);
2104 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
2105 return MarkAsCall(DefineFixed(
new(zone()) LObjectLiteral,
r0), instr);
2109 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2110 return MarkAsCall(DefineFixed(
new(zone()) LRegExpLiteral,
r0), instr);
2114 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2115 return MarkAsCall(DefineFixed(
new(zone()) LFunctionLiteral,
r0), instr);
2119 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
2120 LOperand*
object = UseFixed(instr->object(),
r0);
2121 LOperand* key = UseFixed(instr->key(),
r1);
2122 LDeleteProperty* result =
new(zone()) LDeleteProperty(
object, key);
2123 return MarkAsCall(DefineFixed(result,
r0), instr);
2127 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2128 ASSERT(argument_count_ == 0);
2129 allocator_->MarkAsOsrEntry();
2130 current_block_->last_environment()->set_ast_id(instr->ast_id());
2131 return AssignEnvironment(
new(zone()) LOsrEntry);
2135 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2136 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2137 return DefineAsSpilled(
new(zone()) LParameter, spill_index);
2141 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2142 int spill_index = chunk()->GetNextSpillIndex(
false);
2144 Abort(
"Too many spill slots needed for OSR");
2147 return DefineAsSpilled(
new(zone()) LUnknownOSRValue, spill_index);
2151 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2152 argument_count_ -= instr->argument_count();
2153 return MarkAsCall(DefineFixed(
new(zone()) LCallStub,
r0), instr);
2157 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2166 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2167 LOperand* args = UseRegister(instr->arguments());
2168 LOperand* length = UseTempRegister(instr->length());
2169 LOperand* index = UseRegister(instr->index());
2170 return DefineAsRegister(
new(zone()) LAccessArgumentsAt(args, length, index));
2174 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2175 LOperand*
object = UseFixed(instr->value(),
r0);
2176 LToFastProperties* result =
new(zone()) LToFastProperties(
object);
2177 return MarkAsCall(DefineFixed(result,
r0), instr);
2181 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2182 LTypeof* result =
new(zone()) LTypeof(UseFixed(instr->value(),
r0));
2183 return MarkAsCall(DefineFixed(result,
r0), instr);
2187 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2188 return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
2192 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2193 HIsConstructCallAndBranch* instr) {
2194 return new(zone()) LIsConstructCallAndBranch(TempRegister());
2198 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2199 HEnvironment* env = current_block_->last_environment();
2202 env->set_ast_id(instr->ast_id());
2204 env->Drop(instr->pop_count());
2205 for (
int i = 0; i < instr->values()->length(); ++i) {
2206 HValue* value = instr->values()->at(i);
2207 if (instr->HasAssignedIndexAt(i)) {
2208 env->Bind(instr->GetAssignedIndexAt(i), value);
2216 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
2217 LInstruction* result =
new(zone()) LLazyBailout;
2218 result = AssignEnvironment(result);
2221 instruction_pending_deoptimization_environment_->
2222 SetDeferredLazyDeoptimizationEnvironment(result->environment());
2223 instruction_pending_deoptimization_environment_ =
NULL;
2232 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2233 if (instr->is_function_entry()) {
2234 return MarkAsCall(
new(zone()) LStackCheck, instr);
2236 ASSERT(instr->is_backwards_branch());
2237 return AssignEnvironment(AssignPointerMap(
new(zone()) LStackCheck));
2242 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2243 HEnvironment* outer = current_block_->last_environment();
2244 HConstant* undefined = graph()->GetConstantUndefined();
2245 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2246 instr->arguments_count(),
2250 instr->inlining_kind());
2251 if (instr->arguments_var() !=
NULL) {
2252 inner->Bind(instr->arguments_var(), graph()->GetArgumentsObject());
2254 inner->set_entry(instr);
2255 current_block_->UpdateEnvironment(inner);
2256 chunk_->AddInlinedClosure(instr->closure());
2261 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2262 LInstruction* pop =
NULL;
2264 HEnvironment* env = current_block_->last_environment();
2266 if (env->entry()->arguments_pushed()) {
2267 int argument_count = env->arguments_environment()->parameter_count();
2268 pop =
new(zone()) LDrop(argument_count);
2269 argument_count_ -= argument_count;
2272 HEnvironment* outer = current_block_->last_environment()->
2273 DiscardInlined(
false);
2274 current_block_->UpdateEnvironment(outer);
2280 LInstruction* LChunkBuilder::DoIn(HIn* instr) {
2281 LOperand* key = UseRegisterAtStart(instr->key());
2282 LOperand*
object = UseRegisterAtStart(instr->object());
2283 LIn* result =
new(zone()) LIn(key,
object);
2284 return MarkAsCall(DefineFixed(result,
r0), instr);
2288 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2289 LOperand*
object = UseFixed(instr->enumerable(),
r0);
2290 LForInPrepareMap* result =
new(zone()) LForInPrepareMap(
object);
2291 return MarkAsCall(DefineFixed(result,
r0), instr, CAN_DEOPTIMIZE_EAGERLY);
2295 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2296 LOperand* map = UseRegister(instr->map());
2297 return AssignEnvironment(DefineAsRegister(
new(zone()) LForInCacheArray(map)));
2301 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2302 LOperand* value = UseRegisterAtStart(instr->value());
2303 LOperand* map = UseRegisterAtStart(instr->map());
2304 return AssignEnvironment(
new(zone()) LCheckMapValue(value, map));
2308 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2309 LOperand*
object = UseRegister(instr->object());
2310 LOperand* index = UseRegister(instr->index());
2311 return DefineAsRegister(
new(zone()) LLoadFieldByIndex(
object, index));
#define DEFINE_COMPILE(type)
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)
const DivMagicNumbers DivMagicNumberFor(int32_t divisor)
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)
static Representation Integer32()
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
void Add(Vector< const char > format, Vector< FmtElm > elms)
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)
LLabel * replacement() const
static HUnaryOperation * cast(HValue *value)
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
bool HasFixedPolicy() 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)
const DivMagicNumbers InvalidDivMagicNumber
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)