| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 __ j(not_equal, &true_result); | 266 __ j(not_equal, &true_result); |
| 267 // HeapNumber => false iff +0, -0, or NaN. | 267 // HeapNumber => false iff +0, -0, or NaN. |
| 268 // These three cases set the zero flag when compared to zero using ucomisd. | 268 // These three cases set the zero flag when compared to zero using ucomisd. |
| 269 __ xorpd(xmm0, xmm0); | 269 __ xorpd(xmm0, xmm0); |
| 270 __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); | 270 __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); |
| 271 __ j(zero, &false_result); | 271 __ j(zero, &false_result); |
| 272 // Fall through to |true_result|. | 272 // Fall through to |true_result|. |
| 273 | 273 |
| 274 // Return 1/0 for true/false in rax. | 274 // Return 1/0 for true/false in rax. |
| 275 __ bind(&true_result); | 275 __ bind(&true_result); |
| 276 __ movq(rax, Immediate(1)); | 276 __ Set(rax, 1); |
| 277 __ ret(1 * kPointerSize); | 277 __ ret(1 * kPointerSize); |
| 278 __ bind(&false_result); | 278 __ bind(&false_result); |
| 279 __ Set(rax, 0); | 279 __ Set(rax, 0); |
| 280 __ ret(1 * kPointerSize); | 280 __ ret(1 * kPointerSize); |
| 281 } | 281 } |
| 282 | 282 |
| 283 | 283 |
| 284 class FloatingPointHelper : public AllStatic { | 284 class FloatingPointHelper : public AllStatic { |
| 285 public: | 285 public: |
| 286 // Load the operands from rdx and rax into xmm0 and xmm1, as doubles. | 286 // Load the operands from rdx and rax into xmm0 and xmm1, as doubles. |
| (...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1274 Label load_arg2, done; | 1274 Label load_arg2, done; |
| 1275 | 1275 |
| 1276 __ JumpIfNotSmi(rdx, &arg1_is_object); | 1276 __ JumpIfNotSmi(rdx, &arg1_is_object); |
| 1277 __ SmiToInteger32(r8, rdx); | 1277 __ SmiToInteger32(r8, rdx); |
| 1278 __ jmp(&load_arg2); | 1278 __ jmp(&load_arg2); |
| 1279 | 1279 |
| 1280 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 1280 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
| 1281 __ bind(&check_undefined_arg1); | 1281 __ bind(&check_undefined_arg1); |
| 1282 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); | 1282 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); |
| 1283 __ j(not_equal, conversion_failure); | 1283 __ j(not_equal, conversion_failure); |
| 1284 __ movl(r8, Immediate(0)); | 1284 __ Set(r8, 0); |
| 1285 __ jmp(&load_arg2); | 1285 __ jmp(&load_arg2); |
| 1286 | 1286 |
| 1287 __ bind(&arg1_is_object); | 1287 __ bind(&arg1_is_object); |
| 1288 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), heap_number_map); | 1288 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), heap_number_map); |
| 1289 __ j(not_equal, &check_undefined_arg1); | 1289 __ j(not_equal, &check_undefined_arg1); |
| 1290 // Get the untagged integer version of the rdx heap number in rcx. | 1290 // Get the untagged integer version of the rdx heap number in rcx. |
| 1291 IntegerConvert(masm, r8, rdx); | 1291 IntegerConvert(masm, r8, rdx); |
| 1292 | 1292 |
| 1293 // Here r8 has the untagged integer, rax has a Smi or a heap number. | 1293 // Here r8 has the untagged integer, rax has a Smi or a heap number. |
| 1294 __ bind(&load_arg2); | 1294 __ bind(&load_arg2); |
| 1295 // Test if arg2 is a Smi. | 1295 // Test if arg2 is a Smi. |
| 1296 __ JumpIfNotSmi(rax, &arg2_is_object); | 1296 __ JumpIfNotSmi(rax, &arg2_is_object); |
| 1297 __ SmiToInteger32(rcx, rax); | 1297 __ SmiToInteger32(rcx, rax); |
| 1298 __ jmp(&done); | 1298 __ jmp(&done); |
| 1299 | 1299 |
| 1300 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 1300 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
| 1301 __ bind(&check_undefined_arg2); | 1301 __ bind(&check_undefined_arg2); |
| 1302 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 1302 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
| 1303 __ j(not_equal, conversion_failure); | 1303 __ j(not_equal, conversion_failure); |
| 1304 __ movl(rcx, Immediate(0)); | 1304 __ Set(rcx, 0); |
| 1305 __ jmp(&done); | 1305 __ jmp(&done); |
| 1306 | 1306 |
| 1307 __ bind(&arg2_is_object); | 1307 __ bind(&arg2_is_object); |
| 1308 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map); | 1308 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map); |
| 1309 __ j(not_equal, &check_undefined_arg2); | 1309 __ j(not_equal, &check_undefined_arg2); |
| 1310 // Get the untagged integer version of the rax heap number in rcx. | 1310 // Get the untagged integer version of the rax heap number in rcx. |
| 1311 IntegerConvert(masm, rcx, rax); | 1311 IntegerConvert(masm, rcx, rax); |
| 1312 __ bind(&done); | 1312 __ bind(&done); |
| 1313 __ movl(rax, r8); | 1313 __ movl(rax, r8); |
| 1314 } | 1314 } |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1451 __ bind(&try_float); | 1451 __ bind(&try_float); |
| 1452 } else if (FLAG_debug_code) { | 1452 } else if (FLAG_debug_code) { |
| 1453 __ AbortIfSmi(rax); | 1453 __ AbortIfSmi(rax); |
| 1454 } | 1454 } |
| 1455 | 1455 |
| 1456 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), | 1456 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), |
| 1457 Heap::kHeapNumberMapRootIndex); | 1457 Heap::kHeapNumberMapRootIndex); |
| 1458 __ j(not_equal, &slow); | 1458 __ j(not_equal, &slow); |
| 1459 // Operand is a float, negate its value by flipping sign bit. | 1459 // Operand is a float, negate its value by flipping sign bit. |
| 1460 __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset)); | 1460 __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset)); |
| 1461 __ movq(kScratchRegister, Immediate(0x01)); | 1461 __ Set(kScratchRegister, 0x01); |
| 1462 __ shl(kScratchRegister, Immediate(63)); | 1462 __ shl(kScratchRegister, Immediate(63)); |
| 1463 __ xor_(rdx, kScratchRegister); // Flip sign. | 1463 __ xor_(rdx, kScratchRegister); // Flip sign. |
| 1464 // rdx is value to store. | 1464 // rdx is value to store. |
| 1465 if (overwrite_ == UNARY_OVERWRITE) { | 1465 if (overwrite_ == UNARY_OVERWRITE) { |
| 1466 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rdx); | 1466 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rdx); |
| 1467 } else { | 1467 } else { |
| 1468 __ AllocateHeapNumber(rcx, rbx, &slow); | 1468 __ AllocateHeapNumber(rcx, rbx, &slow); |
| 1469 // rcx: allocated 'empty' number | 1469 // rcx: allocated 'empty' number |
| 1470 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx); | 1470 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx); |
| 1471 __ movq(rax, rcx); | 1471 __ movq(rax, rcx); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 // rax = exponent | 1523 // rax = exponent |
| 1524 // rcx = temporary, result | 1524 // rcx = temporary, result |
| 1525 | 1525 |
| 1526 Label allocate_return, call_runtime; | 1526 Label allocate_return, call_runtime; |
| 1527 | 1527 |
| 1528 // Load input parameters. | 1528 // Load input parameters. |
| 1529 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | 1529 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); |
| 1530 __ movq(rax, Operand(rsp, 1 * kPointerSize)); | 1530 __ movq(rax, Operand(rsp, 1 * kPointerSize)); |
| 1531 | 1531 |
| 1532 // Save 1 in xmm3 - we need this several times later on. | 1532 // Save 1 in xmm3 - we need this several times later on. |
| 1533 __ movl(rcx, Immediate(1)); | 1533 __ Set(rcx, 1); |
| 1534 __ cvtlsi2sd(xmm3, rcx); | 1534 __ cvtlsi2sd(xmm3, rcx); |
| 1535 | 1535 |
| 1536 Label exponent_nonsmi; | 1536 Label exponent_nonsmi; |
| 1537 Label base_nonsmi; | 1537 Label base_nonsmi; |
| 1538 // If the exponent is a heap number go to that specific case. | 1538 // If the exponent is a heap number go to that specific case. |
| 1539 __ JumpIfNotSmi(rax, &exponent_nonsmi); | 1539 __ JumpIfNotSmi(rax, &exponent_nonsmi); |
| 1540 __ JumpIfNotSmi(rdx, &base_nonsmi); | 1540 __ JumpIfNotSmi(rdx, &base_nonsmi); |
| 1541 | 1541 |
| 1542 // Optimized version when both exponent and base are smis. | 1542 // Optimized version when both exponent and base are smis. |
| 1543 Label powi; | 1543 Label powi; |
| (...skipping 1702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3246 == 0xB0 - 0x100); | 3246 == 0xB0 - 0x100); |
| 3247 __ movl(rax, Immediate(0xB0)); // TrueValue is at -10 * kPointerSize. | 3247 __ movl(rax, Immediate(0xB0)); // TrueValue is at -10 * kPointerSize. |
| 3248 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); | 3248 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); |
| 3249 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); | 3249 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); |
| 3250 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); | 3250 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); |
| 3251 if (FLAG_debug_code) { | 3251 if (FLAG_debug_code) { |
| 3252 __ movl(rax, Immediate(kWordBeforeResultValue)); | 3252 __ movl(rax, Immediate(kWordBeforeResultValue)); |
| 3253 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); | 3253 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); |
| 3254 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)."); | 3254 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)."); |
| 3255 } | 3255 } |
| 3256 __ xorl(rax, rax); | 3256 __ Set(rax, 0); |
| 3257 } | 3257 } |
| 3258 __ ret(2 * kPointerSize + extra_stack_space); | 3258 __ ret(2 * kPointerSize + extra_stack_space); |
| 3259 | 3259 |
| 3260 __ bind(&is_not_instance); | 3260 __ bind(&is_not_instance); |
| 3261 if (!HasCallSiteInlineCheck()) { | 3261 if (!HasCallSiteInlineCheck()) { |
| 3262 // We have to store a non-zero value in the cache. | 3262 // We have to store a non-zero value in the cache. |
| 3263 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); | 3263 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); |
| 3264 } else { | 3264 } else { |
| 3265 // Store offset of false in the root array at the inline check site. | 3265 // Store offset of false in the root array at the inline check site. |
| 3266 ASSERT((Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias | 3266 ASSERT((Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias |
| (...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4105 __ sarl(scratch, Immediate(11)); | 4105 __ sarl(scratch, Immediate(11)); |
| 4106 __ xorl(hash, scratch); | 4106 __ xorl(hash, scratch); |
| 4107 // hash += hash << 15; | 4107 // hash += hash << 15; |
| 4108 __ movl(scratch, hash); | 4108 __ movl(scratch, hash); |
| 4109 __ shll(scratch, Immediate(15)); | 4109 __ shll(scratch, Immediate(15)); |
| 4110 __ addl(hash, scratch); | 4110 __ addl(hash, scratch); |
| 4111 | 4111 |
| 4112 // if (hash == 0) hash = 27; | 4112 // if (hash == 0) hash = 27; |
| 4113 Label hash_not_zero; | 4113 Label hash_not_zero; |
| 4114 __ j(not_zero, &hash_not_zero); | 4114 __ j(not_zero, &hash_not_zero); |
| 4115 __ movl(hash, Immediate(27)); | 4115 __ Set(hash, 27); |
| 4116 __ bind(&hash_not_zero); | 4116 __ bind(&hash_not_zero); |
| 4117 } | 4117 } |
| 4118 | 4118 |
| 4119 void SubStringStub::Generate(MacroAssembler* masm) { | 4119 void SubStringStub::Generate(MacroAssembler* masm) { |
| 4120 Label runtime; | 4120 Label runtime; |
| 4121 | 4121 |
| 4122 // Stack frame on entry. | 4122 // Stack frame on entry. |
| 4123 // rsp[0]: return address | 4123 // rsp[0]: return address |
| 4124 // rsp[8]: to | 4124 // rsp[8]: to |
| 4125 // rsp[16]: from | 4125 // rsp[16]: from |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4301 __ SmiToInteger32(min_length, min_length); | 4301 __ SmiToInteger32(min_length, min_length); |
| 4302 | 4302 |
| 4303 // Registers scratch2 and scratch3 are free. | 4303 // Registers scratch2 and scratch3 are free. |
| 4304 NearLabel result_not_equal; | 4304 NearLabel result_not_equal; |
| 4305 Label loop; | 4305 Label loop; |
| 4306 { | 4306 { |
| 4307 // Check characters 0 .. min_length - 1 in a loop. | 4307 // Check characters 0 .. min_length - 1 in a loop. |
| 4308 // Use scratch3 as loop index, min_length as limit and scratch2 | 4308 // Use scratch3 as loop index, min_length as limit and scratch2 |
| 4309 // for computation. | 4309 // for computation. |
| 4310 const Register index = scratch3; | 4310 const Register index = scratch3; |
| 4311 __ movl(index, Immediate(0)); // Index into strings. | 4311 __ Set(index, 0); // Index into strings. |
| 4312 __ bind(&loop); | 4312 __ bind(&loop); |
| 4313 // Compare characters. | 4313 // Compare characters. |
| 4314 // TODO(lrn): Could we load more than one character at a time? | 4314 // TODO(lrn): Could we load more than one character at a time? |
| 4315 __ movb(scratch2, FieldOperand(left, | 4315 __ movb(scratch2, FieldOperand(left, |
| 4316 index, | 4316 index, |
| 4317 times_1, | 4317 times_1, |
| 4318 SeqAsciiString::kHeaderSize)); | 4318 SeqAsciiString::kHeaderSize)); |
| 4319 // Increment index and use -1 modifier on next load to give | 4319 // Increment index and use -1 modifier on next load to give |
| 4320 // the previous load extra time to complete. | 4320 // the previous load extra time to complete. |
| 4321 __ addl(index, Immediate(1)); | 4321 __ addl(index, Immediate(1)); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4509 // Do a tail call to the rewritten stub. | 4509 // Do a tail call to the rewritten stub. |
| 4510 __ jmp(rdi); | 4510 __ jmp(rdi); |
| 4511 } | 4511 } |
| 4512 | 4512 |
| 4513 | 4513 |
| 4514 #undef __ | 4514 #undef __ |
| 4515 | 4515 |
| 4516 } } // namespace v8::internal | 4516 } } // namespace v8::internal |
| 4517 | 4517 |
| 4518 #endif // V8_TARGET_ARCH_X64 | 4518 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |