| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 1414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1425 __ JumpIfSmi(object, label); | 1425 __ JumpIfSmi(object, label); |
| 1426 __ movp(scratch, FieldOperand(object, HeapObject::kMapOffset)); | 1426 __ movp(scratch, FieldOperand(object, HeapObject::kMapOffset)); |
| 1427 __ movzxbp(scratch, | 1427 __ movzxbp(scratch, |
| 1428 FieldOperand(scratch, Map::kInstanceTypeOffset)); | 1428 FieldOperand(scratch, Map::kInstanceTypeOffset)); |
| 1429 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); | 1429 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); |
| 1430 __ testb(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); | 1430 __ testb(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); |
| 1431 __ j(not_zero, label); | 1431 __ j(not_zero, label); |
| 1432 } | 1432 } |
| 1433 | 1433 |
| 1434 | 1434 |
| 1435 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { | 1435 void CompareICStub::GenerateGeneric(MacroAssembler* masm) { |
| 1436 Label check_unequal_objects, done; | 1436 Label check_unequal_objects, done; |
| 1437 Condition cc = GetCondition(); | 1437 Condition cc = GetCondition(); |
| 1438 Factory* factory = isolate()->factory(); | 1438 Factory* factory = isolate()->factory(); |
| 1439 | 1439 |
| 1440 Label miss; | 1440 Label miss; |
| 1441 CheckInputType(masm, rdx, left(), &miss); | 1441 CheckInputType(masm, rdx, left(), &miss); |
| 1442 CheckInputType(masm, rax, right(), &miss); | 1442 CheckInputType(masm, rax, right(), &miss); |
| 1443 | 1443 |
| 1444 // Compare two smis. | 1444 // Compare two smis. |
| 1445 Label non_smi, smi_done; | 1445 Label non_smi, smi_done; |
| (...skipping 1878 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3324 __ Assert(equal, kExpectedAllocationSite); | 3324 __ Assert(equal, kExpectedAllocationSite); |
| 3325 } | 3325 } |
| 3326 | 3326 |
| 3327 // Tail call into the stub that handles binary operations with allocation | 3327 // Tail call into the stub that handles binary operations with allocation |
| 3328 // sites. | 3328 // sites. |
| 3329 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 3329 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
| 3330 __ TailCallStub(&stub); | 3330 __ TailCallStub(&stub); |
| 3331 } | 3331 } |
| 3332 | 3332 |
| 3333 | 3333 |
| 3334 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 3334 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
| 3335 DCHECK(state() == CompareIC::SMI); | 3335 DCHECK(state() == CompareIC::SMI); |
| 3336 Label miss; | 3336 Label miss; |
| 3337 __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear); | 3337 __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear); |
| 3338 | 3338 |
| 3339 if (GetCondition() == equal) { | 3339 if (GetCondition() == equal) { |
| 3340 // For equality we do not care about the sign of the result. | 3340 // For equality we do not care about the sign of the result. |
| 3341 __ subp(rax, rdx); | 3341 __ subp(rax, rdx); |
| 3342 } else { | 3342 } else { |
| 3343 Label done; | 3343 Label done; |
| 3344 __ subp(rdx, rax); | 3344 __ subp(rdx, rax); |
| 3345 __ j(no_overflow, &done, Label::kNear); | 3345 __ j(no_overflow, &done, Label::kNear); |
| 3346 // Correct sign of result in case of overflow. | 3346 // Correct sign of result in case of overflow. |
| 3347 __ notp(rdx); | 3347 __ notp(rdx); |
| 3348 __ bind(&done); | 3348 __ bind(&done); |
| 3349 __ movp(rax, rdx); | 3349 __ movp(rax, rdx); |
| 3350 } | 3350 } |
| 3351 __ ret(0); | 3351 __ ret(0); |
| 3352 | 3352 |
| 3353 __ bind(&miss); | 3353 __ bind(&miss); |
| 3354 GenerateMiss(masm); | 3354 GenerateMiss(masm); |
| 3355 } | 3355 } |
| 3356 | 3356 |
| 3357 | 3357 |
| 3358 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { | 3358 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { |
| 3359 DCHECK(state() == CompareIC::NUMBER); | 3359 DCHECK(state() == CompareIC::NUMBER); |
| 3360 | 3360 |
| 3361 Label generic_stub; | 3361 Label generic_stub; |
| 3362 Label unordered, maybe_undefined1, maybe_undefined2; | 3362 Label unordered, maybe_undefined1, maybe_undefined2; |
| 3363 Label miss; | 3363 Label miss; |
| 3364 | 3364 |
| 3365 if (left() == CompareIC::SMI) { | 3365 if (left() == CompareIC::SMI) { |
| 3366 __ JumpIfNotSmi(rdx, &miss); | 3366 __ JumpIfNotSmi(rdx, &miss); |
| 3367 } | 3367 } |
| 3368 if (right() == CompareIC::SMI) { | 3368 if (right() == CompareIC::SMI) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3400 // Return a result of -1, 0, or 1, based on EFLAGS. | 3400 // Return a result of -1, 0, or 1, based on EFLAGS. |
| 3401 // Performing mov, because xor would destroy the flag register. | 3401 // Performing mov, because xor would destroy the flag register. |
| 3402 __ movl(rax, Immediate(0)); | 3402 __ movl(rax, Immediate(0)); |
| 3403 __ movl(rcx, Immediate(0)); | 3403 __ movl(rcx, Immediate(0)); |
| 3404 __ setcc(above, rax); // Add one to zero if carry clear and not equal. | 3404 __ setcc(above, rax); // Add one to zero if carry clear and not equal. |
| 3405 __ sbbp(rax, rcx); // Subtract one if below (aka. carry set). | 3405 __ sbbp(rax, rcx); // Subtract one if below (aka. carry set). |
| 3406 __ ret(0); | 3406 __ ret(0); |
| 3407 | 3407 |
| 3408 __ bind(&unordered); | 3408 __ bind(&unordered); |
| 3409 __ bind(&generic_stub); | 3409 __ bind(&generic_stub); |
| 3410 ICCompareStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, | 3410 CompareICStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, |
| 3411 CompareIC::GENERIC); | 3411 CompareIC::GENERIC); |
| 3412 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3412 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 3413 | 3413 |
| 3414 __ bind(&maybe_undefined1); | 3414 __ bind(&maybe_undefined1); |
| 3415 if (Token::IsOrderedRelationalCompareOp(op())) { | 3415 if (Token::IsOrderedRelationalCompareOp(op())) { |
| 3416 __ Cmp(rax, isolate()->factory()->undefined_value()); | 3416 __ Cmp(rax, isolate()->factory()->undefined_value()); |
| 3417 __ j(not_equal, &miss); | 3417 __ j(not_equal, &miss); |
| 3418 __ JumpIfSmi(rdx, &unordered); | 3418 __ JumpIfSmi(rdx, &unordered); |
| 3419 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); | 3419 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); |
| 3420 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3420 __ j(not_equal, &maybe_undefined2, Label::kNear); |
| 3421 __ jmp(&unordered); | 3421 __ jmp(&unordered); |
| 3422 } | 3422 } |
| 3423 | 3423 |
| 3424 __ bind(&maybe_undefined2); | 3424 __ bind(&maybe_undefined2); |
| 3425 if (Token::IsOrderedRelationalCompareOp(op())) { | 3425 if (Token::IsOrderedRelationalCompareOp(op())) { |
| 3426 __ Cmp(rdx, isolate()->factory()->undefined_value()); | 3426 __ Cmp(rdx, isolate()->factory()->undefined_value()); |
| 3427 __ j(equal, &unordered); | 3427 __ j(equal, &unordered); |
| 3428 } | 3428 } |
| 3429 | 3429 |
| 3430 __ bind(&miss); | 3430 __ bind(&miss); |
| 3431 GenerateMiss(masm); | 3431 GenerateMiss(masm); |
| 3432 } | 3432 } |
| 3433 | 3433 |
| 3434 | 3434 |
| 3435 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3435 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
| 3436 DCHECK(state() == CompareIC::INTERNALIZED_STRING); | 3436 DCHECK(state() == CompareIC::INTERNALIZED_STRING); |
| 3437 DCHECK(GetCondition() == equal); | 3437 DCHECK(GetCondition() == equal); |
| 3438 | 3438 |
| 3439 // Registers containing left and right operands respectively. | 3439 // Registers containing left and right operands respectively. |
| 3440 Register left = rdx; | 3440 Register left = rdx; |
| 3441 Register right = rax; | 3441 Register right = rax; |
| 3442 Register tmp1 = rcx; | 3442 Register tmp1 = rcx; |
| 3443 Register tmp2 = rbx; | 3443 Register tmp2 = rbx; |
| 3444 | 3444 |
| 3445 // Check that both operands are heap objects. | 3445 // Check that both operands are heap objects. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 3468 STATIC_ASSERT(kSmiTag == 0); | 3468 STATIC_ASSERT(kSmiTag == 0); |
| 3469 __ Move(rax, Smi::FromInt(EQUAL)); | 3469 __ Move(rax, Smi::FromInt(EQUAL)); |
| 3470 __ bind(&done); | 3470 __ bind(&done); |
| 3471 __ ret(0); | 3471 __ ret(0); |
| 3472 | 3472 |
| 3473 __ bind(&miss); | 3473 __ bind(&miss); |
| 3474 GenerateMiss(masm); | 3474 GenerateMiss(masm); |
| 3475 } | 3475 } |
| 3476 | 3476 |
| 3477 | 3477 |
| 3478 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { | 3478 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { |
| 3479 DCHECK(state() == CompareIC::UNIQUE_NAME); | 3479 DCHECK(state() == CompareIC::UNIQUE_NAME); |
| 3480 DCHECK(GetCondition() == equal); | 3480 DCHECK(GetCondition() == equal); |
| 3481 | 3481 |
| 3482 // Registers containing left and right operands respectively. | 3482 // Registers containing left and right operands respectively. |
| 3483 Register left = rdx; | 3483 Register left = rdx; |
| 3484 Register right = rax; | 3484 Register right = rax; |
| 3485 Register tmp1 = rcx; | 3485 Register tmp1 = rcx; |
| 3486 Register tmp2 = rbx; | 3486 Register tmp2 = rbx; |
| 3487 | 3487 |
| 3488 // Check that both operands are heap objects. | 3488 // Check that both operands are heap objects. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 3511 STATIC_ASSERT(kSmiTag == 0); | 3511 STATIC_ASSERT(kSmiTag == 0); |
| 3512 __ Move(rax, Smi::FromInt(EQUAL)); | 3512 __ Move(rax, Smi::FromInt(EQUAL)); |
| 3513 __ bind(&done); | 3513 __ bind(&done); |
| 3514 __ ret(0); | 3514 __ ret(0); |
| 3515 | 3515 |
| 3516 __ bind(&miss); | 3516 __ bind(&miss); |
| 3517 GenerateMiss(masm); | 3517 GenerateMiss(masm); |
| 3518 } | 3518 } |
| 3519 | 3519 |
| 3520 | 3520 |
| 3521 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { | 3521 void CompareICStub::GenerateStrings(MacroAssembler* masm) { |
| 3522 DCHECK(state() == CompareIC::STRING); | 3522 DCHECK(state() == CompareIC::STRING); |
| 3523 Label miss; | 3523 Label miss; |
| 3524 | 3524 |
| 3525 bool equality = Token::IsEqualityOp(op()); | 3525 bool equality = Token::IsEqualityOp(op()); |
| 3526 | 3526 |
| 3527 // Registers containing left and right operands respectively. | 3527 // Registers containing left and right operands respectively. |
| 3528 Register left = rdx; | 3528 Register left = rdx; |
| 3529 Register right = rax; | 3529 Register right = rax; |
| 3530 Register tmp1 = rcx; | 3530 Register tmp1 = rcx; |
| 3531 Register tmp2 = rbx; | 3531 Register tmp2 = rbx; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3597 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); | 3597 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); |
| 3598 } else { | 3598 } else { |
| 3599 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3599 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| 3600 } | 3600 } |
| 3601 | 3601 |
| 3602 __ bind(&miss); | 3602 __ bind(&miss); |
| 3603 GenerateMiss(masm); | 3603 GenerateMiss(masm); |
| 3604 } | 3604 } |
| 3605 | 3605 |
| 3606 | 3606 |
| 3607 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { | 3607 void CompareICStub::GenerateObjects(MacroAssembler* masm) { |
| 3608 DCHECK(state() == CompareIC::OBJECT); | 3608 DCHECK(state() == CompareIC::OBJECT); |
| 3609 Label miss; | 3609 Label miss; |
| 3610 Condition either_smi = masm->CheckEitherSmi(rdx, rax); | 3610 Condition either_smi = masm->CheckEitherSmi(rdx, rax); |
| 3611 __ j(either_smi, &miss, Label::kNear); | 3611 __ j(either_smi, &miss, Label::kNear); |
| 3612 | 3612 |
| 3613 __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); | 3613 __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); |
| 3614 __ j(not_equal, &miss, Label::kNear); | 3614 __ j(not_equal, &miss, Label::kNear); |
| 3615 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); | 3615 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); |
| 3616 __ j(not_equal, &miss, Label::kNear); | 3616 __ j(not_equal, &miss, Label::kNear); |
| 3617 | 3617 |
| 3618 DCHECK(GetCondition() == equal); | 3618 DCHECK(GetCondition() == equal); |
| 3619 __ subp(rax, rdx); | 3619 __ subp(rax, rdx); |
| 3620 __ ret(0); | 3620 __ ret(0); |
| 3621 | 3621 |
| 3622 __ bind(&miss); | 3622 __ bind(&miss); |
| 3623 GenerateMiss(masm); | 3623 GenerateMiss(masm); |
| 3624 } | 3624 } |
| 3625 | 3625 |
| 3626 | 3626 |
| 3627 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) { | 3627 void CompareICStub::GenerateKnownObjects(MacroAssembler* masm) { |
| 3628 Label miss; | 3628 Label miss; |
| 3629 Condition either_smi = masm->CheckEitherSmi(rdx, rax); | 3629 Condition either_smi = masm->CheckEitherSmi(rdx, rax); |
| 3630 __ j(either_smi, &miss, Label::kNear); | 3630 __ j(either_smi, &miss, Label::kNear); |
| 3631 | 3631 |
| 3632 __ movp(rcx, FieldOperand(rax, HeapObject::kMapOffset)); | 3632 __ movp(rcx, FieldOperand(rax, HeapObject::kMapOffset)); |
| 3633 __ movp(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); | 3633 __ movp(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); |
| 3634 __ Cmp(rcx, known_map_); | 3634 __ Cmp(rcx, known_map_); |
| 3635 __ j(not_equal, &miss, Label::kNear); | 3635 __ j(not_equal, &miss, Label::kNear); |
| 3636 __ Cmp(rbx, known_map_); | 3636 __ Cmp(rbx, known_map_); |
| 3637 __ j(not_equal, &miss, Label::kNear); | 3637 __ j(not_equal, &miss, Label::kNear); |
| 3638 | 3638 |
| 3639 __ subp(rax, rdx); | 3639 __ subp(rax, rdx); |
| 3640 __ ret(0); | 3640 __ ret(0); |
| 3641 | 3641 |
| 3642 __ bind(&miss); | 3642 __ bind(&miss); |
| 3643 GenerateMiss(masm); | 3643 GenerateMiss(masm); |
| 3644 } | 3644 } |
| 3645 | 3645 |
| 3646 | 3646 |
| 3647 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { | 3647 void CompareICStub::GenerateMiss(MacroAssembler* masm) { |
| 3648 { | 3648 { |
| 3649 // Call the runtime system in a fresh internal frame. | 3649 // Call the runtime system in a fresh internal frame. |
| 3650 ExternalReference miss = | 3650 ExternalReference miss = |
| 3651 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); | 3651 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); |
| 3652 | 3652 |
| 3653 FrameScope scope(masm, StackFrame::INTERNAL); | 3653 FrameScope scope(masm, StackFrame::INTERNAL); |
| 3654 __ Push(rdx); | 3654 __ Push(rdx); |
| 3655 __ Push(rax); | 3655 __ Push(rax); |
| 3656 __ Push(rdx); | 3656 __ Push(rdx); |
| 3657 __ Push(rax); | 3657 __ Push(rax); |
| (...skipping 1049 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4707 return_value_operand, | 4707 return_value_operand, |
| 4708 NULL); | 4708 NULL); |
| 4709 } | 4709 } |
| 4710 | 4710 |
| 4711 | 4711 |
| 4712 #undef __ | 4712 #undef __ |
| 4713 | 4713 |
| 4714 } } // namespace v8::internal | 4714 } } // namespace v8::internal |
| 4715 | 4715 |
| 4716 #endif // V8_TARGET_ARCH_X64 | 4716 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |