Revision f230a1cf deps/v8/src/x64/lithium-x64.cc
deps/v8/src/x64/lithium-x64.cc | ||
---|---|---|
353 | 353 |
} |
354 | 354 |
|
355 | 355 |
|
356 |
int LPlatformChunk::GetNextSpillIndex(bool is_double) {
|
|
356 |
int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
|
|
357 | 357 |
return spill_slot_count_++; |
358 | 358 |
} |
359 | 359 |
|
360 | 360 |
|
361 |
LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) {
|
|
361 |
LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
|
|
362 | 362 |
// All stack slots are Double stack slots on x64. |
363 | 363 |
// Alternatively, at some point, start using half-size |
364 | 364 |
// stack slots for int32 values. |
365 |
int index = GetNextSpillIndex(is_double);
|
|
366 |
if (is_double) {
|
|
365 |
int index = GetNextSpillIndex(kind);
|
|
366 |
if (kind == DOUBLE_REGISTERS) {
|
|
367 | 367 |
return LDoubleStackSlot::Create(index, zone()); |
368 | 368 |
} else { |
369 |
ASSERT(kind == GENERAL_REGISTERS); |
|
369 | 370 |
return LStackSlot::Create(index, zone()); |
370 | 371 |
} |
371 | 372 |
} |
... | ... | |
445 | 446 |
// which will be subsumed into this frame. |
446 | 447 |
if (graph()->has_osr()) { |
447 | 448 |
for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) { |
448 |
chunk_->GetNextSpillIndex(false);
|
|
449 |
chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
|
|
449 | 450 |
} |
450 | 451 |
} |
451 | 452 |
|
... | ... | |
664 | 665 |
|
665 | 666 |
LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { |
666 | 667 |
ASSERT(!instr->HasPointerMap()); |
667 |
instr->set_pointer_map(new(zone()) LPointerMap(position_, zone()));
|
|
668 |
instr->set_pointer_map(new(zone()) LPointerMap(zone())); |
|
668 | 669 |
return instr; |
669 | 670 |
} |
670 | 671 |
|
... | ... | |
719 | 720 |
|
720 | 721 |
LInstruction* LChunkBuilder::DoShift(Token::Value op, |
721 | 722 |
HBitwiseBinaryOperation* instr) { |
722 |
if (instr->representation().IsTagged()) { |
|
723 |
ASSERT(instr->left()->representation().IsTagged()); |
|
724 |
ASSERT(instr->right()->representation().IsTagged()); |
|
723 |
if (instr->representation().IsSmiOrInteger32()) { |
|
724 |
ASSERT(instr->left()->representation().Equals(instr->representation())); |
|
725 |
ASSERT(instr->right()->representation().Equals(instr->representation())); |
|
726 |
LOperand* left = UseRegisterAtStart(instr->left()); |
|
725 | 727 |
|
726 |
LOperand* left = UseFixed(instr->left(), rdx); |
|
727 |
LOperand* right = UseFixed(instr->right(), rax); |
|
728 |
LArithmeticT* result = new(zone()) LArithmeticT(op, left, right); |
|
729 |
return MarkAsCall(DefineFixed(result, rax), instr); |
|
730 |
} |
|
728 |
HValue* right_value = instr->right(); |
|
729 |
LOperand* right = NULL; |
|
730 |
int constant_value = 0; |
|
731 |
if (right_value->IsConstant()) { |
|
732 |
HConstant* constant = HConstant::cast(right_value); |
|
733 |
right = chunk_->DefineConstantOperand(constant); |
|
734 |
constant_value = constant->Integer32Value() & 0x1f; |
|
735 |
} else { |
|
736 |
right = UseFixed(right_value, rcx); |
|
737 |
} |
|
731 | 738 |
|
732 |
ASSERT(instr->representation().IsSmiOrInteger32()); |
|
733 |
ASSERT(instr->left()->representation().Equals(instr->representation())); |
|
734 |
ASSERT(instr->right()->representation().Equals(instr->representation())); |
|
735 |
LOperand* left = UseRegisterAtStart(instr->left()); |
|
739 |
// Shift operations can only deoptimize if we do a logical shift by 0 and |
|
740 |
// the result cannot be truncated to int32. |
|
741 |
bool does_deopt = false; |
|
742 |
if (op == Token::SHR && constant_value == 0) { |
|
743 |
if (FLAG_opt_safe_uint32_operations) { |
|
744 |
does_deopt = !instr->CheckFlag(HInstruction::kUint32); |
|
745 |
} else { |
|
746 |
does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); |
|
747 |
} |
|
748 |
} |
|
736 | 749 |
|
737 |
HValue* right_value = instr->right(); |
|
738 |
LOperand* right = NULL; |
|
739 |
int constant_value = 0; |
|
740 |
if (right_value->IsConstant()) { |
|
741 |
HConstant* constant = HConstant::cast(right_value); |
|
742 |
right = chunk_->DefineConstantOperand(constant); |
|
743 |
constant_value = constant->Integer32Value() & 0x1f; |
|
750 |
LInstruction* result = |
|
751 |
DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt)); |
|
752 |
return does_deopt ? AssignEnvironment(result) : result; |
|
744 | 753 |
} else { |
745 |
right = UseFixed(right_value, rcx); |
|
746 |
} |
|
747 |
|
|
748 |
// Shift operations can only deoptimize if we do a logical shift by 0 and |
|
749 |
// the result cannot be truncated to int32. |
|
750 |
bool does_deopt = false; |
|
751 |
if (op == Token::SHR && constant_value == 0) { |
|
752 |
if (FLAG_opt_safe_uint32_operations) { |
|
753 |
does_deopt = !instr->CheckFlag(HInstruction::kUint32); |
|
754 |
} else { |
|
755 |
does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); |
|
756 |
} |
|
754 |
return DoArithmeticT(op, instr); |
|
757 | 755 |
} |
758 |
|
|
759 |
LInstruction* result = |
|
760 |
DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt)); |
|
761 |
return does_deopt ? AssignEnvironment(result) : result; |
|
762 | 756 |
} |
763 | 757 |
|
764 | 758 |
|
... | ... | |
767 | 761 |
ASSERT(instr->representation().IsDouble()); |
768 | 762 |
ASSERT(instr->left()->representation().IsDouble()); |
769 | 763 |
ASSERT(instr->right()->representation().IsDouble()); |
770 |
ASSERT(op != Token::MOD); |
|
771 |
LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
|
772 |
LOperand* right = UseRegisterAtStart(instr->BetterRightOperand()); |
|
773 |
LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
|
774 |
return DefineSameAsFirst(result); |
|
764 |
if (op == Token::MOD) { |
|
765 |
LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
|
766 |
LOperand* right = UseFixedDouble(instr->BetterRightOperand(), xmm1); |
|
767 |
LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
|
768 |
return MarkAsCall(DefineSameAsFirst(result), instr); |
|
769 |
} else { |
|
770 |
LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
|
771 |
LOperand* right = UseRegisterAtStart(instr->BetterRightOperand()); |
|
772 |
LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
|
773 |
return DefineSameAsFirst(result); |
|
774 |
} |
|
775 | 775 |
} |
776 | 776 |
|
777 | 777 |
|
778 | 778 |
LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
779 |
HArithmeticBinaryOperation* instr) { |
|
780 |
ASSERT(op == Token::ADD || |
|
781 |
op == Token::DIV || |
|
782 |
op == Token::MOD || |
|
783 |
op == Token::MUL || |
|
784 |
op == Token::SUB); |
|
779 |
HBinaryOperation* instr) { |
|
785 | 780 |
HValue* left = instr->left(); |
786 | 781 |
HValue* right = instr->right(); |
787 | 782 |
ASSERT(left->representation().IsTagged()); |
... | ... | |
864 | 859 |
void LChunkBuilder::VisitInstruction(HInstruction* current) { |
865 | 860 |
HInstruction* old_current = current_instruction_; |
866 | 861 |
current_instruction_ = current; |
867 |
if (current->has_position()) position_ = current->position(); |
|
868 |
LInstruction* instr = current->CompileToLithium(this); |
|
862 |
|
|
863 |
LInstruction* instr = NULL; |
|
864 |
if (current->CanReplaceWithDummyUses()) { |
|
865 |
HValue* first_operand = current->OperandCount() == 0 |
|
866 |
? graph()->GetConstant1() |
|
867 |
: current->OperandAt(0); |
|
868 |
instr = DefineAsRegister(new(zone()) LDummyUse(UseAny(first_operand))); |
|
869 |
for (int i = 1; i < current->OperandCount(); ++i) { |
|
870 |
LInstruction* dummy = |
|
871 |
new(zone()) LDummyUse(UseAny(current->OperandAt(i))); |
|
872 |
dummy->set_hydrogen_value(current); |
|
873 |
chunk_->AddInstruction(dummy, current_block_); |
|
874 |
} |
|
875 |
} else { |
|
876 |
instr = current->CompileToLithium(this); |
|
877 |
} |
|
878 |
|
|
879 |
argument_count_ += current->argument_delta(); |
|
880 |
ASSERT(argument_count_ >= 0); |
|
869 | 881 |
|
870 | 882 |
if (instr != NULL) { |
883 |
// Associate the hydrogen instruction first, since we may need it for |
|
884 |
// the ClobbersRegisters() or ClobbersDoubleRegisters() calls below. |
|
885 |
instr->set_hydrogen_value(current); |
|
886 |
|
|
871 | 887 |
#if DEBUG |
872 | 888 |
// Make sure that the lithium instruction has either no fixed register |
873 | 889 |
// constraints in temps or the result OR no uses that are only used at |
... | ... | |
897 | 913 |
} |
898 | 914 |
#endif |
899 | 915 |
|
900 |
instr->set_position(position_); |
|
901 | 916 |
if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
902 | 917 |
instr = AssignPointerMap(instr); |
903 | 918 |
} |
904 | 919 |
if (FLAG_stress_environments && !instr->HasEnvironment()) { |
905 | 920 |
instr = AssignEnvironment(instr); |
906 | 921 |
} |
907 |
instr->set_hydrogen_value(current); |
|
908 | 922 |
chunk_->AddInstruction(instr, current_block_); |
909 | 923 |
} |
910 | 924 |
current_instruction_ = old_current; |
... | ... | |
996 | 1010 |
|
997 | 1011 |
|
998 | 1012 |
LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
999 |
return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
|
|
1013 |
return new(zone()) LGoto(instr->FirstSuccessor()); |
|
1000 | 1014 |
} |
1001 | 1015 |
|
1002 | 1016 |
|
... | ... | |
1006 | 1020 |
|
1007 | 1021 |
|
1008 | 1022 |
LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
1009 |
HValue* value = instr->value(); |
|
1010 |
if (value->EmitAtUses()) { |
|
1011 |
ASSERT(value->IsConstant()); |
|
1012 |
ASSERT(!value->representation().IsDouble()); |
|
1013 |
HBasicBlock* successor = HConstant::cast(value)->BooleanValue() |
|
1014 |
? instr->FirstSuccessor() |
|
1015 |
: instr->SecondSuccessor(); |
|
1016 |
return new(zone()) LGoto(successor->block_id()); |
|
1017 |
} |
|
1023 |
LInstruction* goto_instr = CheckElideControlInstruction(instr); |
|
1024 |
if (goto_instr != NULL) return goto_instr; |
|
1018 | 1025 |
|
1026 |
HValue* value = instr->value(); |
|
1019 | 1027 |
LBranch* result = new(zone()) LBranch(UseRegister(value)); |
1020 | 1028 |
// Tagged values that are not known smis or booleans require a |
1021 | 1029 |
// deoptimization environment. If the instruction is generic no |
... | ... | |
1067 | 1075 |
} |
1068 | 1076 |
|
1069 | 1077 |
|
1070 |
LInstruction* LChunkBuilder::DoInstanceSize(HInstanceSize* instr) { |
|
1071 |
LOperand* object = UseRegisterAtStart(instr->object()); |
|
1072 |
return DefineAsRegister(new(zone()) LInstanceSize(object)); |
|
1073 |
} |
|
1074 |
|
|
1075 |
|
|
1076 | 1078 |
LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { |
1077 | 1079 |
LOperand* receiver = UseRegister(instr->receiver()); |
1078 | 1080 |
LOperand* function = UseRegisterAtStart(instr->function()); |
... | ... | |
1095 | 1097 |
|
1096 | 1098 |
|
1097 | 1099 |
LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { |
1098 |
++argument_count_; |
|
1099 | 1100 |
LOperand* argument = UseOrConstant(instr->argument()); |
1100 | 1101 |
return new(zone()) LPushArgument(argument); |
1101 | 1102 |
} |
... | ... | |
1161 | 1162 |
|
1162 | 1163 |
LInstruction* LChunkBuilder::DoCallConstantFunction( |
1163 | 1164 |
HCallConstantFunction* instr) { |
1164 |
argument_count_ -= instr->argument_count(); |
|
1165 | 1165 |
return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, rax), instr); |
1166 | 1166 |
} |
1167 | 1167 |
|
1168 | 1168 |
|
1169 | 1169 |
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) { |
1170 | 1170 |
LOperand* function = UseFixed(instr->function(), rdi); |
1171 |
argument_count_ -= instr->argument_count(); |
|
1172 | 1171 |
LInvokeFunction* result = new(zone()) LInvokeFunction(function); |
1173 | 1172 |
return MarkAsCall(DefineFixed(result, rax), instr, CANNOT_DEOPTIMIZE_EAGERLY); |
1174 | 1173 |
} |
... | ... | |
1215 | 1214 |
|
1216 | 1215 |
|
1217 | 1216 |
LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) { |
1218 |
LOperand* input = UseFixedDouble(instr->value(), xmm1); |
|
1217 |
ASSERT(instr->representation().IsDouble()); |
|
1218 |
ASSERT(instr->value()->representation().IsDouble()); |
|
1219 |
LOperand* input = UseRegisterAtStart(instr->value()); |
|
1219 | 1220 |
LMathLog* result = new(zone()) LMathLog(input); |
1220 |
return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
|
|
1221 |
return DefineSameAsFirst(result);
|
|
1221 | 1222 |
} |
1222 | 1223 |
|
1223 | 1224 |
|
... | ... | |
1270 | 1271 |
LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { |
1271 | 1272 |
ASSERT(instr->key()->representation().IsTagged()); |
1272 | 1273 |
LOperand* key = UseFixed(instr->key(), rcx); |
1273 |
argument_count_ -= instr->argument_count(); |
|
1274 | 1274 |
LCallKeyed* result = new(zone()) LCallKeyed(key); |
1275 | 1275 |
return MarkAsCall(DefineFixed(result, rax), instr); |
1276 | 1276 |
} |
1277 | 1277 |
|
1278 | 1278 |
|
1279 | 1279 |
LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { |
1280 |
argument_count_ -= instr->argument_count(); |
|
1281 | 1280 |
return MarkAsCall(DefineFixed(new(zone()) LCallNamed, rax), instr); |
1282 | 1281 |
} |
1283 | 1282 |
|
1284 | 1283 |
|
1285 | 1284 |
LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { |
1286 |
argument_count_ -= instr->argument_count(); |
|
1287 | 1285 |
return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, rax), instr); |
1288 | 1286 |
} |
1289 | 1287 |
|
1290 | 1288 |
|
1291 | 1289 |
LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { |
1292 |
argument_count_ -= instr->argument_count(); |
|
1293 | 1290 |
return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, rax), instr); |
1294 | 1291 |
} |
1295 | 1292 |
|
1296 | 1293 |
|
1297 | 1294 |
LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { |
1298 | 1295 |
LOperand* constructor = UseFixed(instr->constructor(), rdi); |
1299 |
argument_count_ -= instr->argument_count(); |
|
1300 | 1296 |
LCallNew* result = new(zone()) LCallNew(constructor); |
1301 | 1297 |
return MarkAsCall(DefineFixed(result, rax), instr); |
1302 | 1298 |
} |
... | ... | |
1304 | 1300 |
|
1305 | 1301 |
LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) { |
1306 | 1302 |
LOperand* constructor = UseFixed(instr->constructor(), rdi); |
1307 |
argument_count_ -= instr->argument_count(); |
|
1308 | 1303 |
LCallNewArray* result = new(zone()) LCallNewArray(constructor); |
1309 | 1304 |
return MarkAsCall(DefineFixed(result, rax), instr); |
1310 | 1305 |
} |
... | ... | |
1312 | 1307 |
|
1313 | 1308 |
LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { |
1314 | 1309 |
LOperand* function = UseFixed(instr->function(), rdi); |
1315 |
argument_count_ -= instr->argument_count(); |
|
1316 | 1310 |
LCallFunction* result = new(zone()) LCallFunction(function); |
1317 | 1311 |
return MarkAsCall(DefineFixed(result, rax), instr); |
1318 | 1312 |
} |
1319 | 1313 |
|
1320 | 1314 |
|
1321 | 1315 |
LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { |
1322 |
argument_count_ -= instr->argument_count(); |
|
1323 | 1316 |
return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, rax), instr); |
1324 | 1317 |
} |
1325 | 1318 |
|
... | ... | |
1348 | 1341 |
if (instr->representation().IsSmiOrInteger32()) { |
1349 | 1342 |
ASSERT(instr->left()->representation().Equals(instr->representation())); |
1350 | 1343 |
ASSERT(instr->right()->representation().Equals(instr->representation())); |
1344 |
ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32)); |
|
1351 | 1345 |
|
1352 | 1346 |
LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
1353 | 1347 |
LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
1354 | 1348 |
return DefineSameAsFirst(new(zone()) LBitI(left, right)); |
1355 | 1349 |
} else { |
1356 |
ASSERT(instr->representation().IsTagged()); |
|
1357 |
ASSERT(instr->left()->representation().IsTagged()); |
|
1358 |
ASSERT(instr->right()->representation().IsTagged()); |
|
1359 |
|
|
1360 |
LOperand* left = UseFixed(instr->left(), rdx); |
|
1361 |
LOperand* right = UseFixed(instr->right(), rax); |
|
1362 |
LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right); |
|
1363 |
return MarkAsCall(DefineFixed(result, rax), instr); |
|
1350 |
return DoArithmeticT(instr->op(), instr); |
|
1364 | 1351 |
} |
1365 | 1352 |
} |
1366 | 1353 |
|
1367 | 1354 |
|
1368 | 1355 |
LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
1369 |
if (instr->representation().IsDouble()) { |
|
1370 |
return DoArithmeticD(Token::DIV, instr); |
|
1371 |
} else if (instr->representation().IsSmiOrInteger32()) { |
|
1356 |
if (instr->representation().IsSmiOrInteger32()) { |
|
1372 | 1357 |
ASSERT(instr->left()->representation().Equals(instr->representation())); |
1373 | 1358 |
ASSERT(instr->right()->representation().Equals(instr->representation())); |
1374 | 1359 |
if (instr->HasPowerOf2Divisor()) { |
... | ... | |
1385 | 1370 |
LOperand* divisor = UseRegister(instr->right()); |
1386 | 1371 |
LDivI* result = new(zone()) LDivI(dividend, divisor, temp); |
1387 | 1372 |
return AssignEnvironment(DefineFixed(result, rax)); |
1373 |
} else if (instr->representation().IsDouble()) { |
|
1374 |
return DoArithmeticD(Token::DIV, instr); |
|
1388 | 1375 |
} else { |
1389 |
ASSERT(instr->representation().IsTagged()); |
|
1390 | 1376 |
return DoArithmeticT(Token::DIV, instr); |
1391 | 1377 |
} |
1392 | 1378 |
} |
... | ... | |
1485 | 1471 |
? AssignEnvironment(result) |
1486 | 1472 |
: result; |
1487 | 1473 |
} |
1488 |
} else if (instr->representation().IsTagged()) {
|
|
1489 |
return DoArithmeticT(Token::MOD, instr);
|
|
1474 |
} else if (instr->representation().IsDouble()) {
|
|
1475 |
return DoArithmeticD(Token::MOD, instr);
|
|
1490 | 1476 |
} else { |
1491 |
ASSERT(instr->representation().IsDouble()); |
|
1492 |
// We call a C function for double modulo. It can't trigger a GC. We need to |
|
1493 |
// use fixed result register for the call. |
|
1494 |
// TODO(fschneider): Allow any register as input registers. |
|
1495 |
LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, |
|
1496 |
UseFixedDouble(left, xmm2), |
|
1497 |
UseFixedDouble(right, xmm1)); |
|
1498 |
return MarkAsCall(DefineFixedDouble(mod, xmm1), instr); |
|
1477 |
return DoArithmeticT(Token::MOD, instr); |
|
1499 | 1478 |
} |
1500 | 1479 |
} |
1501 | 1480 |
|
... | ... | |
1515 | 1494 |
} else if (instr->representation().IsDouble()) { |
1516 | 1495 |
return DoArithmeticD(Token::MUL, instr); |
1517 | 1496 |
} else { |
1518 |
ASSERT(instr->representation().IsTagged()); |
|
1519 | 1497 |
return DoArithmeticT(Token::MUL, instr); |
1520 | 1498 |
} |
1521 | 1499 |
} |
... | ... | |
1536 | 1514 |
} else if (instr->representation().IsDouble()) { |
1537 | 1515 |
return DoArithmeticD(Token::SUB, instr); |
1538 | 1516 |
} else { |
1539 |
ASSERT(instr->representation().IsTagged()); |
|
1540 | 1517 |
return DoArithmeticT(Token::SUB, instr); |
1541 | 1518 |
} |
1542 | 1519 |
} |
... | ... | |
1568 | 1545 |
} else if (instr->representation().IsDouble()) { |
1569 | 1546 |
return DoArithmeticD(Token::ADD, instr); |
1570 | 1547 |
} else { |
1571 |
ASSERT(instr->representation().IsTagged()); |
|
1572 | 1548 |
return DoArithmeticT(Token::ADD, instr); |
1573 | 1549 |
} |
1574 | 1550 |
return NULL; |
... | ... | |
1662 | 1638 |
|
1663 | 1639 |
LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( |
1664 | 1640 |
HCompareObjectEqAndBranch* instr) { |
1641 |
LInstruction* goto_instr = CheckElideControlInstruction(instr); |
|
1642 |
if (goto_instr != NULL) return goto_instr; |
|
1665 | 1643 |
LOperand* left = UseRegisterAtStart(instr->left()); |
1666 | 1644 |
LOperand* right = UseRegisterOrConstantAtStart(instr->right()); |
1667 | 1645 |
return new(zone()) LCmpObjectEqAndBranch(left, right); |
... | ... | |
1670 | 1648 |
|
1671 | 1649 |
LInstruction* LChunkBuilder::DoCompareHoleAndBranch( |
1672 | 1650 |
HCompareHoleAndBranch* instr) { |
1673 |
LOperand* object = UseRegisterAtStart(instr->object());
|
|
1674 |
return new(zone()) LCmpHoleAndBranch(object);
|
|
1651 |
LOperand* value = UseRegisterAtStart(instr->value());
|
|
1652 |
return new(zone()) LCmpHoleAndBranch(value);
|
|
1675 | 1653 |
} |
1676 | 1654 |
|
1677 | 1655 |
|
... | ... | |
1803 | 1781 |
} |
1804 | 1782 |
|
1805 | 1783 |
|
1784 |
LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { |
|
1785 |
// The control instruction marking the end of a block that completed |
|
1786 |
// abruptly (e.g., threw an exception). There is nothing specific to do. |
|
1787 |
return NULL; |
|
1788 |
} |
|
1789 |
|
|
1790 |
|
|
1806 | 1791 |
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { |
1807 | 1792 |
LOperand* value = UseFixed(instr->value(), rax); |
1808 | 1793 |
return MarkAsCall(new(zone()) LThrow(value), instr); |
... | ... | |
1837 | 1822 |
// building a stack frame. |
1838 | 1823 |
if (from.IsTagged()) { |
1839 | 1824 |
if (to.IsDouble()) { |
1840 |
info()->MarkAsDeferredCalling(); |
|
1841 | 1825 |
LOperand* value = UseRegister(instr->value()); |
1842 | 1826 |
LNumberUntagD* res = new(zone()) LNumberUntagD(value); |
1843 | 1827 |
return AssignEnvironment(DefineAsRegister(res)); |
... | ... | |
1899 | 1883 |
} else if (to.IsSmi()) { |
1900 | 1884 |
HValue* val = instr->value(); |
1901 | 1885 |
LOperand* value = UseRegister(val); |
1902 |
LInstruction* result = |
|
1903 |
DefineAsRegister(new(zone()) LInteger32ToSmi(value)); |
|
1904 |
if (val->HasRange() && val->range()->IsInSmiRange()) { |
|
1905 |
return result; |
|
1886 |
LInstruction* result = NULL; |
|
1887 |
if (val->CheckFlag(HInstruction::kUint32)) { |
|
1888 |
result = DefineAsRegister(new(zone()) LUint32ToSmi(value)); |
|
1889 |
if (val->HasRange() && val->range()->IsInSmiRange() && |
|
1890 |
val->range()->upper() != kMaxInt) { |
|
1891 |
return result; |
|
1892 |
} |
|
1893 |
} else { |
|
1894 |
result = DefineAsRegister(new(zone()) LInteger32ToSmi(value)); |
|
1895 |
if (val->HasRange() && val->range()->IsInSmiRange()) { |
|
1896 |
return result; |
|
1897 |
} |
|
1906 | 1898 |
} |
1907 | 1899 |
return AssignEnvironment(result); |
1908 | 1900 |
} else { |
... | ... | |
1934 | 1926 |
} |
1935 | 1927 |
|
1936 | 1928 |
|
1937 |
LInstruction* LChunkBuilder::DoIsNumberAndBranch(HIsNumberAndBranch* instr) { |
|
1938 |
return new(zone()) LIsNumberAndBranch( |
|
1939 |
UseRegisterOrConstantAtStart(instr->value())); |
|
1940 |
} |
|
1941 |
|
|
1942 |
|
|
1943 | 1929 |
LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
1944 | 1930 |
LOperand* value = UseRegisterAtStart(instr->value()); |
1945 | 1931 |
LCheckInstanceType* result = new(zone()) LCheckInstanceType(value); |
... | ... | |
2075 | 2061 |
|
2076 | 2062 |
|
2077 | 2063 |
LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { |
2078 |
if (instr->access().IsExternalMemory() && instr->access().offset() == 0) { |
|
2064 |
// Use the special mov rax, moffs64 encoding for external |
|
2065 |
// memory accesses with 64-bit word-sized values. |
|
2066 |
if (instr->access().IsExternalMemory() && |
|
2067 |
instr->access().offset() == 0 && |
|
2068 |
(instr->access().representation().IsSmi() || |
|
2069 |
instr->access().representation().IsTagged() || |
|
2070 |
instr->access().representation().IsHeapObject() || |
|
2071 |
instr->access().representation().IsExternal())) { |
|
2079 | 2072 |
LOperand* obj = UseRegisterOrConstantAtStart(instr->object()); |
2080 | 2073 |
return DefineFixed(new(zone()) LLoadNamedField(obj), rax); |
2081 | 2074 |
} |
... | ... | |
2098 | 2091 |
} |
2099 | 2092 |
|
2100 | 2093 |
|
2094 |
LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { |
|
2095 |
return DefineAsRegister(new(zone()) LLoadRoot); |
|
2096 |
} |
|
2097 |
|
|
2098 |
|
|
2101 | 2099 |
LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( |
2102 | 2100 |
HLoadExternalArrayPointer* instr) { |
2103 | 2101 |
LOperand* input = UseRegisterAtStart(instr->value()); |
... | ... | |
2391 | 2389 |
|
2392 | 2390 |
|
2393 | 2391 |
LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { |
2394 |
argument_count_ -= instr->argument_count(); |
|
2395 | 2392 |
return MarkAsCall(DefineFixed(new(zone()) LCallStub, rax), instr); |
2396 | 2393 |
} |
2397 | 2394 |
|
... | ... | |
2513 | 2510 |
if (env->entry()->arguments_pushed()) { |
2514 | 2511 |
int argument_count = env->arguments_environment()->parameter_count(); |
2515 | 2512 |
pop = new(zone()) LDrop(argument_count); |
2516 |
argument_count_ -= argument_count;
|
|
2513 |
ASSERT(instr->argument_delta() == -argument_count);
|
|
2517 | 2514 |
} |
2518 | 2515 |
|
2519 | 2516 |
HEnvironment* outer = current_block_->last_environment()-> |
Also available in: Unified diff