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

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 551080: Refactor GenericBinaryOperation and its helper functions to always return a R... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 11 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/ia32/codegen-ia32.h ('k') | src/x64/codegen-x64.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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 895 matching lines...) Expand 10 before | Expand all | Expand 10 after
906 OverwriteMode overwrite_mode) { 906 OverwriteMode overwrite_mode) {
907 Comment cmnt(masm_, "[ BinaryOperation"); 907 Comment cmnt(masm_, "[ BinaryOperation");
908 Comment cmnt_token(masm_, Token::String(op)); 908 Comment cmnt_token(masm_, Token::String(op));
909 909
910 if (op == Token::COMMA) { 910 if (op == Token::COMMA) {
911 // Simply discard left value. 911 // Simply discard left value.
912 frame_->Nip(1); 912 frame_->Nip(1);
913 return; 913 return;
914 } 914 }
915 915
916 // Set the flags based on the operation, type and loop nesting level.
917 GenericBinaryFlags flags;
918 switch (op) {
919 case Token::BIT_OR:
920 case Token::BIT_AND:
921 case Token::BIT_XOR:
922 case Token::SHL:
923 case Token::SHR:
924 case Token::SAR:
925 // Bit operations always assume they likely operate on Smis. Still only
926 // generate the inline Smi check code if this operation is part of a loop.
927 flags = (loop_nesting() > 0)
928 ? NO_SMI_CODE_IN_STUB
929 : NO_GENERIC_BINARY_FLAGS;
930 break;
931
932 default:
933 // By default only inline the Smi check code for likely smis if this
934 // operation is part of a loop.
935 flags = ((loop_nesting() > 0) && type->IsLikelySmi())
936 ? NO_SMI_CODE_IN_STUB
937 : NO_GENERIC_BINARY_FLAGS;
938 break;
939 }
940
941 Result right = frame_->Pop(); 916 Result right = frame_->Pop();
942 Result left = frame_->Pop(); 917 Result left = frame_->Pop();
943 918
944 if (op == Token::ADD) { 919 if (op == Token::ADD) {
945 bool left_is_string = left.is_constant() && left.handle()->IsString(); 920 bool left_is_string = left.is_constant() && left.handle()->IsString();
946 bool right_is_string = right.is_constant() && right.handle()->IsString(); 921 bool right_is_string = right.is_constant() && right.handle()->IsString();
947 if (left_is_string || right_is_string) { 922 if (left_is_string || right_is_string) {
948 frame_->Push(&left); 923 frame_->Push(&left);
949 frame_->Push(&right); 924 frame_->Push(&right);
950 Result answer; 925 Result answer;
(...skipping 13 matching lines...) Expand all
964 frame_->Push(&answer); 939 frame_->Push(&answer);
965 return; 940 return;
966 } 941 }
967 // Neither operand is known to be a string. 942 // Neither operand is known to be a string.
968 } 943 }
969 944
970 bool left_is_smi = left.is_constant() && left.handle()->IsSmi(); 945 bool left_is_smi = left.is_constant() && left.handle()->IsSmi();
971 bool left_is_non_smi = left.is_constant() && !left.handle()->IsSmi(); 946 bool left_is_non_smi = left.is_constant() && !left.handle()->IsSmi();
972 bool right_is_smi = right.is_constant() && right.handle()->IsSmi(); 947 bool right_is_smi = right.is_constant() && right.handle()->IsSmi();
973 bool right_is_non_smi = right.is_constant() && !right.handle()->IsSmi(); 948 bool right_is_non_smi = right.is_constant() && !right.handle()->IsSmi();
974 bool generate_no_smi_code = false; // No smi code at all, inline or in stub.
975 949
976 if (left_is_smi && right_is_smi) { 950 if (left_is_smi && right_is_smi) {
977 // Compute the constant result at compile time, and leave it on the frame. 951 // Compute the constant result at compile time, and leave it on the frame.
978 int left_int = Smi::cast(*left.handle())->value(); 952 int left_int = Smi::cast(*left.handle())->value();
979 int right_int = Smi::cast(*right.handle())->value(); 953 int right_int = Smi::cast(*right.handle())->value();
980 if (FoldConstantSmis(op, left_int, right_int)) return; 954 if (FoldConstantSmis(op, left_int, right_int)) return;
981 } 955 }
982 956
957 Result answer;
983 if (left_is_non_smi || right_is_non_smi) { 958 if (left_is_non_smi || right_is_non_smi) {
984 // Set flag so that we go straight to the slow case, with no smi code. 959 // Go straight to the slow case, with no smi code.
985 generate_no_smi_code = true;
986 } else if (right_is_smi) {
987 ConstantSmiBinaryOperation(op, &left, right.handle(),
988 type, false, overwrite_mode);
989 return;
990 } else if (left_is_smi) {
991 ConstantSmiBinaryOperation(op, &right, left.handle(),
992 type, true, overwrite_mode);
993 return;
994 }
995
996 if (((flags & NO_SMI_CODE_IN_STUB) != 0) && !generate_no_smi_code) {
997 LikelySmiBinaryOperation(op, &left, &right, overwrite_mode);
998 } else {
999 frame_->Push(&left); 960 frame_->Push(&left);
1000 frame_->Push(&right); 961 frame_->Push(&right);
1001 // If we know the arguments aren't smis, use the binary operation stub 962 GenericBinaryOpStub stub(op, overwrite_mode, NO_SMI_CODE_IN_STUB);
1002 // that does not check for the fast smi case. 963 answer = frame_->CallStub(&stub, 2);
1003 if (generate_no_smi_code) { 964 } else if (right_is_smi) {
1004 flags = NO_SMI_CODE_IN_STUB; 965 answer = ConstantSmiBinaryOperation(op, &left, right.handle(),
966 type, false, overwrite_mode);
967 } else if (left_is_smi) {
968 answer = ConstantSmiBinaryOperation(op, &right, left.handle(),
969 type, true, overwrite_mode);
970 } else {
971 // Set the flags based on the operation, type and loop nesting level.
972 // Bit operations always assume they likely operate on Smis. Still only
973 // generate the inline Smi check code if this operation is part of a loop.
974 // For all other operations only inline the Smi check code for likely smis
975 // if the operation is part of a loop.
976 if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) {
977 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode);
978 } else {
979 frame_->Push(&left);
980 frame_->Push(&right);
981 GenericBinaryOpStub stub(op, overwrite_mode, NO_GENERIC_BINARY_FLAGS);
982 answer = frame_->CallStub(&stub, 2);
1005 } 983 }
1006 GenericBinaryOpStub stub(op, overwrite_mode, flags);
1007 Result answer = frame_->CallStub(&stub, 2);
1008 frame_->Push(&answer);
1009 } 984 }
985 frame_->Push(&answer);
1010 } 986 }
1011 987
1012 988
1013 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) { 989 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
1014 Object* answer_object = Heap::undefined_value(); 990 Object* answer_object = Heap::undefined_value();
1015 switch (op) { 991 switch (op) {
1016 case Token::ADD: 992 case Token::ADD:
1017 if (Smi::IsValid(left + right)) { 993 if (Smi::IsValid(left + right)) {
1018 answer_object = Smi::FromInt(left + right); 994 answer_object = Smi::FromInt(left + right);
1019 } 995 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1086 if (answer_object == Heap::undefined_value()) { 1062 if (answer_object == Heap::undefined_value()) {
1087 return false; 1063 return false;
1088 } 1064 }
1089 frame_->Push(Handle<Object>(answer_object)); 1065 frame_->Push(Handle<Object>(answer_object));
1090 return true; 1066 return true;
1091 } 1067 }
1092 1068
1093 1069
1094 // Implements a binary operation using a deferred code object and some 1070 // Implements a binary operation using a deferred code object and some
1095 // inline code to operate on smis quickly. 1071 // inline code to operate on smis quickly.
1096 void CodeGenerator::LikelySmiBinaryOperation(Token::Value op, 1072 Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
1097 Result* left, 1073 Result* left,
1098 Result* right, 1074 Result* right,
1099 OverwriteMode overwrite_mode) { 1075 OverwriteMode overwrite_mode) {
1076 Result answer;
1100 // Special handling of div and mod because they use fixed registers. 1077 // Special handling of div and mod because they use fixed registers.
1101 if (op == Token::DIV || op == Token::MOD) { 1078 if (op == Token::DIV || op == Token::MOD) {
1102 // We need eax as the quotient register, edx as the remainder 1079 // We need eax as the quotient register, edx as the remainder
1103 // register, neither left nor right in eax or edx, and left copied 1080 // register, neither left nor right in eax or edx, and left copied
1104 // to eax. 1081 // to eax.
1105 Result quotient; 1082 Result quotient;
1106 Result remainder; 1083 Result remainder;
1107 bool left_is_in_eax = false; 1084 bool left_is_in_eax = false;
1108 // Step 1: get eax for quotient. 1085 // Step 1: get eax for quotient.
1109 if ((left->is_register() && left->reg().is(eax)) || 1086 if ((left->is_register() && left->reg().is(eax)) ||
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1211 __ cmp(eax, 0x40000000); 1188 __ cmp(eax, 0x40000000);
1212 deferred->Branch(equal); 1189 deferred->Branch(equal);
1213 // Check that the remainder is zero. 1190 // Check that the remainder is zero.
1214 __ test(edx, Operand(edx)); 1191 __ test(edx, Operand(edx));
1215 deferred->Branch(not_zero); 1192 deferred->Branch(not_zero);
1216 // Tag the result and store it in the quotient register. 1193 // Tag the result and store it in the quotient register.
1217 __ SmiTag(eax); 1194 __ SmiTag(eax);
1218 deferred->BindExit(); 1195 deferred->BindExit();
1219 left->Unuse(); 1196 left->Unuse();
1220 right->Unuse(); 1197 right->Unuse();
1221 frame_->Push(&quotient); 1198 answer = quotient;
1222 } else { 1199 } else {
1223 ASSERT(op == Token::MOD); 1200 ASSERT(op == Token::MOD);
1224 // Check for a negative zero result. If the result is zero, and 1201 // Check for a negative zero result. If the result is zero, and
1225 // the dividend is negative, return a floating point negative 1202 // the dividend is negative, return a floating point negative
1226 // zero. The frame is unchanged in this block, so local control 1203 // zero. The frame is unchanged in this block, so local control
1227 // flow can use a Label rather than a JumpTarget. 1204 // flow can use a Label rather than a JumpTarget.
1228 Label non_zero_result; 1205 Label non_zero_result;
1229 __ test(edx, Operand(edx)); 1206 __ test(edx, Operand(edx));
1230 __ j(not_zero, &non_zero_result, taken); 1207 __ j(not_zero, &non_zero_result, taken);
1231 __ test(left->reg(), Operand(left->reg())); 1208 __ test(left->reg(), Operand(left->reg()));
1232 deferred->Branch(negative); 1209 deferred->Branch(negative);
1233 __ bind(&non_zero_result); 1210 __ bind(&non_zero_result);
1234 deferred->BindExit(); 1211 deferred->BindExit();
1235 left->Unuse(); 1212 left->Unuse();
1236 right->Unuse(); 1213 right->Unuse();
1237 frame_->Push(&remainder); 1214 answer = remainder;
1238 } 1215 }
1239 return; 1216 ASSERT(answer.is_valid());
1217 return answer;
1240 } 1218 }
1241 1219
1242 // Special handling of shift operations because they use fixed 1220 // Special handling of shift operations because they use fixed
1243 // registers. 1221 // registers.
1244 if (op == Token::SHL || op == Token::SHR || op == Token::SAR) { 1222 if (op == Token::SHL || op == Token::SHR || op == Token::SAR) {
1245 // Move left out of ecx if necessary. 1223 // Move left out of ecx if necessary.
1246 if (left->is_register() && left->reg().is(ecx)) { 1224 if (left->is_register() && left->reg().is(ecx)) {
1247 *left = allocator_->Allocate(); 1225 *left = allocator_->Allocate();
1248 ASSERT(left->is_valid()); 1226 ASSERT(left->is_valid());
1249 __ mov(left->reg(), ecx); 1227 __ mov(left->reg(), ecx);
1250 } 1228 }
1251 right->ToRegister(ecx); 1229 right->ToRegister(ecx);
1252 left->ToRegister(); 1230 left->ToRegister();
1253 ASSERT(left->is_register() && !left->reg().is(ecx)); 1231 ASSERT(left->is_register() && !left->reg().is(ecx));
1254 ASSERT(right->is_register() && right->reg().is(ecx)); 1232 ASSERT(right->is_register() && right->reg().is(ecx));
1255 1233
1256 // We will modify right, it must be spilled. 1234 // We will modify right, it must be spilled.
1257 frame_->Spill(ecx); 1235 frame_->Spill(ecx);
1258 1236
1259 // Use a fresh answer register to avoid spilling the left operand. 1237 // Use a fresh answer register to avoid spilling the left operand.
1260 Result answer = allocator_->Allocate(); 1238 answer = allocator_->Allocate();
1261 ASSERT(answer.is_valid()); 1239 ASSERT(answer.is_valid());
1262 // Check that both operands are smis using the answer register as a 1240 // Check that both operands are smis using the answer register as a
1263 // temporary. 1241 // temporary.
1264 DeferredInlineBinaryOperation* deferred = 1242 DeferredInlineBinaryOperation* deferred =
1265 new DeferredInlineBinaryOperation(op, 1243 new DeferredInlineBinaryOperation(op,
1266 answer.reg(), 1244 answer.reg(),
1267 left->reg(), 1245 left->reg(),
1268 ecx, 1246 ecx,
1269 overwrite_mode); 1247 overwrite_mode);
1270 __ mov(answer.reg(), left->reg()); 1248 __ mov(answer.reg(), left->reg());
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1314 break; 1292 break;
1315 } 1293 }
1316 default: 1294 default:
1317 UNREACHABLE(); 1295 UNREACHABLE();
1318 } 1296 }
1319 // Smi-tag the result in answer. 1297 // Smi-tag the result in answer.
1320 __ SmiTag(answer.reg()); 1298 __ SmiTag(answer.reg());
1321 deferred->BindExit(); 1299 deferred->BindExit();
1322 left->Unuse(); 1300 left->Unuse();
1323 right->Unuse(); 1301 right->Unuse();
1324 frame_->Push(&answer); 1302 ASSERT(answer.is_valid());
1325 return; 1303 return answer;
1326 } 1304 }
1327 1305
1328 // Handle the other binary operations. 1306 // Handle the other binary operations.
1329 left->ToRegister(); 1307 left->ToRegister();
1330 right->ToRegister(); 1308 right->ToRegister();
1331 // A newly allocated register answer is used to hold the answer. The 1309 // A newly allocated register answer is used to hold the answer. The
1332 // registers containing left and right are not modified so they don't 1310 // registers containing left and right are not modified so they don't
1333 // need to be spilled in the fast case. 1311 // need to be spilled in the fast case.
1334 Result answer = allocator_->Allocate(); 1312 answer = allocator_->Allocate();
1335 ASSERT(answer.is_valid()); 1313 ASSERT(answer.is_valid());
1336 1314
1337 // Perform the smi tag check. 1315 // Perform the smi tag check.
1338 DeferredInlineBinaryOperation* deferred = 1316 DeferredInlineBinaryOperation* deferred =
1339 new DeferredInlineBinaryOperation(op, 1317 new DeferredInlineBinaryOperation(op,
1340 answer.reg(), 1318 answer.reg(),
1341 left->reg(), 1319 left->reg(),
1342 right->reg(), 1320 right->reg(),
1343 overwrite_mode); 1321 overwrite_mode);
1344 if (left->reg().is(right->reg())) { 1322 if (left->reg().is(right->reg())) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1399 __ xor_(answer.reg(), Operand(right->reg())); 1377 __ xor_(answer.reg(), Operand(right->reg()));
1400 break; 1378 break;
1401 1379
1402 default: 1380 default:
1403 UNREACHABLE(); 1381 UNREACHABLE();
1404 break; 1382 break;
1405 } 1383 }
1406 deferred->BindExit(); 1384 deferred->BindExit();
1407 left->Unuse(); 1385 left->Unuse();
1408 right->Unuse(); 1386 right->Unuse();
1409 frame_->Push(&answer); 1387 ASSERT(answer.is_valid());
1388 return answer;
1410 } 1389 }
1411 1390
1412 1391
1413 // Call the appropriate binary operation stub to compute src op value 1392 // Call the appropriate binary operation stub to compute src op value
1414 // and leave the result in dst. 1393 // and leave the result in dst.
1415 class DeferredInlineSmiOperation: public DeferredCode { 1394 class DeferredInlineSmiOperation: public DeferredCode {
1416 public: 1395 public:
1417 DeferredInlineSmiOperation(Token::Value op, 1396 DeferredInlineSmiOperation(Token::Value op,
1418 Register dst, 1397 Register dst,
1419 Register src, 1398 Register src,
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1568 1547
1569 void DeferredInlineSmiSub::Generate() { 1548 void DeferredInlineSmiSub::Generate() {
1570 // Undo the optimistic sub operation and call the shared stub. 1549 // Undo the optimistic sub operation and call the shared stub.
1571 __ add(Operand(dst_), Immediate(value_)); 1550 __ add(Operand(dst_), Immediate(value_));
1572 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, NO_SMI_CODE_IN_STUB); 1551 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, NO_SMI_CODE_IN_STUB);
1573 igostub.GenerateCall(masm_, dst_, value_); 1552 igostub.GenerateCall(masm_, dst_, value_);
1574 if (!dst_.is(eax)) __ mov(dst_, eax); 1553 if (!dst_.is(eax)) __ mov(dst_, eax);
1575 } 1554 }
1576 1555
1577 1556
1578 void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 1557 Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
1579 Result* operand, 1558 Result* operand,
1580 Handle<Object> value, 1559 Handle<Object> value,
1581 StaticType* type, 1560 StaticType* type,
1582 bool reversed, 1561 bool reversed,
1583 OverwriteMode overwrite_mode) { 1562 OverwriteMode overwrite_mode) {
1584 // NOTE: This is an attempt to inline (a bit) more of the code for 1563 // NOTE: This is an attempt to inline (a bit) more of the code for
1585 // some possible smi operations (like + and -) when (at least) one 1564 // some possible smi operations (like + and -) when (at least) one
1586 // of the operands is a constant smi. 1565 // of the operands is a constant smi.
1587 // Consumes the argument "operand". 1566 // Consumes the argument "operand".
1588
1589 // TODO(199): Optimize some special cases of operations involving a 1567 // TODO(199): Optimize some special cases of operations involving a
1590 // smi literal (multiply by 2, shift by 0, etc.). 1568 // smi literal (multiply by 2, shift by 0, etc.).
1591 if (IsUnsafeSmi(value)) { 1569 if (IsUnsafeSmi(value)) {
1592 Result unsafe_operand(value); 1570 Result unsafe_operand(value);
1593 if (reversed) { 1571 if (reversed) {
1594 LikelySmiBinaryOperation(op, &unsafe_operand, operand, 1572 return LikelySmiBinaryOperation(op, &unsafe_operand, operand,
1595 overwrite_mode); 1573 overwrite_mode);
1596 } else { 1574 } else {
1597 LikelySmiBinaryOperation(op, operand, &unsafe_operand, 1575 return LikelySmiBinaryOperation(op, operand, &unsafe_operand,
1598 overwrite_mode); 1576 overwrite_mode);
1599 } 1577 }
1600 ASSERT(!operand->is_valid());
1601 return;
1602 } 1578 }
1603 1579
1604 // Get the literal value. 1580 // Get the literal value.
1605 Smi* smi_value = Smi::cast(*value); 1581 Smi* smi_value = Smi::cast(*value);
1606 int int_value = smi_value->value(); 1582 int int_value = smi_value->value();
1607 1583
1584 Result answer;
1608 switch (op) { 1585 switch (op) {
1609 case Token::ADD: { 1586 case Token::ADD: {
1610 operand->ToRegister(); 1587 operand->ToRegister();
1611 frame_->Spill(operand->reg()); 1588 frame_->Spill(operand->reg());
1612 1589
1613 // Optimistically add. Call the specialized add stub if the 1590 // Optimistically add. Call the specialized add stub if the
1614 // result is not a smi or overflows. 1591 // result is not a smi or overflows.
1615 DeferredCode* deferred = NULL; 1592 DeferredCode* deferred = NULL;
1616 if (reversed) { 1593 if (reversed) {
1617 deferred = new DeferredInlineSmiAddReversed(operand->reg(), 1594 deferred = new DeferredInlineSmiAddReversed(operand->reg(),
1618 smi_value, 1595 smi_value,
1619 overwrite_mode); 1596 overwrite_mode);
1620 } else { 1597 } else {
1621 deferred = new DeferredInlineSmiAdd(operand->reg(), 1598 deferred = new DeferredInlineSmiAdd(operand->reg(),
1622 smi_value, 1599 smi_value,
1623 overwrite_mode); 1600 overwrite_mode);
1624 } 1601 }
1625 __ add(Operand(operand->reg()), Immediate(value)); 1602 __ add(Operand(operand->reg()), Immediate(value));
1626 deferred->Branch(overflow); 1603 deferred->Branch(overflow);
1627 __ test(operand->reg(), Immediate(kSmiTagMask)); 1604 __ test(operand->reg(), Immediate(kSmiTagMask));
1628 deferred->Branch(not_zero); 1605 deferred->Branch(not_zero);
1629 deferred->BindExit(); 1606 deferred->BindExit();
1630 frame_->Push(operand); 1607 answer = *operand;
1631 break; 1608 break;
1632 } 1609 }
1633 1610
1634 case Token::SUB: { 1611 case Token::SUB: {
1635 DeferredCode* deferred = NULL; 1612 DeferredCode* deferred = NULL;
1636 Result answer; // Only allocate a new register if reversed.
1637 if (reversed) { 1613 if (reversed) {
1638 // The reversed case is only hit when the right operand is not a 1614 // The reversed case is only hit when the right operand is not a
1639 // constant. 1615 // constant.
1640 ASSERT(operand->is_register()); 1616 ASSERT(operand->is_register());
1641 answer = allocator()->Allocate(); 1617 answer = allocator()->Allocate();
1642 ASSERT(answer.is_valid()); 1618 ASSERT(answer.is_valid());
1643 __ Set(answer.reg(), Immediate(value)); 1619 __ Set(answer.reg(), Immediate(value));
1644 deferred = new DeferredInlineSmiOperationReversed(op, 1620 deferred = new DeferredInlineSmiOperationReversed(op,
1645 answer.reg(), 1621 answer.reg(),
1646 smi_value, 1622 smi_value,
1647 operand->reg(), 1623 operand->reg(),
1648 overwrite_mode); 1624 overwrite_mode);
1649 __ sub(answer.reg(), Operand(operand->reg())); 1625 __ sub(answer.reg(), Operand(operand->reg()));
1650 } else { 1626 } else {
1651 operand->ToRegister(); 1627 operand->ToRegister();
1652 frame_->Spill(operand->reg()); 1628 frame_->Spill(operand->reg());
1653 answer = *operand; 1629 answer = *operand;
1654 deferred = new DeferredInlineSmiSub(operand->reg(), 1630 deferred = new DeferredInlineSmiSub(operand->reg(),
1655 smi_value, 1631 smi_value,
1656 overwrite_mode); 1632 overwrite_mode);
1657 __ sub(Operand(operand->reg()), Immediate(value)); 1633 __ sub(Operand(operand->reg()), Immediate(value));
1658 } 1634 }
1659 deferred->Branch(overflow); 1635 deferred->Branch(overflow);
1660 __ test(answer.reg(), Immediate(kSmiTagMask)); 1636 __ test(answer.reg(), Immediate(kSmiTagMask));
1661 deferred->Branch(not_zero); 1637 deferred->Branch(not_zero);
1662 deferred->BindExit(); 1638 deferred->BindExit();
1663 operand->Unuse(); 1639 operand->Unuse();
1664 frame_->Push(&answer);
1665 break; 1640 break;
1666 } 1641 }
1667 1642
1668 case Token::SAR: 1643 case Token::SAR:
1669 if (reversed) { 1644 if (reversed) {
1670 Result constant_operand(value); 1645 Result constant_operand(value);
1671 LikelySmiBinaryOperation(op, &constant_operand, operand, 1646 answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
1672 overwrite_mode); 1647 overwrite_mode);
1673 } else { 1648 } else {
1674 // Only the least significant 5 bits of the shift value are used. 1649 // Only the least significant 5 bits of the shift value are used.
1675 // In the slow case, this masking is done inside the runtime call. 1650 // In the slow case, this masking is done inside the runtime call.
1676 int shift_value = int_value & 0x1f; 1651 int shift_value = int_value & 0x1f;
1677 operand->ToRegister(); 1652 operand->ToRegister();
1678 frame_->Spill(operand->reg()); 1653 frame_->Spill(operand->reg());
1679 DeferredInlineSmiOperation* deferred = 1654 DeferredInlineSmiOperation* deferred =
1680 new DeferredInlineSmiOperation(op, 1655 new DeferredInlineSmiOperation(op,
1681 operand->reg(), 1656 operand->reg(),
1682 operand->reg(), 1657 operand->reg(),
1683 smi_value, 1658 smi_value,
1684 overwrite_mode); 1659 overwrite_mode);
1685 __ test(operand->reg(), Immediate(kSmiTagMask)); 1660 __ test(operand->reg(), Immediate(kSmiTagMask));
1686 deferred->Branch(not_zero); 1661 deferred->Branch(not_zero);
1687 if (shift_value > 0) { 1662 if (shift_value > 0) {
1688 __ sar(operand->reg(), shift_value); 1663 __ sar(operand->reg(), shift_value);
1689 __ and_(operand->reg(), ~kSmiTagMask); 1664 __ and_(operand->reg(), ~kSmiTagMask);
1690 } 1665 }
1691 deferred->BindExit(); 1666 deferred->BindExit();
1692 frame_->Push(operand); 1667 answer = *operand;
1693 } 1668 }
1694 break; 1669 break;
1695 1670
1696 case Token::SHR: 1671 case Token::SHR:
1697 if (reversed) { 1672 if (reversed) {
1698 Result constant_operand(value); 1673 Result constant_operand(value);
1699 LikelySmiBinaryOperation(op, &constant_operand, operand, 1674 answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
1700 overwrite_mode); 1675 overwrite_mode);
1701 } else { 1676 } else {
1702 // Only the least significant 5 bits of the shift value are used. 1677 // Only the least significant 5 bits of the shift value are used.
1703 // In the slow case, this masking is done inside the runtime call. 1678 // In the slow case, this masking is done inside the runtime call.
1704 int shift_value = int_value & 0x1f; 1679 int shift_value = int_value & 0x1f;
1705 operand->ToRegister(); 1680 operand->ToRegister();
1706 Result answer = allocator()->Allocate(); 1681 answer = allocator()->Allocate();
1707 ASSERT(answer.is_valid()); 1682 ASSERT(answer.is_valid());
1708 DeferredInlineSmiOperation* deferred = 1683 DeferredInlineSmiOperation* deferred =
1709 new DeferredInlineSmiOperation(op, 1684 new DeferredInlineSmiOperation(op,
1710 answer.reg(), 1685 answer.reg(),
1711 operand->reg(), 1686 operand->reg(),
1712 smi_value, 1687 smi_value,
1713 overwrite_mode); 1688 overwrite_mode);
1714 __ test(operand->reg(), Immediate(kSmiTagMask)); 1689 __ test(operand->reg(), Immediate(kSmiTagMask));
1715 deferred->Branch(not_zero); 1690 deferred->Branch(not_zero);
1716 __ mov(answer.reg(), operand->reg()); 1691 __ mov(answer.reg(), operand->reg());
1717 __ SmiUntag(answer.reg()); 1692 __ SmiUntag(answer.reg());
1718 __ shr(answer.reg(), shift_value); 1693 __ shr(answer.reg(), shift_value);
1719 // A negative Smi shifted right two is in the positive Smi range. 1694 // A negative Smi shifted right two is in the positive Smi range.
1720 if (shift_value < 2) { 1695 if (shift_value < 2) {
1721 __ test(answer.reg(), Immediate(0xc0000000)); 1696 __ test(answer.reg(), Immediate(0xc0000000));
1722 deferred->Branch(not_zero); 1697 deferred->Branch(not_zero);
1723 } 1698 }
1724 operand->Unuse(); 1699 operand->Unuse();
1725 __ SmiTag(answer.reg()); 1700 __ SmiTag(answer.reg());
1726 deferred->BindExit(); 1701 deferred->BindExit();
1727 frame_->Push(&answer);
1728 } 1702 }
1729 break; 1703 break;
1730 1704
1731 case Token::SHL: 1705 case Token::SHL:
1732 if (reversed) { 1706 if (reversed) {
1733 Result right; 1707 Result right;
1734 Result right_copy_in_ecx; 1708 Result right_copy_in_ecx;
1735 1709
1736 // Make sure to get a copy of the right operand into ecx. This 1710 // Make sure to get a copy of the right operand into ecx. This
1737 // allows us to modify it without having to restore it in the 1711 // allows us to modify it without having to restore it in the
1738 // deferred code. 1712 // deferred code.
1739 operand->ToRegister(); 1713 operand->ToRegister();
1740 if (operand->reg().is(ecx)) { 1714 if (operand->reg().is(ecx)) {
1741 right = allocator()->Allocate(); 1715 right = allocator()->Allocate();
1742 __ mov(right.reg(), ecx); 1716 __ mov(right.reg(), ecx);
1743 frame_->Spill(ecx); 1717 frame_->Spill(ecx);
1744 right_copy_in_ecx = *operand; 1718 right_copy_in_ecx = *operand;
1745 } else { 1719 } else {
1746 right_copy_in_ecx = allocator()->Allocate(ecx); 1720 right_copy_in_ecx = allocator()->Allocate(ecx);
1747 __ mov(ecx, operand->reg()); 1721 __ mov(ecx, operand->reg());
1748 right = *operand; 1722 right = *operand;
1749 } 1723 }
1750 operand->Unuse(); 1724 operand->Unuse();
1751 1725
1752 Result answer = allocator()->Allocate(); 1726 answer = allocator()->Allocate();
1753 DeferredInlineSmiOperationReversed* deferred = 1727 DeferredInlineSmiOperationReversed* deferred =
1754 new DeferredInlineSmiOperationReversed(op, 1728 new DeferredInlineSmiOperationReversed(op,
1755 answer.reg(), 1729 answer.reg(),
1756 smi_value, 1730 smi_value,
1757 right.reg(), 1731 right.reg(),
1758 overwrite_mode); 1732 overwrite_mode);
1759 __ mov(answer.reg(), Immediate(int_value)); 1733 __ mov(answer.reg(), Immediate(int_value));
1760 __ sar(ecx, kSmiTagSize); 1734 __ sar(ecx, kSmiTagSize);
1761 deferred->Branch(carry); 1735 deferred->Branch(carry);
1762 __ shl_cl(answer.reg()); 1736 __ shl_cl(answer.reg());
1763 __ cmp(answer.reg(), 0xc0000000); 1737 __ cmp(answer.reg(), 0xc0000000);
1764 deferred->Branch(sign); 1738 deferred->Branch(sign);
1765 __ SmiTag(answer.reg()); 1739 __ SmiTag(answer.reg());
1766 1740
1767 deferred->BindExit(); 1741 deferred->BindExit();
1768 frame_->Push(&answer);
1769 } else { 1742 } else {
1770 // Only the least significant 5 bits of the shift value are used. 1743 // Only the least significant 5 bits of the shift value are used.
1771 // In the slow case, this masking is done inside the runtime call. 1744 // In the slow case, this masking is done inside the runtime call.
1772 int shift_value = int_value & 0x1f; 1745 int shift_value = int_value & 0x1f;
1773 operand->ToRegister(); 1746 operand->ToRegister();
1774 if (shift_value == 0) { 1747 if (shift_value == 0) {
1775 // Spill operand so it can be overwritten in the slow case. 1748 // Spill operand so it can be overwritten in the slow case.
1776 frame_->Spill(operand->reg()); 1749 frame_->Spill(operand->reg());
1777 DeferredInlineSmiOperation* deferred = 1750 DeferredInlineSmiOperation* deferred =
1778 new DeferredInlineSmiOperation(op, 1751 new DeferredInlineSmiOperation(op,
1779 operand->reg(), 1752 operand->reg(),
1780 operand->reg(), 1753 operand->reg(),
1781 smi_value, 1754 smi_value,
1782 overwrite_mode); 1755 overwrite_mode);
1783 __ test(operand->reg(), Immediate(kSmiTagMask)); 1756 __ test(operand->reg(), Immediate(kSmiTagMask));
1784 deferred->Branch(not_zero); 1757 deferred->Branch(not_zero);
1785 deferred->BindExit(); 1758 deferred->BindExit();
1786 frame_->Push(operand); 1759 answer = *operand;
1787 } else { 1760 } else {
1788 // Use a fresh temporary for nonzero shift values. 1761 // Use a fresh temporary for nonzero shift values.
1789 Result answer = allocator()->Allocate(); 1762 answer = allocator()->Allocate();
1790 ASSERT(answer.is_valid()); 1763 ASSERT(answer.is_valid());
1791 DeferredInlineSmiOperation* deferred = 1764 DeferredInlineSmiOperation* deferred =
1792 new DeferredInlineSmiOperation(op, 1765 new DeferredInlineSmiOperation(op,
1793 answer.reg(), 1766 answer.reg(),
1794 operand->reg(), 1767 operand->reg(),
1795 smi_value, 1768 smi_value,
1796 overwrite_mode); 1769 overwrite_mode);
1797 __ test(operand->reg(), Immediate(kSmiTagMask)); 1770 __ test(operand->reg(), Immediate(kSmiTagMask));
1798 deferred->Branch(not_zero); 1771 deferred->Branch(not_zero);
1799 __ mov(answer.reg(), operand->reg()); 1772 __ mov(answer.reg(), operand->reg());
1800 ASSERT(kSmiTag == 0); // adjust code if not the case 1773 ASSERT(kSmiTag == 0); // adjust code if not the case
1801 // We do no shifts, only the Smi conversion, if shift_value is 1. 1774 // We do no shifts, only the Smi conversion, if shift_value is 1.
1802 if (shift_value > 1) { 1775 if (shift_value > 1) {
1803 __ shl(answer.reg(), shift_value - 1); 1776 __ shl(answer.reg(), shift_value - 1);
1804 } 1777 }
1805 // Convert int result to Smi, checking that it is in int range. 1778 // Convert int result to Smi, checking that it is in int range.
1806 ASSERT(kSmiTagSize == 1); // adjust code if not the case 1779 ASSERT(kSmiTagSize == 1); // adjust code if not the case
1807 __ add(answer.reg(), Operand(answer.reg())); 1780 __ add(answer.reg(), Operand(answer.reg()));
1808 deferred->Branch(overflow); 1781 deferred->Branch(overflow);
1809 deferred->BindExit(); 1782 deferred->BindExit();
1810 operand->Unuse(); 1783 operand->Unuse();
1811 frame_->Push(&answer);
1812 } 1784 }
1813 } 1785 }
1814 break; 1786 break;
1815 1787
1816 case Token::BIT_OR: 1788 case Token::BIT_OR:
1817 case Token::BIT_XOR: 1789 case Token::BIT_XOR:
1818 case Token::BIT_AND: { 1790 case Token::BIT_AND: {
1819 operand->ToRegister(); 1791 operand->ToRegister();
1820 frame_->Spill(operand->reg()); 1792 frame_->Spill(operand->reg());
1821 DeferredCode* deferred = NULL; 1793 DeferredCode* deferred = NULL;
(...skipping 18 matching lines...) Expand all
1840 if (int_value != 0) { 1812 if (int_value != 0) {
1841 __ xor_(Operand(operand->reg()), Immediate(value)); 1813 __ xor_(Operand(operand->reg()), Immediate(value));
1842 } 1814 }
1843 } else { 1815 } else {
1844 ASSERT(op == Token::BIT_OR); 1816 ASSERT(op == Token::BIT_OR);
1845 if (int_value != 0) { 1817 if (int_value != 0) {
1846 __ or_(Operand(operand->reg()), Immediate(value)); 1818 __ or_(Operand(operand->reg()), Immediate(value));
1847 } 1819 }
1848 } 1820 }
1849 deferred->BindExit(); 1821 deferred->BindExit();
1850 frame_->Push(operand); 1822 answer = *operand;
1851 break; 1823 break;
1852 } 1824 }
1853 1825
1854 // Generate inline code for mod of powers of 2 and negative powers of 2. 1826 // Generate inline code for mod of powers of 2 and negative powers of 2.
1855 case Token::MOD: 1827 case Token::MOD:
1856 if (!reversed && 1828 if (!reversed &&
1857 int_value != 0 && 1829 int_value != 0 &&
1858 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { 1830 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) {
1859 operand->ToRegister(); 1831 operand->ToRegister();
1860 frame_->Spill(operand->reg()); 1832 frame_->Spill(operand->reg());
1861 DeferredCode* deferred = new DeferredInlineSmiOperation(op, 1833 DeferredCode* deferred = new DeferredInlineSmiOperation(op,
1862 operand->reg(), 1834 operand->reg(),
1863 operand->reg(), 1835 operand->reg(),
1864 smi_value, 1836 smi_value,
1865 overwrite_mode); 1837 overwrite_mode);
1866 // Check for negative or non-Smi left hand side. 1838 // Check for negative or non-Smi left hand side.
1867 __ test(operand->reg(), Immediate(kSmiTagMask | 0x80000000)); 1839 __ test(operand->reg(), Immediate(kSmiTagMask | 0x80000000));
1868 deferred->Branch(not_zero); 1840 deferred->Branch(not_zero);
1869 if (int_value < 0) int_value = -int_value; 1841 if (int_value < 0) int_value = -int_value;
1870 if (int_value == 1) { 1842 if (int_value == 1) {
1871 __ mov(operand->reg(), Immediate(Smi::FromInt(0))); 1843 __ mov(operand->reg(), Immediate(Smi::FromInt(0)));
1872 } else { 1844 } else {
1873 __ and_(operand->reg(), (int_value << kSmiTagSize) - 1); 1845 __ and_(operand->reg(), (int_value << kSmiTagSize) - 1);
1874 } 1846 }
1875 deferred->BindExit(); 1847 deferred->BindExit();
1876 frame_->Push(operand); 1848 answer = *operand;
1877 break; 1849 break;
1878 } 1850 }
1879 // Fall through if we did not find a power of 2 on the right hand side! 1851 // Fall through if we did not find a power of 2 on the right hand side!
1880 1852
1881 default: { 1853 default: {
1882 Result constant_operand(value); 1854 Result constant_operand(value);
1883 if (reversed) { 1855 if (reversed) {
1884 LikelySmiBinaryOperation(op, &constant_operand, operand, 1856 answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
1885 overwrite_mode); 1857 overwrite_mode);
1886 } else { 1858 } else {
1887 LikelySmiBinaryOperation(op, operand, &constant_operand, 1859 answer = LikelySmiBinaryOperation(op, operand, &constant_operand,
1888 overwrite_mode); 1860 overwrite_mode);
1889 } 1861 }
1890 break; 1862 break;
1891 } 1863 }
1892 } 1864 }
1893 ASSERT(!operand->is_valid()); 1865 ASSERT(answer.is_valid());
1866 return answer;
1894 } 1867 }
1895 1868
1896 1869
1897 static bool CouldBeNaN(const Result& result) { 1870 static bool CouldBeNaN(const Result& result) {
1898 if (!result.is_constant()) return true; 1871 if (!result.is_constant()) return true;
1899 if (!result.handle()->IsHeapNumber()) return false; 1872 if (!result.handle()->IsHeapNumber()) return false;
1900 return isnan(HeapNumber::cast(*result.handle())->value()); 1873 return isnan(HeapNumber::cast(*result.handle())->value());
1901 } 1874 }
1902 1875
1903 1876
(...skipping 7905 matching lines...) Expand 10 before | Expand all | Expand 10 after
9809 9782
9810 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 9783 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
9811 // tagged as a small integer. 9784 // tagged as a small integer.
9812 __ bind(&runtime); 9785 __ bind(&runtime);
9813 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); 9786 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1);
9814 } 9787 }
9815 9788
9816 #undef __ 9789 #undef __
9817 9790
9818 } } // namespace v8::internal 9791 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/x64/codegen-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698