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 |