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

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

Issue 501113: Refactor smi tagging and untagging on IA-32. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years 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 | « bleeding_edge/src/ia32/builtins-ia32.cc ('k') | bleeding_edge/src/ia32/macro-assembler-ia32.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 824 matching lines...) Expand 10 before | Expand all | Expand 10 after
835 __ cmp(FieldOperand(left_, HeapObject::kMapOffset), 835 __ cmp(FieldOperand(left_, HeapObject::kMapOffset),
836 Factory::heap_number_map()); 836 Factory::heap_number_map());
837 __ j(not_equal, &call_runtime); 837 __ j(not_equal, &call_runtime);
838 __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset)); 838 __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset));
839 if (mode_ == OVERWRITE_LEFT) { 839 if (mode_ == OVERWRITE_LEFT) {
840 __ mov(dst_, left_); 840 __ mov(dst_, left_);
841 } 841 }
842 __ jmp(&load_right); 842 __ jmp(&load_right);
843 843
844 __ bind(&left_smi); 844 __ bind(&left_smi);
845 __ sar(left_, 1); 845 __ SmiUntag(left_);
846 __ cvtsi2sd(xmm0, Operand(left_)); 846 __ cvtsi2sd(xmm0, Operand(left_));
847 __ shl(left_, 1); 847 __ SmiTag(left_);
848 if (mode_ == OVERWRITE_LEFT) { 848 if (mode_ == OVERWRITE_LEFT) {
849 Label alloc_failure; 849 Label alloc_failure;
850 __ push(left_); 850 __ push(left_);
851 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); 851 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
852 __ pop(left_); 852 __ pop(left_);
853 } 853 }
854 854
855 __ bind(&load_right); 855 __ bind(&load_right);
856 __ test(right_, Immediate(kSmiTagMask)); 856 __ test(right_, Immediate(kSmiTagMask));
857 __ j(zero, &right_smi); 857 __ j(zero, &right_smi);
858 __ cmp(FieldOperand(right_, HeapObject::kMapOffset), 858 __ cmp(FieldOperand(right_, HeapObject::kMapOffset),
859 Factory::heap_number_map()); 859 Factory::heap_number_map());
860 __ j(not_equal, &call_runtime); 860 __ j(not_equal, &call_runtime);
861 __ movdbl(xmm1, FieldOperand(right_, HeapNumber::kValueOffset)); 861 __ movdbl(xmm1, FieldOperand(right_, HeapNumber::kValueOffset));
862 if (mode_ == OVERWRITE_RIGHT) { 862 if (mode_ == OVERWRITE_RIGHT) {
863 __ mov(dst_, right_); 863 __ mov(dst_, right_);
864 } else if (mode_ == NO_OVERWRITE) { 864 } else if (mode_ == NO_OVERWRITE) {
865 Label alloc_failure; 865 Label alloc_failure;
866 __ push(left_); 866 __ push(left_);
867 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); 867 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
868 __ pop(left_); 868 __ pop(left_);
869 } 869 }
870 __ jmp(&do_op); 870 __ jmp(&do_op);
871 871
872 __ bind(&right_smi); 872 __ bind(&right_smi);
873 __ sar(right_, 1); 873 __ SmiUntag(right_);
874 __ cvtsi2sd(xmm1, Operand(right_)); 874 __ cvtsi2sd(xmm1, Operand(right_));
875 __ shl(right_, 1); 875 __ SmiTag(right_);
876 if (mode_ == OVERWRITE_RIGHT || mode_ == NO_OVERWRITE) { 876 if (mode_ == OVERWRITE_RIGHT || mode_ == NO_OVERWRITE) {
877 Label alloc_failure; 877 Label alloc_failure;
878 __ push(left_); 878 __ push(left_);
879 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); 879 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
880 __ pop(left_); 880 __ pop(left_);
881 } 881 }
882 882
883 __ bind(&do_op); 883 __ bind(&do_op);
884 switch (op_) { 884 switch (op_) {
885 case Token::ADD: __ addsd(xmm0, xmm1); break; 885 case Token::ADD: __ addsd(xmm0, xmm1); break;
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
1208 // Check for the corner case of dividing the most negative smi by 1208 // Check for the corner case of dividing the most negative smi by
1209 // -1. We cannot use the overflow flag, since it is not set by 1209 // -1. We cannot use the overflow flag, since it is not set by
1210 // idiv instruction. 1210 // idiv instruction.
1211 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 1211 ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
1212 __ cmp(eax, 0x40000000); 1212 __ cmp(eax, 0x40000000);
1213 deferred->Branch(equal); 1213 deferred->Branch(equal);
1214 // Check that the remainder is zero. 1214 // Check that the remainder is zero.
1215 __ test(edx, Operand(edx)); 1215 __ test(edx, Operand(edx));
1216 deferred->Branch(not_zero); 1216 deferred->Branch(not_zero);
1217 // Tag the result and store it in the quotient register. 1217 // Tag the result and store it in the quotient register.
1218 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 1218 __ SmiTag(eax);
1219 __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
1220 deferred->BindExit(); 1219 deferred->BindExit();
1221 left->Unuse(); 1220 left->Unuse();
1222 right->Unuse(); 1221 right->Unuse();
1223 frame_->Push(&quotient); 1222 frame_->Push(&quotient);
1224 } else { 1223 } else {
1225 ASSERT(op == Token::MOD); 1224 ASSERT(op == Token::MOD);
1226 // Check for a negative zero result. If the result is zero, and 1225 // Check for a negative zero result. If the result is zero, and
1227 // the dividend is negative, return a floating point negative 1226 // the dividend is negative, return a floating point negative
1228 // zero. The frame is unchanged in this block, so local control 1227 // zero. The frame is unchanged in this block, so local control
1229 // flow can use a Label rather than a JumpTarget. 1228 // flow can use a Label rather than a JumpTarget.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1269 left->reg(), 1268 left->reg(),
1270 ecx, 1269 ecx,
1271 overwrite_mode); 1270 overwrite_mode);
1272 __ mov(answer.reg(), left->reg()); 1271 __ mov(answer.reg(), left->reg());
1273 __ or_(answer.reg(), Operand(ecx)); 1272 __ or_(answer.reg(), Operand(ecx));
1274 __ test(answer.reg(), Immediate(kSmiTagMask)); 1273 __ test(answer.reg(), Immediate(kSmiTagMask));
1275 deferred->Branch(not_zero); 1274 deferred->Branch(not_zero);
1276 1275
1277 // Untag both operands. 1276 // Untag both operands.
1278 __ mov(answer.reg(), left->reg()); 1277 __ mov(answer.reg(), left->reg());
1279 __ sar(answer.reg(), kSmiTagSize); 1278 __ SmiUntag(answer.reg());
1280 __ sar(ecx, kSmiTagSize); 1279 __ SmiUntag(ecx);
1281 // Perform the operation. 1280 // Perform the operation.
1282 switch (op) { 1281 switch (op) {
1283 case Token::SAR: 1282 case Token::SAR:
1284 __ sar_cl(answer.reg()); 1283 __ sar_cl(answer.reg());
1285 // No checks of result necessary 1284 // No checks of result necessary
1286 break; 1285 break;
1287 case Token::SHR: { 1286 case Token::SHR: {
1288 Label result_ok; 1287 Label result_ok;
1289 __ shr_cl(answer.reg()); 1288 __ shr_cl(answer.reg());
1290 // Check that the *unsigned* result fits in a smi. Neither of 1289 // Check that the *unsigned* result fits in a smi. Neither of
1291 // the two high-order bits can be set: 1290 // the two high-order bits can be set:
1292 // * 0x80000000: high bit would be lost when smi tagging. 1291 // * 0x80000000: high bit would be lost when smi tagging.
1293 // * 0x40000000: this number would convert to negative when smi 1292 // * 0x40000000: this number would convert to negative when smi
1294 // tagging. 1293 // tagging.
1295 // These two cases can only happen with shifts by 0 or 1 when 1294 // These two cases can only happen with shifts by 0 or 1 when
1296 // handed a valid smi. If the answer cannot be represented by a 1295 // handed a valid smi. If the answer cannot be represented by a
1297 // smi, restore the left and right arguments, and jump to slow 1296 // smi, restore the left and right arguments, and jump to slow
1298 // case. The low bit of the left argument may be lost, but only 1297 // case. The low bit of the left argument may be lost, but only
1299 // in a case where it is dropped anyway. 1298 // in a case where it is dropped anyway.
1300 __ test(answer.reg(), Immediate(0xc0000000)); 1299 __ test(answer.reg(), Immediate(0xc0000000));
1301 __ j(zero, &result_ok); 1300 __ j(zero, &result_ok);
1302 ASSERT(kSmiTag == 0); 1301 __ SmiTag(ecx);
1303 __ shl(ecx, kSmiTagSize);
1304 deferred->Jump(); 1302 deferred->Jump();
1305 __ bind(&result_ok); 1303 __ bind(&result_ok);
1306 break; 1304 break;
1307 } 1305 }
1308 case Token::SHL: { 1306 case Token::SHL: {
1309 Label result_ok; 1307 Label result_ok;
1310 __ shl_cl(answer.reg()); 1308 __ shl_cl(answer.reg());
1311 // Check that the *signed* result fits in a smi. 1309 // Check that the *signed* result fits in a smi.
1312 __ cmp(answer.reg(), 0xc0000000); 1310 __ cmp(answer.reg(), 0xc0000000);
1313 __ j(positive, &result_ok); 1311 __ j(positive, &result_ok);
1314 ASSERT(kSmiTag == 0); 1312 __ SmiTag(ecx);
1315 __ shl(ecx, kSmiTagSize);
1316 deferred->Jump(); 1313 deferred->Jump();
1317 __ bind(&result_ok); 1314 __ bind(&result_ok);
1318 break; 1315 break;
1319 } 1316 }
1320 default: 1317 default:
1321 UNREACHABLE(); 1318 UNREACHABLE();
1322 } 1319 }
1323 // Smi-tag the result in answer. 1320 // Smi-tag the result in answer.
1324 ASSERT(kSmiTagSize == 1); // Adjust code if not the case. 1321 __ SmiTag(answer.reg());
1325 __ lea(answer.reg(),
1326 Operand(answer.reg(), answer.reg(), times_1, kSmiTag));
1327 deferred->BindExit(); 1322 deferred->BindExit();
1328 left->Unuse(); 1323 left->Unuse();
1329 right->Unuse(); 1324 right->Unuse();
1330 frame_->Push(&answer); 1325 frame_->Push(&answer);
1331 return; 1326 return;
1332 } 1327 }
1333 1328
1334 // Handle the other binary operations. 1329 // Handle the other binary operations.
1335 left->ToRegister(); 1330 left->ToRegister();
1336 right->ToRegister(); 1331 right->ToRegister();
(...skipping 29 matching lines...) Expand all
1366 case Token::SUB: 1361 case Token::SUB:
1367 __ sub(answer.reg(), Operand(right->reg())); // Subtract optimistically. 1362 __ sub(answer.reg(), Operand(right->reg())); // Subtract optimistically.
1368 deferred->Branch(overflow); 1363 deferred->Branch(overflow);
1369 break; 1364 break;
1370 1365
1371 case Token::MUL: { 1366 case Token::MUL: {
1372 // If the smi tag is 0 we can just leave the tag on one operand. 1367 // If the smi tag is 0 we can just leave the tag on one operand.
1373 ASSERT(kSmiTag == 0); // Adjust code below if not the case. 1368 ASSERT(kSmiTag == 0); // Adjust code below if not the case.
1374 // Remove smi tag from the left operand (but keep sign). 1369 // Remove smi tag from the left operand (but keep sign).
1375 // Left-hand operand has been copied into answer. 1370 // Left-hand operand has been copied into answer.
1376 __ sar(answer.reg(), kSmiTagSize); 1371 __ SmiUntag(answer.reg());
1377 // Do multiplication of smis, leaving result in answer. 1372 // Do multiplication of smis, leaving result in answer.
1378 __ imul(answer.reg(), Operand(right->reg())); 1373 __ imul(answer.reg(), Operand(right->reg()));
1379 // Go slow on overflows. 1374 // Go slow on overflows.
1380 deferred->Branch(overflow); 1375 deferred->Branch(overflow);
1381 // Check for negative zero result. If product is zero, and one 1376 // Check for negative zero result. If product is zero, and one
1382 // argument is negative, go to slow case. The frame is unchanged 1377 // argument is negative, go to slow case. The frame is unchanged
1383 // in this block, so local control flow can use a Label rather 1378 // in this block, so local control flow can use a Label rather
1384 // than a JumpTarget. 1379 // than a JumpTarget.
1385 Label non_zero_result; 1380 Label non_zero_result;
1386 __ test(answer.reg(), Operand(answer.reg())); 1381 __ test(answer.reg(), Operand(answer.reg()));
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
1713 ASSERT(answer.is_valid()); 1708 ASSERT(answer.is_valid());
1714 DeferredInlineSmiOperation* deferred = 1709 DeferredInlineSmiOperation* deferred =
1715 new DeferredInlineSmiOperation(op, 1710 new DeferredInlineSmiOperation(op,
1716 answer.reg(), 1711 answer.reg(),
1717 operand->reg(), 1712 operand->reg(),
1718 smi_value, 1713 smi_value,
1719 overwrite_mode); 1714 overwrite_mode);
1720 __ test(operand->reg(), Immediate(kSmiTagMask)); 1715 __ test(operand->reg(), Immediate(kSmiTagMask));
1721 deferred->Branch(not_zero); 1716 deferred->Branch(not_zero);
1722 __ mov(answer.reg(), operand->reg()); 1717 __ mov(answer.reg(), operand->reg());
1723 __ sar(answer.reg(), kSmiTagSize); 1718 __ SmiUntag(answer.reg());
1724 __ shr(answer.reg(), shift_value); 1719 __ shr(answer.reg(), shift_value);
1725 // A negative Smi shifted right two is in the positive Smi range. 1720 // A negative Smi shifted right two is in the positive Smi range.
1726 if (shift_value < 2) { 1721 if (shift_value < 2) {
1727 __ test(answer.reg(), Immediate(0xc0000000)); 1722 __ test(answer.reg(), Immediate(0xc0000000));
1728 deferred->Branch(not_zero); 1723 deferred->Branch(not_zero);
1729 } 1724 }
1730 operand->Unuse(); 1725 operand->Unuse();
1731 ASSERT(kSmiTagSize == times_2); // Adjust the code if not true. 1726 __ SmiTag(answer.reg());
1732 __ lea(answer.reg(),
1733 Operand(answer.reg(), answer.reg(), times_1, kSmiTag));
1734 deferred->BindExit(); 1727 deferred->BindExit();
1735 frame_->Push(&answer); 1728 frame_->Push(&answer);
1736 } 1729 }
1737 break; 1730 break;
1738 1731
1739 case Token::SHL: 1732 case Token::SHL:
1740 if (reversed) { 1733 if (reversed) {
1741 Result constant_operand(value); 1734 Result constant_operand(value);
1742 LikelySmiBinaryOperation(op, &constant_operand, operand, 1735 LikelySmiBinaryOperation(op, &constant_operand, operand,
1743 overwrite_mode); 1736 overwrite_mode);
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after
2236 for (int i = 0; i < scope_->num_parameters(); i++) { 2229 for (int i = 0; i < scope_->num_parameters(); i++) {
2237 __ push(frame_->ParameterAt(i)); 2230 __ push(frame_->ParameterAt(i));
2238 } 2231 }
2239 __ jmp(&invoke); 2232 __ jmp(&invoke);
2240 2233
2241 // Arguments adaptor frame present. Copy arguments from there, but 2234 // Arguments adaptor frame present. Copy arguments from there, but
2242 // avoid copying too many arguments to avoid stack overflows. 2235 // avoid copying too many arguments to avoid stack overflows.
2243 __ bind(&adapted); 2236 __ bind(&adapted);
2244 static const uint32_t kArgumentsLimit = 1 * KB; 2237 static const uint32_t kArgumentsLimit = 1 * KB;
2245 __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2238 __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2246 __ shr(eax, kSmiTagSize); 2239 __ SmiUntag(eax);
2247 __ mov(ecx, Operand(eax)); 2240 __ mov(ecx, Operand(eax));
2248 __ cmp(eax, kArgumentsLimit); 2241 __ cmp(eax, kArgumentsLimit);
2249 build_args.Branch(above); 2242 build_args.Branch(above);
2250 2243
2251 // Loop through the arguments pushing them onto the execution 2244 // Loop through the arguments pushing them onto the execution
2252 // stack. We don't inform the virtual frame of the push, so we don't 2245 // stack. We don't inform the virtual frame of the push, so we don't
2253 // have to worry about getting rid of the elements from the virtual 2246 // have to worry about getting rid of the elements from the virtual
2254 // frame. 2247 // frame.
2255 Label loop; 2248 Label loop;
2256 __ bind(&loop); 2249 __ bind(&loop);
(...skipping 1006 matching lines...) Expand 10 before | Expand all | Expand 10 after
3263 3256
3264 __ mov(ecx, FieldOperand(ecx, Map::kInstanceDescriptorsOffset)); 3257 __ mov(ecx, FieldOperand(ecx, Map::kInstanceDescriptorsOffset));
3265 // Get the bridge array held in the enumeration index field. 3258 // Get the bridge array held in the enumeration index field.
3266 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); 3259 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset));
3267 // Get the cache from the bridge array. 3260 // Get the cache from the bridge array.
3268 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 3261 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
3269 3262
3270 frame_->EmitPush(eax); // <- slot 3 3263 frame_->EmitPush(eax); // <- slot 3
3271 frame_->EmitPush(edx); // <- slot 2 3264 frame_->EmitPush(edx); // <- slot 2
3272 __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset)); 3265 __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset));
3273 __ shl(eax, kSmiTagSize); 3266 __ SmiTag(eax);
3274 frame_->EmitPush(eax); // <- slot 1 3267 frame_->EmitPush(eax); // <- slot 1
3275 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0 3268 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0
3276 entry.Jump(); 3269 entry.Jump();
3277 3270
3278 fixed_array.Bind(); 3271 fixed_array.Bind();
3279 // eax: fixed array (result from call to Runtime::kGetPropertyNamesFast) 3272 // eax: fixed array (result from call to Runtime::kGetPropertyNamesFast)
3280 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 3 3273 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 3
3281 frame_->EmitPush(eax); // <- slot 2 3274 frame_->EmitPush(eax); // <- slot 2
3282 3275
3283 // Push the length of the array and the initial index onto the stack. 3276 // Push the length of the array and the initial index onto the stack.
3284 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); 3277 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
3285 __ shl(eax, kSmiTagSize); 3278 __ SmiTag(eax);
3286 frame_->EmitPush(eax); // <- slot 1 3279 frame_->EmitPush(eax); // <- slot 1
3287 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0 3280 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0
3288 3281
3289 // Condition. 3282 // Condition.
3290 entry.Bind(); 3283 entry.Bind();
3291 // Grab the current frame's height for the break and continue 3284 // Grab the current frame's height for the break and continue
3292 // targets only after all the state is pushed on the frame. 3285 // targets only after all the state is pushed on the frame.
3293 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); 3286 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
3294 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); 3287 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
3295 3288
(...skipping 1144 matching lines...) Expand 10 before | Expand all | Expand 10 after
4440 deferred->Branch(equal); 4433 deferred->Branch(equal);
4441 deferred->BindExit(); 4434 deferred->BindExit();
4442 literals.Unuse(); 4435 literals.Unuse();
4443 4436
4444 // Push the resulting array literal boilerplate on the stack. 4437 // Push the resulting array literal boilerplate on the stack.
4445 frame_->Push(&boilerplate); 4438 frame_->Push(&boilerplate);
4446 4439
4447 // Clone the boilerplate object. 4440 // Clone the boilerplate object.
4448 int length = node->values()->length(); 4441 int length = node->values()->length();
4449 Result clone; 4442 Result clone;
4450 if (node->depth() == 1 && 4443 if (node->depth() == 1) {
4451 length <= FastCloneShallowArrayStub::kMaximumLength) { 4444 if (length <= FastCloneShallowArrayStub::kMaximumLength) {
4452 FastCloneShallowArrayStub stub(length); 4445 FastCloneShallowArrayStub stub(length);
4453 clone = frame_->CallStub(&stub, 1); 4446 clone = frame_->CallStub(&stub, 1);
4447 } else {
4448 clone = frame_->CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1);
4449 }
4454 } else { 4450 } else {
4455 clone = frame_->CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); 4451 clone = frame_->CallRuntime(Runtime::kCloneLiteralBoilerplate, 1);
4456 } 4452 }
4457 // Push the newly cloned literal object as the result. 4453 // Push the newly cloned literal object as the result.
4458 frame_->Push(&clone); 4454 frame_->Push(&clone);
4459 4455
4460 // Generate code to set the elements in the array that are not 4456 // Generate code to set the elements in the array that are not
4461 // literals. 4457 // literals.
4462 for (int i = 0; i < length; i++) { 4458 for (int i = 0; i < length; i++) {
4463 Expression* value = node->values()->at(i); 4459 Expression* value = node->values()->at(i);
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after
5006 __ jmp(&got_char_code); 5002 __ jmp(&got_char_code);
5007 5003
5008 // ASCII string. 5004 // ASCII string.
5009 __ bind(&ascii_string); 5005 __ bind(&ascii_string);
5010 // Load the byte into the temp register. 5006 // Load the byte into the temp register.
5011 __ movzx_b(temp.reg(), FieldOperand(object.reg(), 5007 __ movzx_b(temp.reg(), FieldOperand(object.reg(),
5012 index.reg(), 5008 index.reg(),
5013 times_1, 5009 times_1,
5014 SeqAsciiString::kHeaderSize)); 5010 SeqAsciiString::kHeaderSize));
5015 __ bind(&got_char_code); 5011 __ bind(&got_char_code);
5016 ASSERT(kSmiTag == 0); 5012 __ SmiTag(temp.reg());
5017 __ shl(temp.reg(), kSmiTagSize);
5018 __ jmp(&end); 5013 __ jmp(&end);
5019 5014
5020 // Handle non-flat strings. 5015 // Handle non-flat strings.
5021 __ bind(&not_a_flat_string); 5016 __ bind(&not_a_flat_string);
5022 __ and_(temp.reg(), kStringRepresentationMask); 5017 __ and_(temp.reg(), kStringRepresentationMask);
5023 __ cmp(temp.reg(), kConsStringTag); 5018 __ cmp(temp.reg(), kConsStringTag);
5024 __ j(not_equal, &slow_case); 5019 __ j(not_equal, &slow_case);
5025 5020
5026 // ConsString. 5021 // ConsString.
5027 // Check that the right hand side is the empty string (ie if this is really a 5022 // Check that the right hand side is the empty string (ie if this is really a
(...skipping 1993 matching lines...) Expand 10 before | Expand all | Expand 10 after
7021 switch (op_) { 7016 switch (op_) {
7022 case Token::ADD: 7017 case Token::ADD:
7023 case Token::SUB: 7018 case Token::SUB:
7024 // Do nothing here. 7019 // Do nothing here.
7025 break; 7020 break;
7026 7021
7027 case Token::MUL: 7022 case Token::MUL:
7028 // If the smi tag is 0 we can just leave the tag on one operand. 7023 // If the smi tag is 0 we can just leave the tag on one operand.
7029 ASSERT(kSmiTag == 0); // adjust code below if not the case 7024 ASSERT(kSmiTag == 0); // adjust code below if not the case
7030 // Remove tag from one of the operands (but keep sign). 7025 // Remove tag from one of the operands (but keep sign).
7031 __ sar(eax, kSmiTagSize); 7026 __ SmiUntag(eax);
7032 // Do multiplication. 7027 // Do multiplication.
7033 __ imul(eax, Operand(ebx)); // multiplication of smis; result in eax 7028 __ imul(eax, Operand(ebx)); // multiplication of smis; result in eax
7034 // Go slow on overflows. 7029 // Go slow on overflows.
7035 __ j(overflow, slow, not_taken); 7030 __ j(overflow, slow, not_taken);
7036 // Check for negative zero result. 7031 // Check for negative zero result.
7037 __ NegativeZeroTest(eax, ecx, slow); // use ecx = x | y 7032 __ NegativeZeroTest(eax, ecx, slow); // use ecx = x | y
7038 break; 7033 break;
7039 7034
7040 case Token::DIV: 7035 case Token::DIV:
7041 // Divide edx:eax by ebx. 7036 // Divide edx:eax by ebx.
7042 __ idiv(ebx); 7037 __ idiv(ebx);
7043 // Check for the corner case of dividing the most negative smi 7038 // Check for the corner case of dividing the most negative smi
7044 // by -1. We cannot use the overflow flag, since it is not set 7039 // by -1. We cannot use the overflow flag, since it is not set
7045 // by idiv instruction. 7040 // by idiv instruction.
7046 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 7041 ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
7047 __ cmp(eax, 0x40000000); 7042 __ cmp(eax, 0x40000000);
7048 __ j(equal, slow); 7043 __ j(equal, slow);
7049 // Check for negative zero result. 7044 // Check for negative zero result.
7050 __ NegativeZeroTest(eax, ecx, slow); // use ecx = x | y 7045 __ NegativeZeroTest(eax, ecx, slow); // use ecx = x | y
7051 // Check that the remainder is zero. 7046 // Check that the remainder is zero.
7052 __ test(edx, Operand(edx)); 7047 __ test(edx, Operand(edx));
7053 __ j(not_zero, slow); 7048 __ j(not_zero, slow);
7054 // Tag the result and store it in register eax. 7049 // Tag the result and store it in register eax.
7055 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 7050 __ SmiTag(eax);
7056 __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
7057 break; 7051 break;
7058 7052
7059 case Token::MOD: 7053 case Token::MOD:
7060 // Divide edx:eax by ebx. 7054 // Divide edx:eax by ebx.
7061 __ idiv(ebx); 7055 __ idiv(ebx);
7062 // Check for negative zero result. 7056 // Check for negative zero result.
7063 __ NegativeZeroTest(edx, ecx, slow); // use ecx = x | y 7057 __ NegativeZeroTest(edx, ecx, slow); // use ecx = x | y
7064 // Move remainder to register eax. 7058 // Move remainder to register eax.
7065 __ mov(eax, Operand(edx)); 7059 __ mov(eax, Operand(edx));
7066 break; 7060 break;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
7105 case Token::SHL: 7099 case Token::SHL:
7106 __ shl_cl(eax); 7100 __ shl_cl(eax);
7107 // Check that the *signed* result fits in a smi. 7101 // Check that the *signed* result fits in a smi.
7108 __ cmp(eax, 0xc0000000); 7102 __ cmp(eax, 0xc0000000);
7109 __ j(sign, slow, not_taken); 7103 __ j(sign, slow, not_taken);
7110 break; 7104 break;
7111 default: 7105 default:
7112 UNREACHABLE(); 7106 UNREACHABLE();
7113 } 7107 }
7114 // Tag the result and store it in register eax. 7108 // Tag the result and store it in register eax.
7115 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 7109 __ SmiTag(eax);
7116 __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
7117 break; 7110 break;
7118 7111
7119 default: 7112 default:
7120 UNREACHABLE(); 7113 UNREACHABLE();
7121 break; 7114 break;
7122 } 7115 }
7123 } 7116 }
7124 7117
7125 7118
7126 void GenericBinaryOpStub::Generate(MacroAssembler* masm) { 7119 void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
7255 if (op_ == Token::SHR) { 7248 if (op_ == Token::SHR) {
7256 // Check if result is non-negative and fits in a smi. 7249 // Check if result is non-negative and fits in a smi.
7257 __ test(eax, Immediate(0xc0000000)); 7250 __ test(eax, Immediate(0xc0000000));
7258 __ j(not_zero, &non_smi_result); 7251 __ j(not_zero, &non_smi_result);
7259 } else { 7252 } else {
7260 // Check if result fits in a smi. 7253 // Check if result fits in a smi.
7261 __ cmp(eax, 0xc0000000); 7254 __ cmp(eax, 0xc0000000);
7262 __ j(negative, &non_smi_result); 7255 __ j(negative, &non_smi_result);
7263 } 7256 }
7264 // Tag smi result and return. 7257 // Tag smi result and return.
7265 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 7258 __ SmiTag(eax);
7266 __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
7267 GenerateReturn(masm); 7259 GenerateReturn(masm);
7268 7260
7269 // All ops except SHR return a signed int32 that we load in a HeapNumber. 7261 // All ops except SHR return a signed int32 that we load in a HeapNumber.
7270 if (op_ != Token::SHR) { 7262 if (op_ != Token::SHR) {
7271 __ bind(&non_smi_result); 7263 __ bind(&non_smi_result);
7272 // Allocate a heap number if needed. 7264 // Allocate a heap number if needed.
7273 __ mov(ebx, Operand(eax)); // ebx: result 7265 __ mov(ebx, Operand(eax)); // ebx: result
7274 switch (mode_) { 7266 switch (mode_) {
7275 case OVERWRITE_LEFT: 7267 case OVERWRITE_LEFT:
7276 case OVERWRITE_RIGHT: 7268 case OVERWRITE_RIGHT:
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
7604 __ j(not_equal, not_numbers); // Argument in edx is not a number. 7596 __ j(not_equal, not_numbers); // Argument in edx is not a number.
7605 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); 7597 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
7606 __ bind(&load_eax); 7598 __ bind(&load_eax);
7607 // Load operand in eax into xmm1, or branch to not_numbers. 7599 // Load operand in eax into xmm1, or branch to not_numbers.
7608 __ test(eax, Immediate(kSmiTagMask)); 7600 __ test(eax, Immediate(kSmiTagMask));
7609 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. 7601 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi.
7610 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::heap_number_map()); 7602 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::heap_number_map());
7611 __ j(equal, &load_float_eax); 7603 __ j(equal, &load_float_eax);
7612 __ jmp(not_numbers); // Argument in eax is not a number. 7604 __ jmp(not_numbers); // Argument in eax is not a number.
7613 __ bind(&load_smi_edx); 7605 __ bind(&load_smi_edx);
7614 __ sar(edx, 1); // Untag smi before converting to float. 7606 __ SmiUntag(edx); // Untag smi before converting to float.
7615 __ cvtsi2sd(xmm0, Operand(edx)); 7607 __ cvtsi2sd(xmm0, Operand(edx));
7616 __ shl(edx, 1); // Retag smi for heap number overwriting test. 7608 __ SmiTag(edx); // Retag smi for heap number overwriting test.
7617 __ jmp(&load_eax); 7609 __ jmp(&load_eax);
7618 __ bind(&load_smi_eax); 7610 __ bind(&load_smi_eax);
7619 __ sar(eax, 1); // Untag smi before converting to float. 7611 __ SmiUntag(eax); // Untag smi before converting to float.
7620 __ cvtsi2sd(xmm1, Operand(eax)); 7612 __ cvtsi2sd(xmm1, Operand(eax));
7621 __ shl(eax, 1); // Retag smi for heap number overwriting test. 7613 __ SmiTag(eax); // Retag smi for heap number overwriting test.
7622 __ jmp(&done); 7614 __ jmp(&done);
7623 __ bind(&load_float_eax); 7615 __ bind(&load_float_eax);
7624 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); 7616 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
7625 __ bind(&done); 7617 __ bind(&done);
7626 } 7618 }
7627 7619
7628 7620
7629 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, 7621 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
7630 Register scratch) { 7622 Register scratch) {
7631 Label load_smi_1, load_smi_2, done_load_1, done; 7623 Label load_smi_1, load_smi_2, done_load_1, done;
(...skipping 1280 matching lines...) Expand 10 before | Expand all | Expand 10 after
8912 __ add(Operand(dest), Immediate(2)); 8904 __ add(Operand(dest), Immediate(2));
8913 } 8905 }
8914 __ sub(Operand(count), Immediate(1)); 8906 __ sub(Operand(count), Immediate(1));
8915 __ j(not_zero, &loop); 8907 __ j(not_zero, &loop);
8916 } 8908 }
8917 8909
8918 8910
8919 #undef __ 8911 #undef __
8920 8912
8921 } } // namespace v8::internal 8913 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « bleeding_edge/src/ia32/builtins-ia32.cc ('k') | bleeding_edge/src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698