Revision f230a1cf deps/v8/src/ia32/lithium-ia32.cc
deps/v8/src/ia32/lithium-ia32.cc | ||
---|---|---|
386 | 386 |
} |
387 | 387 |
|
388 | 388 |
|
389 |
int LPlatformChunk::GetNextSpillIndex(bool is_double) {
|
|
389 |
int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
|
|
390 | 390 |
// Skip a slot if for a double-width slot. |
391 |
if (is_double) {
|
|
391 |
if (kind == DOUBLE_REGISTERS) {
|
|
392 | 392 |
spill_slot_count_++; |
393 | 393 |
spill_slot_count_ |= 1; |
394 | 394 |
num_double_slots_++; |
... | ... | |
397 | 397 |
} |
398 | 398 |
|
399 | 399 |
|
400 |
LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) {
|
|
401 |
int index = GetNextSpillIndex(is_double);
|
|
402 |
if (is_double) {
|
|
400 |
LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
|
|
401 |
int index = GetNextSpillIndex(kind);
|
|
402 |
if (kind == DOUBLE_REGISTERS) {
|
|
403 | 403 |
return LDoubleStackSlot::Create(index, zone()); |
404 | 404 |
} else { |
405 |
ASSERT(kind == GENERAL_REGISTERS); |
|
405 | 406 |
return LStackSlot::Create(index, zone()); |
406 | 407 |
} |
407 | 408 |
} |
... | ... | |
479 | 480 |
|
480 | 481 |
// Reserve the first spill slot for the state of dynamic alignment. |
481 | 482 |
if (info()->IsOptimizing()) { |
482 |
int alignment_state_index = chunk_->GetNextSpillIndex(false);
|
|
483 |
int alignment_state_index = chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
|
|
483 | 484 |
ASSERT_EQ(alignment_state_index, 0); |
484 | 485 |
USE(alignment_state_index); |
485 | 486 |
} |
... | ... | |
488 | 489 |
// which will be subsumed into this frame. |
489 | 490 |
if (graph()->has_osr()) { |
490 | 491 |
for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) { |
491 |
chunk_->GetNextSpillIndex(false);
|
|
492 |
chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
|
|
492 | 493 |
} |
493 | 494 |
} |
494 | 495 |
|
... | ... | |
560 | 561 |
} |
561 | 562 |
|
562 | 563 |
|
564 |
static inline bool CanBeImmediateConstant(HValue* value) { |
|
565 |
return value->IsConstant() && HConstant::cast(value)->NotInNewSpace(); |
|
566 |
} |
|
567 |
|
|
568 |
|
|
563 | 569 |
LOperand* LChunkBuilder::UseOrConstant(HValue* value) { |
564 |
return value->IsConstant()
|
|
570 |
return CanBeImmediateConstant(value)
|
|
565 | 571 |
? chunk_->DefineConstantOperand(HConstant::cast(value)) |
566 | 572 |
: Use(value); |
567 | 573 |
} |
568 | 574 |
|
569 | 575 |
|
570 | 576 |
LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) { |
571 |
return value->IsConstant()
|
|
577 |
return CanBeImmediateConstant(value)
|
|
572 | 578 |
? chunk_->DefineConstantOperand(HConstant::cast(value)) |
573 | 579 |
: UseAtStart(value); |
574 | 580 |
} |
575 | 581 |
|
576 | 582 |
|
577 | 583 |
LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) { |
578 |
return value->IsConstant()
|
|
584 |
return CanBeImmediateConstant(value)
|
|
579 | 585 |
? chunk_->DefineConstantOperand(HConstant::cast(value)) |
580 | 586 |
: UseRegister(value); |
581 | 587 |
} |
582 | 588 |
|
583 | 589 |
|
584 | 590 |
LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { |
585 |
return value->IsConstant()
|
|
591 |
return CanBeImmediateConstant(value)
|
|
586 | 592 |
? chunk_->DefineConstantOperand(HConstant::cast(value)) |
587 | 593 |
: UseRegisterAtStart(value); |
588 | 594 |
} |
... | ... | |
707 | 713 |
|
708 | 714 |
LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { |
709 | 715 |
ASSERT(!instr->HasPointerMap()); |
710 |
instr->set_pointer_map(new(zone()) LPointerMap(position_, zone()));
|
|
716 |
instr->set_pointer_map(new(zone()) LPointerMap(zone())); |
|
711 | 717 |
return instr; |
712 | 718 |
} |
713 | 719 |
|
... | ... | |
762 | 768 |
|
763 | 769 |
LInstruction* LChunkBuilder::DoShift(Token::Value op, |
764 | 770 |
HBitwiseBinaryOperation* instr) { |
765 |
if (instr->representation().IsTagged()) { |
|
766 |
ASSERT(instr->left()->representation().IsSmiOrTagged()); |
|
767 |
ASSERT(instr->right()->representation().IsSmiOrTagged()); |
|
768 |
|
|
769 |
LOperand* context = UseFixed(instr->context(), esi); |
|
770 |
LOperand* left = UseFixed(instr->left(), edx); |
|
771 |
LOperand* right = UseFixed(instr->right(), eax); |
|
772 |
LArithmeticT* result = new(zone()) LArithmeticT(op, context, left, right); |
|
773 |
return MarkAsCall(DefineFixed(result, eax), instr); |
|
774 |
} |
|
775 |
|
|
776 |
ASSERT(instr->representation().IsSmiOrInteger32()); |
|
777 |
ASSERT(instr->left()->representation().Equals(instr->representation())); |
|
778 |
ASSERT(instr->right()->representation().Equals(instr->representation())); |
|
779 |
LOperand* left = UseRegisterAtStart(instr->left()); |
|
771 |
if (instr->representation().IsSmiOrInteger32()) { |
|
772 |
ASSERT(instr->left()->representation().Equals(instr->representation())); |
|
773 |
ASSERT(instr->right()->representation().Equals(instr->representation())); |
|
774 |
LOperand* left = UseRegisterAtStart(instr->left()); |
|
780 | 775 |
|
781 |
HValue* right_value = instr->right(); |
|
782 |
LOperand* right = NULL; |
|
783 |
int constant_value = 0; |
|
784 |
bool does_deopt = false; |
|
785 |
if (right_value->IsConstant()) { |
|
786 |
HConstant* constant = HConstant::cast(right_value); |
|
787 |
right = chunk_->DefineConstantOperand(constant); |
|
788 |
constant_value = constant->Integer32Value() & 0x1f; |
|
789 |
// Left shifts can deoptimize if we shift by > 0 and the result cannot be |
|
790 |
// truncated to smi. |
|
791 |
if (instr->representation().IsSmi() && constant_value > 0) { |
|
792 |
does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi); |
|
776 |
HValue* right_value = instr->right(); |
|
777 |
LOperand* right = NULL; |
|
778 |
int constant_value = 0; |
|
779 |
bool does_deopt = false; |
|
780 |
if (right_value->IsConstant()) { |
|
781 |
HConstant* constant = HConstant::cast(right_value); |
|
782 |
right = chunk_->DefineConstantOperand(constant); |
|
783 |
constant_value = constant->Integer32Value() & 0x1f; |
|
784 |
// Left shifts can deoptimize if we shift by > 0 and the result cannot be |
|
785 |
// truncated to smi. |
|
786 |
if (instr->representation().IsSmi() && constant_value > 0) { |
|
787 |
does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi); |
|
788 |
} |
|
789 |
} else { |
|
790 |
right = UseFixed(right_value, ecx); |
|
793 | 791 |
} |
794 |
} else { |
|
795 |
right = UseFixed(right_value, ecx); |
|
796 |
} |
|
797 | 792 |
|
798 |
// Shift operations can only deoptimize if we do a logical shift by 0 and |
|
799 |
// the result cannot be truncated to int32. |
|
800 |
if (op == Token::SHR && constant_value == 0) { |
|
801 |
if (FLAG_opt_safe_uint32_operations) { |
|
802 |
does_deopt = !instr->CheckFlag(HInstruction::kUint32); |
|
803 |
} else { |
|
804 |
does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); |
|
793 |
// Shift operations can only deoptimize if we do a logical shift by 0 and |
|
794 |
// the result cannot be truncated to int32. |
|
795 |
if (op == Token::SHR && constant_value == 0) { |
|
796 |
if (FLAG_opt_safe_uint32_operations) { |
|
797 |
does_deopt = !instr->CheckFlag(HInstruction::kUint32); |
|
798 |
} else { |
|
799 |
does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); |
|
800 |
} |
|
805 | 801 |
} |
806 |
} |
|
807 | 802 |
|
808 |
LInstruction* result = |
|
809 |
DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt)); |
|
810 |
return does_deopt ? AssignEnvironment(result) : result; |
|
803 |
LInstruction* result = |
|
804 |
DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt)); |
|
805 |
return does_deopt ? AssignEnvironment(result) : result; |
|
806 |
} else { |
|
807 |
return DoArithmeticT(op, instr); |
|
808 |
} |
|
811 | 809 |
} |
812 | 810 |
|
813 | 811 |
|
... | ... | |
816 | 814 |
ASSERT(instr->representation().IsDouble()); |
817 | 815 |
ASSERT(instr->left()->representation().IsDouble()); |
818 | 816 |
ASSERT(instr->right()->representation().IsDouble()); |
819 |
ASSERT(op != Token::MOD); |
|
820 |
LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
|
821 |
LOperand* right = UseRegisterAtStart(instr->BetterRightOperand()); |
|
822 |
LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
|
823 |
return DefineSameAsFirst(result); |
|
817 |
if (op == Token::MOD) { |
|
818 |
LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
|
819 |
LOperand* right = UseRegisterAtStart(instr->BetterRightOperand()); |
|
820 |
LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
|
821 |
return MarkAsCall(DefineSameAsFirst(result), instr); |
|
822 |
} else { |
|
823 |
LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
|
824 |
LOperand* right = UseRegisterAtStart(instr->BetterRightOperand()); |
|
825 |
LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
|
826 |
return DefineSameAsFirst(result); |
|
827 |
} |
|
824 | 828 |
} |
825 | 829 |
|
826 | 830 |
|
827 | 831 |
LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
828 |
HArithmeticBinaryOperation* instr) { |
|
829 |
ASSERT(op == Token::ADD || |
|
830 |
op == Token::DIV || |
|
831 |
op == Token::MOD || |
|
832 |
op == Token::MUL || |
|
833 |
op == Token::SUB); |
|
832 |
HBinaryOperation* instr) { |
|
834 | 833 |
HValue* left = instr->left(); |
835 | 834 |
HValue* right = instr->right(); |
836 | 835 |
ASSERT(left->representation().IsTagged()); |
... | ... | |
914 | 913 |
void LChunkBuilder::VisitInstruction(HInstruction* current) { |
915 | 914 |
HInstruction* old_current = current_instruction_; |
916 | 915 |
current_instruction_ = current; |
917 |
if (current->has_position()) position_ = current->position(); |
|
918 |
LInstruction* instr = current->CompileToLithium(this); |
|
916 |
|
|
917 |
LInstruction* instr = NULL; |
|
918 |
if (current->CanReplaceWithDummyUses()) { |
|
919 |
HValue* first_operand = current->OperandCount() == 0 |
|
920 |
? graph()->GetConstant1() |
|
921 |
: current->OperandAt(0); |
|
922 |
instr = DefineAsRegister(new(zone()) LDummyUse(UseAny(first_operand))); |
|
923 |
for (int i = 1; i < current->OperandCount(); ++i) { |
|
924 |
LInstruction* dummy = |
|
925 |
new(zone()) LDummyUse(UseAny(current->OperandAt(i))); |
|
926 |
dummy->set_hydrogen_value(current); |
|
927 |
chunk_->AddInstruction(dummy, current_block_); |
|
928 |
} |
|
929 |
} else { |
|
930 |
instr = current->CompileToLithium(this); |
|
931 |
} |
|
932 |
|
|
933 |
argument_count_ += current->argument_delta(); |
|
934 |
ASSERT(argument_count_ >= 0); |
|
919 | 935 |
|
920 | 936 |
if (instr != NULL) { |
937 |
// Associate the hydrogen instruction first, since we may need it for |
|
938 |
// the ClobbersRegisters() or ClobbersDoubleRegisters() calls below. |
|
939 |
instr->set_hydrogen_value(current); |
|
940 |
|
|
921 | 941 |
#if DEBUG |
922 | 942 |
// Make sure that the lithium instruction has either no fixed register |
923 | 943 |
// constraints in temps or the result OR no uses that are only used at |
... | ... | |
947 | 967 |
} |
948 | 968 |
#endif |
949 | 969 |
|
950 |
instr->set_position(position_); |
|
951 | 970 |
if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
952 | 971 |
instr = AssignPointerMap(instr); |
953 | 972 |
} |
... | ... | |
964 | 983 |
clobber->set_hydrogen_value(current); |
965 | 984 |
chunk_->AddInstruction(clobber, current_block_); |
966 | 985 |
} |
967 |
instr->set_hydrogen_value(current); |
|
968 | 986 |
chunk_->AddInstruction(instr, current_block_); |
969 | 987 |
} |
970 | 988 |
current_instruction_ = old_current; |
... | ... | |
1061 | 1079 |
|
1062 | 1080 |
|
1063 | 1081 |
LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
1064 |
HValue* value = instr->value(); |
|
1065 |
if (value->EmitAtUses()) { |
|
1066 |
ASSERT(value->IsConstant()); |
|
1067 |
ASSERT(!value->representation().IsDouble()); |
|
1068 |
HBasicBlock* successor = HConstant::cast(value)->BooleanValue() |
|
1069 |
? instr->FirstSuccessor() |
|
1070 |
: instr->SecondSuccessor(); |
|
1071 |
return new(zone()) LGoto(successor); |
|
1072 |
} |
|
1082 |
LInstruction* goto_instr = CheckElideControlInstruction(instr); |
|
1083 |
if (goto_instr != NULL) return goto_instr; |
|
1073 | 1084 |
|
1074 | 1085 |
ToBooleanStub::Types expected = instr->expected_input_types(); |
1075 | 1086 |
|
1076 | 1087 |
// Tagged values that are not known smis or booleans require a |
1077 | 1088 |
// deoptimization environment. If the instruction is generic no |
1078 | 1089 |
// environment is needed since all cases are handled. |
1090 |
HValue* value = instr->value(); |
|
1079 | 1091 |
Representation rep = value->representation(); |
1080 | 1092 |
HType type = value->type(); |
1081 | 1093 |
if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) { |
... | ... | |
1141 | 1153 |
} |
1142 | 1154 |
|
1143 | 1155 |
|
1144 |
LInstruction* LChunkBuilder::DoInstanceSize(HInstanceSize* instr) { |
|
1145 |
LOperand* object = UseRegisterAtStart(instr->object()); |
|
1146 |
return DefineAsRegister(new(zone()) LInstanceSize(object)); |
|
1147 |
} |
|
1148 |
|
|
1149 |
|
|
1150 | 1156 |
LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { |
1151 | 1157 |
LOperand* receiver = UseRegister(instr->receiver()); |
1152 | 1158 |
LOperand* function = UseRegisterAtStart(instr->function()); |
... | ... | |
1171 | 1177 |
|
1172 | 1178 |
|
1173 | 1179 |
LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { |
1174 |
++argument_count_; |
|
1175 | 1180 |
LOperand* argument = UseAny(instr->argument()); |
1176 | 1181 |
return new(zone()) LPushArgument(argument); |
1177 | 1182 |
} |
... | ... | |
1238 | 1243 |
|
1239 | 1244 |
LInstruction* LChunkBuilder::DoCallConstantFunction( |
1240 | 1245 |
HCallConstantFunction* instr) { |
1241 |
argument_count_ -= instr->argument_count(); |
|
1242 | 1246 |
return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, eax), instr); |
1243 | 1247 |
} |
1244 | 1248 |
|
... | ... | |
1246 | 1250 |
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) { |
1247 | 1251 |
LOperand* context = UseFixed(instr->context(), esi); |
1248 | 1252 |
LOperand* function = UseFixed(instr->function(), edi); |
1249 |
argument_count_ -= instr->argument_count(); |
|
1250 | 1253 |
LInvokeFunction* result = new(zone()) LInvokeFunction(context, function); |
1251 | 1254 |
return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY); |
1252 | 1255 |
} |
... | ... | |
1356 | 1359 |
ASSERT(instr->key()->representation().IsTagged()); |
1357 | 1360 |
LOperand* context = UseFixed(instr->context(), esi); |
1358 | 1361 |
LOperand* key = UseFixed(instr->key(), ecx); |
1359 |
argument_count_ -= instr->argument_count(); |
|
1360 | 1362 |
LCallKeyed* result = new(zone()) LCallKeyed(context, key); |
1361 | 1363 |
return MarkAsCall(DefineFixed(result, eax), instr); |
1362 | 1364 |
} |
... | ... | |
1364 | 1366 |
|
1365 | 1367 |
LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { |
1366 | 1368 |
LOperand* context = UseFixed(instr->context(), esi); |
1367 |
argument_count_ -= instr->argument_count(); |
|
1368 | 1369 |
LCallNamed* result = new(zone()) LCallNamed(context); |
1369 | 1370 |
return MarkAsCall(DefineFixed(result, eax), instr); |
1370 | 1371 |
} |
... | ... | |
1372 | 1373 |
|
1373 | 1374 |
LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { |
1374 | 1375 |
LOperand* context = UseFixed(instr->context(), esi); |
1375 |
argument_count_ -= instr->argument_count(); |
|
1376 | 1376 |
LCallGlobal* result = new(zone()) LCallGlobal(context); |
1377 | 1377 |
return MarkAsCall(DefineFixed(result, eax), instr); |
1378 | 1378 |
} |
1379 | 1379 |
|
1380 | 1380 |
|
1381 | 1381 |
LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { |
1382 |
argument_count_ -= instr->argument_count(); |
|
1383 | 1382 |
return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, eax), instr); |
1384 | 1383 |
} |
1385 | 1384 |
|
... | ... | |
1387 | 1386 |
LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { |
1388 | 1387 |
LOperand* context = UseFixed(instr->context(), esi); |
1389 | 1388 |
LOperand* constructor = UseFixed(instr->constructor(), edi); |
1390 |
argument_count_ -= instr->argument_count(); |
|
1391 | 1389 |
LCallNew* result = new(zone()) LCallNew(context, constructor); |
1392 | 1390 |
return MarkAsCall(DefineFixed(result, eax), instr); |
1393 | 1391 |
} |
... | ... | |
1396 | 1394 |
LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) { |
1397 | 1395 |
LOperand* context = UseFixed(instr->context(), esi); |
1398 | 1396 |
LOperand* constructor = UseFixed(instr->constructor(), edi); |
1399 |
argument_count_ -= instr->argument_count(); |
|
1400 | 1397 |
LCallNewArray* result = new(zone()) LCallNewArray(context, constructor); |
1401 | 1398 |
return MarkAsCall(DefineFixed(result, eax), instr); |
1402 | 1399 |
} |
... | ... | |
1405 | 1402 |
LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { |
1406 | 1403 |
LOperand* context = UseFixed(instr->context(), esi); |
1407 | 1404 |
LOperand* function = UseFixed(instr->function(), edi); |
1408 |
argument_count_ -= instr->argument_count(); |
|
1409 | 1405 |
LCallFunction* result = new(zone()) LCallFunction(context, function); |
1410 | 1406 |
return MarkAsCall(DefineFixed(result, eax), instr); |
1411 | 1407 |
} |
1412 | 1408 |
|
1413 | 1409 |
|
1414 | 1410 |
LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { |
1415 |
argument_count_ -= instr->argument_count(); |
|
1416 | 1411 |
LOperand* context = UseFixed(instr->context(), esi); |
1417 | 1412 |
return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), eax), instr); |
1418 | 1413 |
} |
... | ... | |
1442 | 1437 |
if (instr->representation().IsSmiOrInteger32()) { |
1443 | 1438 |
ASSERT(instr->left()->representation().Equals(instr->representation())); |
1444 | 1439 |
ASSERT(instr->right()->representation().Equals(instr->representation())); |
1440 |
ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32)); |
|
1445 | 1441 |
|
1446 | 1442 |
LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
1447 | 1443 |
LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
1448 | 1444 |
return DefineSameAsFirst(new(zone()) LBitI(left, right)); |
1449 | 1445 |
} else { |
1450 |
ASSERT(instr->representation().IsSmiOrTagged()); |
|
1451 |
ASSERT(instr->left()->representation().IsSmiOrTagged()); |
|
1452 |
ASSERT(instr->right()->representation().IsSmiOrTagged()); |
|
1453 |
|
|
1454 |
LOperand* context = UseFixed(instr->context(), esi); |
|
1455 |
LOperand* left = UseFixed(instr->left(), edx); |
|
1456 |
LOperand* right = UseFixed(instr->right(), eax); |
|
1457 |
LArithmeticT* result = |
|
1458 |
new(zone()) LArithmeticT(instr->op(), context, left, right); |
|
1459 |
return MarkAsCall(DefineFixed(result, eax), instr); |
|
1446 |
return DoArithmeticT(instr->op(), instr); |
|
1460 | 1447 |
} |
1461 | 1448 |
} |
1462 | 1449 |
|
1463 | 1450 |
|
1464 | 1451 |
LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
1465 |
if (instr->representation().IsDouble()) { |
|
1466 |
return DoArithmeticD(Token::DIV, instr); |
|
1467 |
} else if (instr->representation().IsSmiOrInteger32()) { |
|
1452 |
if (instr->representation().IsSmiOrInteger32()) { |
|
1468 | 1453 |
ASSERT(instr->left()->representation().Equals(instr->representation())); |
1469 | 1454 |
ASSERT(instr->right()->representation().Equals(instr->representation())); |
1470 | 1455 |
if (instr->HasPowerOf2Divisor()) { |
... | ... | |
1481 | 1466 |
LOperand* divisor = UseRegister(instr->right()); |
1482 | 1467 |
LDivI* result = new(zone()) LDivI(dividend, divisor, temp); |
1483 | 1468 |
return AssignEnvironment(DefineFixed(result, eax)); |
1469 |
} else if (instr->representation().IsDouble()) { |
|
1470 |
return DoArithmeticD(Token::DIV, instr); |
|
1484 | 1471 |
} else { |
1485 |
ASSERT(instr->representation().IsTagged()); |
|
1486 | 1472 |
return DoArithmeticT(Token::DIV, instr); |
1487 | 1473 |
} |
1488 | 1474 |
} |
... | ... | |
1584 | 1570 |
? AssignEnvironment(result) |
1585 | 1571 |
: result; |
1586 | 1572 |
} |
1587 |
} else if (instr->representation().IsSmiOrTagged()) {
|
|
1588 |
return DoArithmeticT(Token::MOD, instr);
|
|
1573 |
} else if (instr->representation().IsDouble()) {
|
|
1574 |
return DoArithmeticD(Token::MOD, instr);
|
|
1589 | 1575 |
} else { |
1590 |
ASSERT(instr->representation().IsDouble()); |
|
1591 |
// We call a C function for double modulo. It can't trigger a GC. We need |
|
1592 |
// to use fixed result register for the call. |
|
1593 |
// TODO(fschneider): Allow any register as input registers. |
|
1594 |
LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, |
|
1595 |
UseFixedDouble(left, xmm2), |
|
1596 |
UseFixedDouble(right, xmm1)); |
|
1597 |
return MarkAsCall(DefineFixedDouble(mod, xmm1), instr); |
|
1576 |
return DoArithmeticT(Token::MOD, instr); |
|
1598 | 1577 |
} |
1599 | 1578 |
} |
1600 | 1579 |
|
... | ... | |
1618 | 1597 |
} else if (instr->representation().IsDouble()) { |
1619 | 1598 |
return DoArithmeticD(Token::MUL, instr); |
1620 | 1599 |
} else { |
1621 |
ASSERT(instr->representation().IsTagged()); |
|
1622 | 1600 |
return DoArithmeticT(Token::MUL, instr); |
1623 | 1601 |
} |
1624 | 1602 |
} |
... | ... | |
1639 | 1617 |
} else if (instr->representation().IsDouble()) { |
1640 | 1618 |
return DoArithmeticD(Token::SUB, instr); |
1641 | 1619 |
} else { |
1642 |
ASSERT(instr->representation().IsSmiOrTagged()); |
|
1643 | 1620 |
return DoArithmeticT(Token::SUB, instr); |
1644 | 1621 |
} |
1645 | 1622 |
} |
... | ... | |
1671 | 1648 |
} else if (instr->representation().IsDouble()) { |
1672 | 1649 |
return DoArithmeticD(Token::ADD, instr); |
1673 | 1650 |
} else { |
1674 |
ASSERT(instr->representation().IsSmiOrTagged()); |
|
1675 | 1651 |
return DoArithmeticT(Token::ADD, instr); |
1676 | 1652 |
} |
1677 | 1653 |
} |
... | ... | |
1752 | 1728 |
ASSERT(instr->right()->representation().IsDouble()); |
1753 | 1729 |
LOperand* left; |
1754 | 1730 |
LOperand* right; |
1755 |
if (instr->left()->IsConstant() && instr->right()->IsConstant()) { |
|
1756 |
left = UseRegisterOrConstantAtStart(instr->left()); |
|
1757 |
right = UseRegisterOrConstantAtStart(instr->right()); |
|
1731 |
if (CanBeImmediateConstant(instr->left()) && |
|
1732 |
CanBeImmediateConstant(instr->right())) { |
|
1733 |
// The code generator requires either both inputs to be constant |
|
1734 |
// operands, or neither. |
|
1735 |
left = UseConstant(instr->left()); |
|
1736 |
right = UseConstant(instr->right()); |
|
1758 | 1737 |
} else { |
1759 | 1738 |
left = UseRegisterAtStart(instr->left()); |
1760 | 1739 |
right = UseRegisterAtStart(instr->right()); |
... | ... | |
1766 | 1745 |
|
1767 | 1746 |
LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( |
1768 | 1747 |
HCompareObjectEqAndBranch* instr) { |
1748 |
LInstruction* goto_instr = CheckElideControlInstruction(instr); |
|
1749 |
if (goto_instr != NULL) return goto_instr; |
|
1769 | 1750 |
LOperand* left = UseRegisterAtStart(instr->left()); |
1770 | 1751 |
LOperand* right = UseOrConstantAtStart(instr->right()); |
1771 | 1752 |
return new(zone()) LCmpObjectEqAndBranch(left, right); |
... | ... | |
1774 | 1755 |
|
1775 | 1756 |
LInstruction* LChunkBuilder::DoCompareHoleAndBranch( |
1776 | 1757 |
HCompareHoleAndBranch* instr) { |
1777 |
LOperand* object = UseRegisterAtStart(instr->object());
|
|
1778 |
return new(zone()) LCmpHoleAndBranch(object);
|
|
1758 |
LOperand* value = UseRegisterAtStart(instr->value());
|
|
1759 |
return new(zone()) LCmpHoleAndBranch(value);
|
|
1779 | 1760 |
} |
1780 | 1761 |
|
1781 | 1762 |
|
... | ... | |
1909 | 1890 |
} |
1910 | 1891 |
|
1911 | 1892 |
|
1893 |
LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { |
|
1894 |
// The control instruction marking the end of a block that completed |
|
1895 |
// abruptly (e.g., threw an exception). There is nothing specific to do. |
|
1896 |
return NULL; |
|
1897 |
} |
|
1898 |
|
|
1899 |
|
|
1912 | 1900 |
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { |
1913 | 1901 |
LOperand* context = UseFixed(instr->context(), esi); |
1914 | 1902 |
LOperand* value = UseFixed(instr->value(), eax); |
... | ... | |
1944 | 1932 |
// building a stack frame. |
1945 | 1933 |
if (from.IsTagged()) { |
1946 | 1934 |
if (to.IsDouble()) { |
1947 |
info()->MarkAsDeferredCalling(); |
|
1948 | 1935 |
LOperand* value = UseRegister(instr->value()); |
1949 | 1936 |
// Temp register only necessary for minus zero check. |
1950 | 1937 |
LOperand* temp = TempRegister(); |
... | ... | |
2015 | 2002 |
} else if (to.IsSmi()) { |
2016 | 2003 |
HValue* val = instr->value(); |
2017 | 2004 |
LOperand* value = UseRegister(val); |
2018 |
LInstruction* result = |
|
2019 |
DefineSameAsFirst(new(zone()) LInteger32ToSmi(value)); |
|
2005 |
LInstruction* result = val->CheckFlag(HInstruction::kUint32) |
|
2006 |
? DefineSameAsFirst(new(zone()) LUint32ToSmi(value)) |
|
2007 |
: DefineSameAsFirst(new(zone()) LInteger32ToSmi(value)); |
|
2020 | 2008 |
if (val->HasRange() && val->range()->IsInSmiRange()) { |
2021 | 2009 |
return result; |
2022 | 2010 |
} |
... | ... | |
2050 | 2038 |
} |
2051 | 2039 |
|
2052 | 2040 |
|
2053 |
LInstruction* LChunkBuilder::DoIsNumberAndBranch(HIsNumberAndBranch* instr) { |
|
2054 |
return new(zone()) |
|
2055 |
LIsNumberAndBranch(UseRegisterOrConstantAtStart(instr->value())); |
|
2056 |
} |
|
2057 |
|
|
2058 |
|
|
2059 | 2041 |
LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
2060 | 2042 |
LOperand* value = UseRegisterAtStart(instr->value()); |
2061 | 2043 |
LOperand* temp = TempRegister(); |
... | ... | |
2234 | 2216 |
} |
2235 | 2217 |
|
2236 | 2218 |
|
2219 |
LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { |
|
2220 |
return DefineAsRegister(new(zone()) LLoadRoot); |
|
2221 |
} |
|
2222 |
|
|
2223 |
|
|
2237 | 2224 |
LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( |
2238 | 2225 |
HLoadExternalArrayPointer* instr) { |
2239 | 2226 |
LOperand* input = UseRegisterAtStart(instr->value()); |
... | ... | |
2435 | 2422 |
!(FLAG_track_double_fields && instr->field_representation().IsDouble()); |
2436 | 2423 |
|
2437 | 2424 |
LOperand* val; |
2438 |
if (needs_write_barrier) { |
|
2425 |
if (instr->field_representation().IsByte()) { |
|
2426 |
// mov_b requires a byte register (i.e. any of eax, ebx, ecx, edx). |
|
2427 |
// Just force the value to be in eax and we're safe here. |
|
2428 |
val = UseFixed(instr->value(), eax); |
|
2429 |
} else if (needs_write_barrier) { |
|
2439 | 2430 |
val = UseTempRegister(instr->value()); |
2440 | 2431 |
} else if (can_be_constant) { |
2441 | 2432 |
val = UseRegisterOrConstant(instr->value()); |
... | ... | |
2582 | 2573 |
|
2583 | 2574 |
LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { |
2584 | 2575 |
LOperand* context = UseFixed(instr->context(), esi); |
2585 |
argument_count_ -= instr->argument_count(); |
|
2586 | 2576 |
LCallStub* result = new(zone()) LCallStub(context); |
2587 | 2577 |
return MarkAsCall(DefineFixed(result, eax), instr); |
2588 | 2578 |
} |
... | ... | |
2711 | 2701 |
if (env->entry()->arguments_pushed()) { |
2712 | 2702 |
int argument_count = env->arguments_environment()->parameter_count(); |
2713 | 2703 |
pop = new(zone()) LDrop(argument_count); |
2714 |
argument_count_ -= argument_count;
|
|
2704 |
ASSERT(instr->argument_delta() == -argument_count);
|
|
2715 | 2705 |
} |
2716 | 2706 |
|
2717 | 2707 |
HEnvironment* outer = current_block_->last_environment()-> |
Also available in: Unified diff