Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: src/a64/lithium-a64.cc

Issue 196133017: Experimental parser: merge r19949 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/a64/lithium-a64.h ('k') | src/a64/lithium-codegen-a64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, 499 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
500 HInstruction* hinstr, 500 HInstruction* hinstr,
501 CanDeoptimize can_deoptimize) { 501 CanDeoptimize can_deoptimize) {
502 info()->MarkAsNonDeferredCalling(); 502 info()->MarkAsNonDeferredCalling();
503 #ifdef DEBUG 503 #ifdef DEBUG
504 instr->VerifyCall(); 504 instr->VerifyCall();
505 #endif 505 #endif
506 instr->MarkAsCall(); 506 instr->MarkAsCall();
507 instr = AssignPointerMap(instr); 507 instr = AssignPointerMap(instr);
508 508
509 if (hinstr->HasObservableSideEffects()) {
510 ASSERT(hinstr->next()->IsSimulate());
511 HSimulate* sim = HSimulate::cast(hinstr->next());
512 ASSERT(instruction_pending_deoptimization_environment_ == NULL);
513 ASSERT(pending_deoptimization_ast_id_.IsNone());
514 instruction_pending_deoptimization_environment_ = instr;
515 pending_deoptimization_ast_id_ = sim->ast_id();
516 }
517
518 // If instruction does not have side-effects lazy deoptimization 509 // If instruction does not have side-effects lazy deoptimization
519 // after the call will try to deoptimize to the point before the call. 510 // after the call will try to deoptimize to the point before the call.
520 // Thus we still need to attach environment to this call even if 511 // Thus we still need to attach environment to this call even if
521 // call sequence can not deoptimize eagerly. 512 // call sequence can not deoptimize eagerly.
522 bool needs_environment = 513 bool needs_environment =
523 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || 514 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
524 !hinstr->HasObservableSideEffects(); 515 !hinstr->HasObservableSideEffects();
525 if (needs_environment && !instr->HasEnvironment()) { 516 if (needs_environment && !instr->HasEnvironment()) {
526 instr = AssignEnvironment(instr); 517 instr = AssignEnvironment(instr);
527 } 518 }
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 } 720 }
730 #endif 721 #endif
731 722
732 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { 723 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
733 instr = AssignPointerMap(instr); 724 instr = AssignPointerMap(instr);
734 } 725 }
735 if (FLAG_stress_environments && !instr->HasEnvironment()) { 726 if (FLAG_stress_environments && !instr->HasEnvironment()) {
736 instr = AssignEnvironment(instr); 727 instr = AssignEnvironment(instr);
737 } 728 }
738 chunk_->AddInstruction(instr, current_block_); 729 chunk_->AddInstruction(instr, current_block_);
730
731 if (instr->IsCall()) {
732 HValue* hydrogen_value_for_lazy_bailout = current;
733 LInstruction* instruction_needing_environment = NULL;
734 if (current->HasObservableSideEffects()) {
735 HSimulate* sim = HSimulate::cast(current->next());
736 instruction_needing_environment = instr;
737 sim->ReplayEnvironment(current_block_->last_environment());
738 hydrogen_value_for_lazy_bailout = sim;
739 }
740 LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout());
741 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
742 chunk_->AddInstruction(bailout, current_block_);
743 if (instruction_needing_environment != NULL) {
744 // Store the lazy deopt environment with the instruction if needed.
745 // Right now it is only used for LInstanceOfKnownGlobal.
746 instruction_needing_environment->
747 SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
748 }
749 }
739 } 750 }
740 current_instruction_ = old_current; 751 current_instruction_ = old_current;
741 } 752 }
742 753
743 754
744 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { 755 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
745 HEnvironment* hydrogen_env = current_block_->last_environment(); 756 HEnvironment* hydrogen_env = current_block_->last_environment();
746 int argument_index_accumulator = 0; 757 int argument_index_accumulator = 0;
747 ZoneList<HValue*> objects_to_materialize(0, zone()); 758 ZoneList<HValue*> objects_to_materialize(0, zone());
748 instr->set_environment(CreateEnvironment(hydrogen_env, 759 instr->set_environment(CreateEnvironment(hydrogen_env,
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 } 871 }
861 } 872 }
862 873
863 874
864 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { 875 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
865 info()->MarkAsDeferredCalling(); 876 info()->MarkAsDeferredCalling();
866 LOperand* context = UseAny(instr->context()); 877 LOperand* context = UseAny(instr->context());
867 LOperand* size = UseRegisterOrConstant(instr->size()); 878 LOperand* size = UseRegisterOrConstant(instr->size());
868 LOperand* temp1 = TempRegister(); 879 LOperand* temp1 = TempRegister();
869 LOperand* temp2 = TempRegister(); 880 LOperand* temp2 = TempRegister();
870 LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2); 881 LOperand* temp3 = instr->MustPrefillWithFiller() ? TempRegister() : NULL;
882 LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2, temp3);
871 return AssignPointerMap(DefineAsRegister(result)); 883 return AssignPointerMap(DefineAsRegister(result));
872 } 884 }
873 885
874 886
875 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { 887 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
876 LOperand* function = UseFixed(instr->function(), x1); 888 LOperand* function = UseFixed(instr->function(), x1);
877 LOperand* receiver = UseFixed(instr->receiver(), x0); 889 LOperand* receiver = UseFixed(instr->receiver(), x0);
878 LOperand* length = UseFixed(instr->length(), x2); 890 LOperand* length = UseFixed(instr->length(), x2);
879 LOperand* elements = UseFixed(instr->elements(), x3); 891 LOperand* elements = UseFixed(instr->elements(), x3);
880 LApplyArguments* result = new(zone()) LApplyArguments(function, 892 LApplyArguments* result = new(zone()) LApplyArguments(function,
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
1134 TempRegister()); 1146 TempRegister());
1135 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); 1147 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1136 } else { 1148 } else {
1137 STATIC_ASSERT((kMinInt == Smi::kMinValue) && 1149 STATIC_ASSERT((kMinInt == Smi::kMinValue) &&
1138 (kMaxInt == Smi::kMaxValue)); 1150 (kMaxInt == Smi::kMaxValue));
1139 LOperand* value = UseRegisterAtStart(instr->value()); 1151 LOperand* value = UseRegisterAtStart(instr->value());
1140 return DefineAsRegister(new(zone()) LSmiTag(value)); 1152 return DefineAsRegister(new(zone()) LSmiTag(value));
1141 } 1153 }
1142 } else if (to.IsSmi()) { 1154 } else if (to.IsSmi()) {
1143 LOperand* value = UseRegisterAtStart(instr->value()); 1155 LOperand* value = UseRegisterAtStart(instr->value());
1156 LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value));
1144 if (instr->value()->CheckFlag(HInstruction::kUint32)) { 1157 if (instr->value()->CheckFlag(HInstruction::kUint32)) {
1145 LUint32ToSmi* result = new(zone()) LUint32ToSmi(value); 1158 result = AssignEnvironment(result);
1146 return AssignEnvironment(DefineAsRegister(result));
1147 } else {
1148 // This cannot deoptimize because an A64 smi can represent any int32.
1149 return DefineAsRegister(new(zone()) LInteger32ToSmi(value));
1150 } 1159 }
1160 return result;
1151 } else { 1161 } else {
1152 ASSERT(to.IsDouble()); 1162 ASSERT(to.IsDouble());
1153 if (instr->value()->CheckFlag(HInstruction::kUint32)) { 1163 if (instr->value()->CheckFlag(HInstruction::kUint32)) {
1154 return DefineAsRegister( 1164 return DefineAsRegister(
1155 new(zone()) LUint32ToDouble(UseRegisterAtStart(instr->value()))); 1165 new(zone()) LUint32ToDouble(UseRegisterAtStart(instr->value())));
1156 } else { 1166 } else {
1157 return DefineAsRegister( 1167 return DefineAsRegister(
1158 new(zone()) LInteger32ToDouble(UseRegisterAtStart(instr->value()))); 1168 new(zone()) LInteger32ToDouble(UseRegisterAtStart(instr->value())));
1159 } 1169 }
1160 } 1170 }
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
1361 LOperand* context = UseFixed(instr->context(), cp); 1371 LOperand* context = UseFixed(instr->context(), cp);
1362 return MarkAsCall(new(zone()) LDeclareGlobals(context), instr); 1372 return MarkAsCall(new(zone()) LDeclareGlobals(context), instr);
1363 } 1373 }
1364 1374
1365 1375
1366 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { 1376 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
1367 return AssignEnvironment(new(zone()) LDeoptimize); 1377 return AssignEnvironment(new(zone()) LDeoptimize);
1368 } 1378 }
1369 1379
1370 1380
1381 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) {
1382 ASSERT(instr->representation().IsInteger32());
1383 ASSERT(instr->left()->representation().Equals(instr->representation()));
1384 ASSERT(instr->right()->representation().Equals(instr->representation()));
1385 LOperand* dividend = UseRegister(instr->left());
1386 int32_t divisor = instr->right()->GetInteger32Constant();
1387 LInstruction* result = DefineAsRegister(new(zone()) LDivByPowerOf2I(
1388 dividend, divisor));
1389 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1390 (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) ||
1391 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1392 divisor != 1 && divisor != -1)) {
1393 result = AssignEnvironment(result);
1394 }
1395 return result;
1396 }
1397
1398
1399 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) {
1400 ASSERT(instr->representation().IsInteger32());
1401 ASSERT(instr->left()->representation().Equals(instr->representation()));
1402 ASSERT(instr->right()->representation().Equals(instr->representation()));
1403 LOperand* dividend = UseRegister(instr->left());
1404 int32_t divisor = instr->right()->GetInteger32Constant();
1405 LOperand* temp = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)
1406 ? NULL : TempRegister();
1407 LInstruction* result = DefineAsRegister(new(zone()) LDivByConstI(
1408 dividend, divisor, temp));
1409 if (divisor == 0 ||
1410 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1411 !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1412 result = AssignEnvironment(result);
1413 }
1414 return result;
1415 }
1416
1417
1418 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) {
1419 ASSERT(instr->representation().IsSmiOrInteger32());
1420 ASSERT(instr->left()->representation().Equals(instr->representation()));
1421 ASSERT(instr->right()->representation().Equals(instr->representation()));
1422 LOperand* dividend = UseRegister(instr->left());
1423 LOperand* divisor = UseRegister(instr->right());
1424 LOperand* temp = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)
1425 ? NULL : TempRegister();
1426 LDivI* div = new(zone()) LDivI(dividend, divisor, temp);
1427 return AssignEnvironment(DefineAsRegister(div));
1428 }
1429
1430
1371 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { 1431 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1372 if (instr->representation().IsInteger32()) { 1432 if (instr->representation().IsSmiOrInteger32()) {
1373 // TODO(all): Update this case to support smi inputs.
1374 ASSERT(instr->left()->representation().Equals(instr->representation()));
1375 ASSERT(instr->right()->representation().Equals(instr->representation()));
1376 if (instr->RightIsPowerOf2()) { 1433 if (instr->RightIsPowerOf2()) {
1377 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); 1434 return DoDivByPowerOf2I(instr);
1378 LOperand* value = UseRegister(instr->left()); 1435 } else if (instr->right()->IsConstant()) {
1379 LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL); 1436 return DoDivByConstI(instr);
1380 return AssignEnvironment(DefineAsRegister(div)); 1437 } else {
1438 return DoDivI(instr);
1381 } 1439 }
1382 LOperand* dividend = UseRegister(instr->left());
1383 LOperand* divisor = UseRegister(instr->right());
1384 LOperand* temp = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)
1385 ? NULL : TempRegister();
1386 LDivI* div = new(zone()) LDivI(dividend, divisor, temp);
1387 return AssignEnvironment(DefineAsRegister(div));
1388 } else if (instr->representation().IsDouble()) { 1440 } else if (instr->representation().IsDouble()) {
1389 return DoArithmeticD(Token::DIV, instr); 1441 return DoArithmeticD(Token::DIV, instr);
1390 } else { 1442 } else {
1391 return DoArithmeticT(Token::DIV, instr); 1443 return DoArithmeticT(Token::DIV, instr);
1392 } 1444 }
1393 } 1445 }
1394 1446
1395 1447
1396 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) { 1448 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
1397 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value()))); 1449 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value())));
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
1685 return DefineAsRegister(new(zone()) LLoadRoot); 1737 return DefineAsRegister(new(zone()) LLoadRoot);
1686 } 1738 }
1687 1739
1688 1740
1689 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) { 1741 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1690 LOperand* map = UseRegisterAtStart(instr->value()); 1742 LOperand* map = UseRegisterAtStart(instr->value());
1691 return DefineAsRegister(new(zone()) LMapEnumLength(map)); 1743 return DefineAsRegister(new(zone()) LMapEnumLength(map));
1692 } 1744 }
1693 1745
1694 1746
1747 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
1748 ASSERT(instr->representation().IsInteger32());
1749 ASSERT(instr->left()->representation().Equals(instr->representation()));
1750 ASSERT(instr->right()->representation().Equals(instr->representation()));
1751 LOperand* dividend = UseRegisterAtStart(instr->left());
1752 int32_t divisor = instr->right()->GetInteger32Constant();
1753 LInstruction* result = DefineAsRegister(new(zone()) LFlooringDivByPowerOf2I(
1754 dividend, divisor));
1755 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1756 (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) {
1757 result = AssignEnvironment(result);
1758 }
1759 return result;
1760 }
1761
1762
1763 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
1764 ASSERT(instr->representation().IsInteger32());
1765 ASSERT(instr->left()->representation().Equals(instr->representation()));
1766 ASSERT(instr->right()->representation().Equals(instr->representation()));
1767 LOperand* dividend = UseRegister(instr->left());
1768 int32_t divisor = instr->right()->GetInteger32Constant();
1769 LInstruction* result =
1770 DefineAsRegister(new(zone()) LFlooringDivByConstI(dividend, divisor));
1771 bool can_deopt =
1772 divisor == 0 ||
1773 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0);
1774 return can_deopt ? AssignEnvironment(result) : result;
1775 }
1776
1777
1778 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) {
1779 LOperand* dividend = UseRegister(instr->left());
1780 LOperand* divisor = UseRegister(instr->right());
1781 LOperand* remainder = TempRegister();
1782 LInstruction* result =
1783 DefineAsRegister(new(zone()) LFlooringDivI(dividend, divisor, remainder));
1784 return AssignEnvironment(result);
1785 }
1786
1787
1695 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { 1788 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1696 HValue* right = instr->right(); 1789 if (instr->RightIsPowerOf2()) {
1697 LOperand* dividend = UseRegister(instr->left()); 1790 return DoFlooringDivByPowerOf2I(instr);
1698 LOperand* divisor = UseRegister(right); 1791 } else if (false && instr->right()->IsConstant()) {
1699 LOperand* remainder = TempRegister(); 1792 return DoFlooringDivByConstI(instr); // TODO(svenpanne) Fix and re-enable.
1700 return AssignEnvironment(DefineAsRegister( 1793 } else {
1701 new(zone()) LMathFloorOfDiv(dividend, divisor, remainder))); 1794 return DoFlooringDivI(instr);
1795 }
1702 } 1796 }
1703 1797
1704 1798
1705 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { 1799 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1706 LOperand* left = NULL; 1800 LOperand* left = NULL;
1707 LOperand* right = NULL; 1801 LOperand* right = NULL;
1708 if (instr->representation().IsSmiOrInteger32()) { 1802 if (instr->representation().IsSmiOrInteger32()) {
1709 ASSERT(instr->left()->representation().Equals(instr->representation())); 1803 ASSERT(instr->left()->representation().Equals(instr->representation()));
1710 ASSERT(instr->right()->representation().Equals(instr->representation())); 1804 ASSERT(instr->right()->representation().Equals(instr->representation()));
1711 left = UseRegisterAtStart(instr->BetterLeftOperand()); 1805 left = UseRegisterAtStart(instr->BetterLeftOperand());
1712 right = UseRegisterOrConstantAtStart(instr->BetterRightOperand()); 1806 right = UseRegisterOrConstantAtStart(instr->BetterRightOperand());
1713 } else { 1807 } else {
1714 ASSERT(instr->representation().IsDouble()); 1808 ASSERT(instr->representation().IsDouble());
1715 ASSERT(instr->left()->representation().IsDouble()); 1809 ASSERT(instr->left()->representation().IsDouble());
1716 ASSERT(instr->right()->representation().IsDouble()); 1810 ASSERT(instr->right()->representation().IsDouble());
1717 left = UseRegisterAtStart(instr->left()); 1811 left = UseRegisterAtStart(instr->left());
1718 right = UseRegisterAtStart(instr->right()); 1812 right = UseRegisterAtStart(instr->right());
1719 } 1813 }
1720 return DefineAsRegister(new(zone()) LMathMinMax(left, right)); 1814 return DefineAsRegister(new(zone()) LMathMinMax(left, right));
1721 } 1815 }
1722 1816
1723 1817
1724 LInstruction* LChunkBuilder::DoMod(HMod* hmod) { 1818 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
1725 HValue* hleft = hmod->left(); 1819 ASSERT(instr->representation().IsInteger32());
1726 HValue* hright = hmod->right(); 1820 ASSERT(instr->left()->representation().Equals(instr->representation()));
1821 ASSERT(instr->right()->representation().Equals(instr->representation()));
1822 LOperand* dividend = UseRegisterAtStart(instr->left());
1823 int32_t divisor = instr->right()->GetInteger32Constant();
1824 LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I(
1825 dividend, divisor));
1826 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1827 result = AssignEnvironment(result);
1828 }
1829 return result;
1830 }
1727 1831
1728 // TODO(jbramley): Add smi support.
1729 if (hmod->representation().IsInteger32()) {
1730 ASSERT(hleft->representation().IsInteger32());
1731 ASSERT(hleft->representation().IsInteger32());
1732 LOperand* left_op;
1733 LOperand* right_op;
1734 1832
1735 if (hmod->RightIsPowerOf2()) { 1833 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) {
1736 left_op = UseRegisterAtStart(hleft); 1834 ASSERT(instr->representation().IsInteger32());
1737 right_op = UseConstant(hright); 1835 ASSERT(instr->left()->representation().Equals(instr->representation()));
1836 ASSERT(instr->right()->representation().Equals(instr->representation()));
1837 LOperand* dividend = UseRegister(instr->left());
1838 int32_t divisor = instr->right()->GetInteger32Constant();
1839 LOperand* temp = TempRegister();
1840 LInstruction* result = DefineAsRegister(new(zone()) LModByConstI(
1841 dividend, divisor, temp));
1842 if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1843 result = AssignEnvironment(result);
1844 }
1845 return result;
1846 }
1847
1848
1849 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
1850 ASSERT(instr->representation().IsSmiOrInteger32());
1851 ASSERT(instr->left()->representation().Equals(instr->representation()));
1852 ASSERT(instr->right()->representation().Equals(instr->representation()));
1853 LOperand* dividend = UseRegister(instr->left());
1854 LOperand* divisor = UseRegister(instr->right());
1855 LInstruction* result = DefineAsRegister(new(zone()) LModI(dividend, divisor));
1856 if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1857 instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1858 result = AssignEnvironment(result);
1859 }
1860 return result;
1861 }
1862
1863
1864 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1865 if (instr->representation().IsSmiOrInteger32()) {
1866 if (instr->RightIsPowerOf2()) {
1867 return DoModByPowerOf2I(instr);
1868 } else if (instr->right()->IsConstant()) {
1869 return DoModByConstI(instr);
1738 } else { 1870 } else {
1739 right_op = UseRegister(hright); 1871 return DoModI(instr);
1740 left_op = UseRegister(hleft);
1741 } 1872 }
1742 1873 } else if (instr->representation().IsDouble()) {
1743 LModI* lmod = new(zone()) LModI(left_op, right_op); 1874 return DoArithmeticD(Token::MOD, instr);
1744
1745 if (hmod->right()->CanBeZero() ||
1746 (hmod->CheckFlag(HValue::kBailoutOnMinusZero) &&
1747 hmod->left()->CanBeNegative() && hmod->CanBeZero())) {
1748 AssignEnvironment(lmod);
1749 }
1750 return DefineAsRegister(lmod);
1751
1752 } else if (hmod->representation().IsSmiOrTagged()) {
1753 return DoArithmeticT(Token::MOD, hmod);
1754 } else { 1875 } else {
1755 return DoArithmeticD(Token::MOD, hmod); 1876 return DoArithmeticT(Token::MOD, instr);
1756 } 1877 }
1757 } 1878 }
1758 1879
1759 1880
1760 LInstruction* LChunkBuilder::DoMul(HMul* instr) { 1881 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1761 if (instr->representation().IsSmiOrInteger32()) { 1882 if (instr->representation().IsSmiOrInteger32()) {
1762 ASSERT(instr->left()->representation().Equals(instr->representation())); 1883 ASSERT(instr->left()->representation().Equals(instr->representation()));
1763 ASSERT(instr->right()->representation().Equals(instr->representation())); 1884 ASSERT(instr->right()->representation().Equals(instr->representation()));
1764 1885
1765 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow); 1886 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
(...skipping 23 matching lines...) Expand all
1789 LMulConstIS* mul = new(zone()) LMulConstIS(left, right); 1910 LMulConstIS* mul = new(zone()) LMulConstIS(left, right);
1790 if (needs_environment) AssignEnvironment(mul); 1911 if (needs_environment) AssignEnvironment(mul);
1791 return DefineAsRegister(mul); 1912 return DefineAsRegister(mul);
1792 } 1913 }
1793 } 1914 }
1794 1915
1795 // LMulI/S can handle all cases, but it requires that a register is 1916 // LMulI/S can handle all cases, but it requires that a register is
1796 // allocated for the second operand. 1917 // allocated for the second operand.
1797 LInstruction* result; 1918 LInstruction* result;
1798 if (instr->representation().IsSmi()) { 1919 if (instr->representation().IsSmi()) {
1799 // TODO(jbramley/rmcilroy): Fix LMulS so we can UseRegisterAtStart here. 1920 LOperand* right = UseRegisterAtStart(most_const);
1800 LOperand* right = UseRegister(most_const);
1801 result = DefineAsRegister(new(zone()) LMulS(left, right)); 1921 result = DefineAsRegister(new(zone()) LMulS(left, right));
1802 } else { 1922 } else {
1803 LOperand* right = UseRegisterAtStart(most_const); 1923 LOperand* right = UseRegisterAtStart(most_const);
1804 result = DefineAsRegister(new(zone()) LMulI(left, right)); 1924 result = DefineAsRegister(new(zone()) LMulI(left, right));
1805 } 1925 }
1806 if (needs_environment) AssignEnvironment(result); 1926 if (needs_environment) AssignEnvironment(result);
1807 return result; 1927 return result;
1808 } else if (instr->representation().IsDouble()) { 1928 } else if (instr->representation().IsDouble()) {
1809 return DoArithmeticD(Token::MUL, instr); 1929 return DoArithmeticD(Token::MUL, instr);
1810 } else { 1930 } else {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1862 } 1982 }
1863 1983
1864 1984
1865 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) { 1985 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
1866 LOperand* context = UseFixed(instr->context(), cp); 1986 LOperand* context = UseFixed(instr->context(), cp);
1867 return MarkAsCall( 1987 return MarkAsCall(
1868 DefineFixed(new(zone()) LRegExpLiteral(context), x0), instr); 1988 DefineFixed(new(zone()) LRegExpLiteral(context), x0), instr);
1869 } 1989 }
1870 1990
1871 1991
1992 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) {
1993 HValue* value = instr->value();
1994 ASSERT(value->representation().IsDouble());
1995 return DefineAsRegister(new(zone()) LDoubleBits(UseRegister(value)));
1996 }
1997
1998
1999 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
2000 LOperand* lo = UseRegister(instr->lo());
2001 LOperand* hi = UseRegister(instr->hi());
2002 LOperand* temp = TempRegister();
2003 return DefineAsRegister(new(zone()) LConstructDouble(hi, lo, temp));
2004 }
2005
2006
1872 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { 2007 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1873 LOperand* context = info()->IsStub() 2008 LOperand* context = info()->IsStub()
1874 ? UseFixed(instr->context(), cp) 2009 ? UseFixed(instr->context(), cp)
1875 : NULL; 2010 : NULL;
1876 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count()); 2011 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
1877 return new(zone()) LReturn(UseFixed(instr->value(), x0), context, 2012 return new(zone()) LReturn(UseFixed(instr->value(), x0), context,
1878 parameter_count); 2013 parameter_count);
1879 } 2014 }
1880 2015
1881 2016
1882 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) { 2017 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
1883 // TODO(all): Use UseRegisterAtStart and UseRegisterOrConstantAtStart here. 2018 LOperand* string = UseRegisterAtStart(instr->string());
1884 // We cannot do it now because the debug code in the implementation changes 2019 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1885 // temp.
1886 LOperand* string = UseRegister(instr->string());
1887 LOperand* index = UseRegisterOrConstant(instr->index());
1888 LOperand* temp = TempRegister(); 2020 LOperand* temp = TempRegister();
1889 LSeqStringGetChar* result = 2021 LSeqStringGetChar* result =
1890 new(zone()) LSeqStringGetChar(string, index, temp); 2022 new(zone()) LSeqStringGetChar(string, index, temp);
1891 return DefineAsRegister(result); 2023 return DefineAsRegister(result);
1892 } 2024 }
1893 2025
1894 2026
1895 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { 2027 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1896 LOperand* string = UseRegister(instr->string()); 2028 LOperand* string = UseRegister(instr->string());
1897 LOperand* index = FLAG_debug_code 2029 LOperand* index = FLAG_debug_code
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1975 } 2107 }
1976 2108
1977 2109
1978 LInstruction* LChunkBuilder::DoShr(HShr* instr) { 2110 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1979 return DoShift(Token::SHR, instr); 2111 return DoShift(Token::SHR, instr);
1980 } 2112 }
1981 2113
1982 2114
1983 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { 2115 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
1984 instr->ReplayEnvironment(current_block_->last_environment()); 2116 instr->ReplayEnvironment(current_block_->last_environment());
1985
1986 // If there is an instruction pending deoptimization environment create a
1987 // lazy bailout instruction to capture the environment.
1988 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
1989 LInstruction* result = new(zone()) LLazyBailout;
1990 result = AssignEnvironment(result);
1991 // Store the lazy deopt environment with the instruction if needed. Right
1992 // now it is only used for LInstanceOfKnownGlobal.
1993 instruction_pending_deoptimization_environment_->
1994 SetDeferredLazyDeoptimizationEnvironment(result->environment());
1995 instruction_pending_deoptimization_environment_ = NULL;
1996 pending_deoptimization_ast_id_ = BailoutId::None();
1997 return result;
1998 }
1999
2000 return NULL; 2117 return NULL;
2001 } 2118 }
2002 2119
2003 2120
2004 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { 2121 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2005 if (instr->is_function_entry()) { 2122 if (instr->is_function_entry()) {
2006 LOperand* context = UseFixed(instr->context(), cp); 2123 LOperand* context = UseFixed(instr->context(), cp);
2007 return MarkAsCall(new(zone()) LStackCheck(context), instr); 2124 return MarkAsCall(new(zone()) LStackCheck(context), instr);
2008 } else { 2125 } else {
2009 ASSERT(instr->is_backwards_branch()); 2126 ASSERT(instr->is_backwards_branch());
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2049 } else { 2166 } else {
2050 return new(zone()) LStoreGlobalCell(value, TempRegister(), NULL); 2167 return new(zone()) LStoreGlobalCell(value, TempRegister(), NULL);
2051 } 2168 }
2052 } 2169 }
2053 2170
2054 2171
2055 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { 2172 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
2056 LOperand* temp = NULL; 2173 LOperand* temp = NULL;
2057 LOperand* elements = NULL; 2174 LOperand* elements = NULL;
2058 LOperand* val = NULL; 2175 LOperand* val = NULL;
2059 LOperand* key = NULL; 2176 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
2060 2177
2061 if (!instr->is_typed_elements() && 2178 if (!instr->is_typed_elements() &&
2062 instr->value()->representation().IsTagged() && 2179 instr->value()->representation().IsTagged() &&
2063 instr->NeedsWriteBarrier()) { 2180 instr->NeedsWriteBarrier()) {
2064 // RecordWrite() will clobber all registers. 2181 // RecordWrite() will clobber all registers.
2065 elements = UseRegisterAndClobber(instr->elements()); 2182 elements = UseRegisterAndClobber(instr->elements());
2066 val = UseRegisterAndClobber(instr->value()); 2183 val = UseRegisterAndClobber(instr->value());
2067 key = UseRegisterAndClobber(instr->key()); 2184 temp = TempRegister();
2068 } else { 2185 } else {
2069 elements = UseRegister(instr->elements()); 2186 elements = UseRegister(instr->elements());
2070 val = UseRegister(instr->value()); 2187 val = UseRegister(instr->value());
2071 key = UseRegisterOrConstantAtStart(instr->key()); 2188 temp = instr->key()->IsConstant() ? NULL : TempRegister();
2072 } 2189 }
2073 2190
2074 if (instr->is_typed_elements()) { 2191 if (instr->is_typed_elements()) {
2075 ASSERT((instr->value()->representation().IsInteger32() && 2192 ASSERT((instr->value()->representation().IsInteger32() &&
2076 !IsDoubleOrFloatElementsKind(instr->elements_kind())) || 2193 !IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
2077 (instr->value()->representation().IsDouble() && 2194 (instr->value()->representation().IsDouble() &&
2078 IsDoubleOrFloatElementsKind(instr->elements_kind()))); 2195 IsDoubleOrFloatElementsKind(instr->elements_kind())));
2079 ASSERT((instr->is_fixed_typed_array() && 2196 ASSERT((instr->is_fixed_typed_array() &&
2080 instr->elements()->representation().IsTagged()) || 2197 instr->elements()->representation().IsTagged()) ||
2081 (instr->is_external() && 2198 (instr->is_external() &&
2082 instr->elements()->representation().IsExternal())); 2199 instr->elements()->representation().IsExternal()));
2083 temp = instr->key()->IsConstant() ? NULL : TempRegister();
2084 return new(zone()) LStoreKeyedExternal(elements, key, val, temp); 2200 return new(zone()) LStoreKeyedExternal(elements, key, val, temp);
2085 2201
2086 } else if (instr->value()->representation().IsDouble()) { 2202 } else if (instr->value()->representation().IsDouble()) {
2087 ASSERT(instr->elements()->representation().IsTagged()); 2203 ASSERT(instr->elements()->representation().IsTagged());
2088
2089 // The constraint used here is UseRegister, even though the StoreKeyed
2090 // instruction may canonicalize the value in the register if it is a NaN.
2091 temp = TempRegister();
2092 return new(zone()) LStoreKeyedFixedDouble(elements, key, val, temp); 2204 return new(zone()) LStoreKeyedFixedDouble(elements, key, val, temp);
2093 2205
2094 } else { 2206 } else {
2095 ASSERT(instr->elements()->representation().IsTagged()); 2207 ASSERT(instr->elements()->representation().IsTagged());
2096 ASSERT(instr->value()->representation().IsSmiOrTagged() || 2208 ASSERT(instr->value()->representation().IsSmiOrTagged() ||
2097 instr->value()->representation().IsInteger32()); 2209 instr->value()->representation().IsInteger32());
2098
2099 temp = TempRegister();
2100 return new(zone()) LStoreKeyedFixed(elements, key, val, temp); 2210 return new(zone()) LStoreKeyedFixed(elements, key, val, temp);
2101 } 2211 }
2102 } 2212 }
2103 2213
2104 2214
2105 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { 2215 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
2106 LOperand* context = UseFixed(instr->context(), cp); 2216 LOperand* context = UseFixed(instr->context(), cp);
2107 LOperand* object = UseFixed(instr->object(), x2); 2217 LOperand* object = UseFixed(instr->object(), x2);
2108 LOperand* key = UseFixed(instr->key(), x1); 2218 LOperand* key = UseFixed(instr->key(), x1);
2109 LOperand* value = UseFixed(instr->value(), x0); 2219 LOperand* value = UseFixed(instr->value(), x0);
2110 2220
2111 ASSERT(instr->object()->representation().IsTagged()); 2221 ASSERT(instr->object()->representation().IsTagged());
2112 ASSERT(instr->key()->representation().IsTagged()); 2222 ASSERT(instr->key()->representation().IsTagged());
2113 ASSERT(instr->value()->representation().IsTagged()); 2223 ASSERT(instr->value()->representation().IsTagged());
2114 2224
2115 return MarkAsCall( 2225 return MarkAsCall(
2116 new(zone()) LStoreKeyedGeneric(context, object, key, value), instr); 2226 new(zone()) LStoreKeyedGeneric(context, object, key, value), instr);
2117 } 2227 }
2118 2228
2119 2229
2120 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { 2230 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2121 // TODO(jbramley): Optimize register usage in this instruction. For now, it
2122 // allocates everything that it might need because it keeps changing in the
2123 // merge and keeping it valid is time-consuming.
2124
2125 // TODO(jbramley): It might be beneficial to allow value to be a constant in 2231 // TODO(jbramley): It might be beneficial to allow value to be a constant in
2126 // some cases. x64 makes use of this with FLAG_track_fields, for example. 2232 // some cases. x64 makes use of this with FLAG_track_fields, for example.
2127 2233
2128 LOperand* object = UseRegister(instr->object()); 2234 LOperand* object = UseRegister(instr->object());
2129 LOperand* value = UseRegisterAndClobber(instr->value()); 2235 LOperand* value;
2130 LOperand* temp0 = TempRegister(); 2236 LOperand* temp0 = NULL;
2131 LOperand* temp1 = TempRegister(); 2237 LOperand* temp1 = NULL;
2238
2239 if (instr->access().IsExternalMemory() ||
2240 instr->field_representation().IsDouble()) {
2241 value = UseRegister(instr->value());
2242 } else if (instr->NeedsWriteBarrier()) {
2243 value = UseRegisterAndClobber(instr->value());
2244 temp0 = TempRegister();
2245 temp1 = TempRegister();
2246 } else if (instr->NeedsWriteBarrierForMap()) {
2247 value = UseRegister(instr->value());
2248 temp0 = TempRegister();
2249 temp1 = TempRegister();
2250 } else {
2251 value = UseRegister(instr->value());
2252 temp0 = TempRegister();
2253 }
2132 2254
2133 LStoreNamedField* result = 2255 LStoreNamedField* result =
2134 new(zone()) LStoreNamedField(object, value, temp0, temp1); 2256 new(zone()) LStoreNamedField(object, value, temp0, temp1);
2135 if (FLAG_track_heap_object_fields && 2257 if (instr->field_representation().IsHeapObject() &&
2136 instr->field_representation().IsHeapObject() &&
2137 !instr->value()->type().IsHeapObject()) { 2258 !instr->value()->type().IsHeapObject()) {
2138 return AssignEnvironment(result); 2259 return AssignEnvironment(result);
2139 } 2260 }
2140 return result; 2261 return result;
2141 } 2262 }
2142 2263
2143 2264
2144 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { 2265 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2145 LOperand* context = UseFixed(instr->context(), cp); 2266 LOperand* context = UseFixed(instr->context(), cp);
2146 LOperand* object = UseFixed(instr->object(), x1); 2267 LOperand* object = UseFixed(instr->object(), x1);
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
2440 2561
2441 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { 2562 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
2442 LOperand* receiver = UseRegister(instr->receiver()); 2563 LOperand* receiver = UseRegister(instr->receiver());
2443 LOperand* function = UseRegister(instr->function()); 2564 LOperand* function = UseRegister(instr->function());
2444 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function); 2565 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function);
2445 return AssignEnvironment(DefineAsRegister(result)); 2566 return AssignEnvironment(DefineAsRegister(result));
2446 } 2567 }
2447 2568
2448 2569
2449 } } // namespace v8::internal 2570 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/a64/lithium-a64.h ('k') | src/a64/lithium-codegen-a64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698