OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
571 __ ldr(r3, FieldMemOperand(rhs, HeapObject::kMapOffset)); | 571 __ ldr(r3, FieldMemOperand(rhs, HeapObject::kMapOffset)); |
572 __ ldrb(r2, FieldMemOperand(r2, Map::kBitFieldOffset)); | 572 __ ldrb(r2, FieldMemOperand(r2, Map::kBitFieldOffset)); |
573 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset)); | 573 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset)); |
574 __ and_(r0, r2, Operand(r3)); | 574 __ and_(r0, r2, Operand(r3)); |
575 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); | 575 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); |
576 __ eor(r0, r0, Operand(1 << Map::kIsUndetectable)); | 576 __ eor(r0, r0, Operand(1 << Map::kIsUndetectable)); |
577 __ Ret(); | 577 __ Ret(); |
578 } | 578 } |
579 | 579 |
580 | 580 |
581 static void ICCompareStub_CheckInputType(MacroAssembler* masm, | 581 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, |
582 Register input, | |
583 Register scratch, | 582 Register scratch, |
584 CompareIC::State expected, | 583 CompareIC::State expected, |
585 Label* fail) { | 584 Label* fail) { |
586 Label ok; | 585 Label ok; |
587 if (expected == CompareIC::SMI) { | 586 if (expected == CompareIC::SMI) { |
588 __ JumpIfNotSmi(input, fail); | 587 __ JumpIfNotSmi(input, fail); |
589 } else if (expected == CompareIC::NUMBER) { | 588 } else if (expected == CompareIC::NUMBER) { |
590 __ JumpIfSmi(input, &ok); | 589 __ JumpIfSmi(input, &ok); |
591 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, | 590 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, |
592 DONT_DO_SMI_CHECK); | 591 DONT_DO_SMI_CHECK); |
593 } | 592 } |
594 // We could be strict about internalized/non-internalized here, but as long as | 593 // We could be strict about internalized/non-internalized here, but as long as |
595 // hydrogen doesn't care, the stub doesn't have to care either. | 594 // hydrogen doesn't care, the stub doesn't have to care either. |
596 __ bind(&ok); | 595 __ bind(&ok); |
597 } | 596 } |
598 | 597 |
599 | 598 |
600 // On entry r1 and r2 are the values to be compared. | 599 // On entry r1 and r2 are the values to be compared. |
601 // On exit r0 is 0, positive or negative to indicate the result of | 600 // On exit r0 is 0, positive or negative to indicate the result of |
602 // the comparison. | 601 // the comparison. |
603 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { | 602 void CompareICStub::GenerateGeneric(MacroAssembler* masm) { |
604 Register lhs = r1; | 603 Register lhs = r1; |
605 Register rhs = r0; | 604 Register rhs = r0; |
606 Condition cc = GetCondition(); | 605 Condition cc = GetCondition(); |
607 | 606 |
608 Label miss; | 607 Label miss; |
609 ICCompareStub_CheckInputType(masm, lhs, r2, left(), &miss); | 608 CompareICStub_CheckInputType(masm, lhs, r2, left(), &miss); |
610 ICCompareStub_CheckInputType(masm, rhs, r3, right(), &miss); | 609 CompareICStub_CheckInputType(masm, rhs, r3, right(), &miss); |
611 | 610 |
612 Label slow; // Call builtin. | 611 Label slow; // Call builtin. |
613 Label not_smis, both_loaded_as_doubles, lhs_not_nan; | 612 Label not_smis, both_loaded_as_doubles, lhs_not_nan; |
614 | 613 |
615 Label not_two_smis, smi_done; | 614 Label not_two_smis, smi_done; |
616 __ orr(r2, r1, r0); | 615 __ orr(r2, r1, r0); |
617 __ JumpIfNotSmi(r2, ¬_two_smis); | 616 __ JumpIfNotSmi(r2, ¬_two_smis); |
618 __ mov(r1, Operand(r1, ASR, 1)); | 617 __ mov(r1, Operand(r1, ASR, 1)); |
619 __ sub(r0, r1, Operand(r0, ASR, 1)); | 618 __ sub(r0, r1, Operand(r0, ASR, 1)); |
620 __ Ret(); | 619 __ Ret(); |
(...skipping 2725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3346 __ Assert(eq, kExpectedAllocationSite); | 3345 __ Assert(eq, kExpectedAllocationSite); |
3347 } | 3346 } |
3348 | 3347 |
3349 // Tail call into the stub that handles binary operations with allocation | 3348 // Tail call into the stub that handles binary operations with allocation |
3350 // sites. | 3349 // sites. |
3351 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 3350 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
3352 __ TailCallStub(&stub); | 3351 __ TailCallStub(&stub); |
3353 } | 3352 } |
3354 | 3353 |
3355 | 3354 |
3356 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 3355 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
3357 DCHECK(state() == CompareIC::SMI); | 3356 DCHECK(state() == CompareIC::SMI); |
3358 Label miss; | 3357 Label miss; |
3359 __ orr(r2, r1, r0); | 3358 __ orr(r2, r1, r0); |
3360 __ JumpIfNotSmi(r2, &miss); | 3359 __ JumpIfNotSmi(r2, &miss); |
3361 | 3360 |
3362 if (GetCondition() == eq) { | 3361 if (GetCondition() == eq) { |
3363 // For equality we do not care about the sign of the result. | 3362 // For equality we do not care about the sign of the result. |
3364 __ sub(r0, r0, r1, SetCC); | 3363 __ sub(r0, r0, r1, SetCC); |
3365 } else { | 3364 } else { |
3366 // Untag before subtracting to avoid handling overflow. | 3365 // Untag before subtracting to avoid handling overflow. |
3367 __ SmiUntag(r1); | 3366 __ SmiUntag(r1); |
3368 __ sub(r0, r1, Operand::SmiUntag(r0)); | 3367 __ sub(r0, r1, Operand::SmiUntag(r0)); |
3369 } | 3368 } |
3370 __ Ret(); | 3369 __ Ret(); |
3371 | 3370 |
3372 __ bind(&miss); | 3371 __ bind(&miss); |
3373 GenerateMiss(masm); | 3372 GenerateMiss(masm); |
3374 } | 3373 } |
3375 | 3374 |
3376 | 3375 |
3377 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { | 3376 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { |
3378 DCHECK(state() == CompareIC::NUMBER); | 3377 DCHECK(state() == CompareIC::NUMBER); |
3379 | 3378 |
3380 Label generic_stub; | 3379 Label generic_stub; |
3381 Label unordered, maybe_undefined1, maybe_undefined2; | 3380 Label unordered, maybe_undefined1, maybe_undefined2; |
3382 Label miss; | 3381 Label miss; |
3383 | 3382 |
3384 if (left() == CompareIC::SMI) { | 3383 if (left() == CompareIC::SMI) { |
3385 __ JumpIfNotSmi(r1, &miss); | 3384 __ JumpIfNotSmi(r1, &miss); |
3386 } | 3385 } |
3387 if (right() == CompareIC::SMI) { | 3386 if (right() == CompareIC::SMI) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3419 __ b(vs, &unordered); | 3418 __ b(vs, &unordered); |
3420 | 3419 |
3421 // Return a result of -1, 0, or 1, based on status bits. | 3420 // Return a result of -1, 0, or 1, based on status bits. |
3422 __ mov(r0, Operand(EQUAL), LeaveCC, eq); | 3421 __ mov(r0, Operand(EQUAL), LeaveCC, eq); |
3423 __ mov(r0, Operand(LESS), LeaveCC, lt); | 3422 __ mov(r0, Operand(LESS), LeaveCC, lt); |
3424 __ mov(r0, Operand(GREATER), LeaveCC, gt); | 3423 __ mov(r0, Operand(GREATER), LeaveCC, gt); |
3425 __ Ret(); | 3424 __ Ret(); |
3426 | 3425 |
3427 __ bind(&unordered); | 3426 __ bind(&unordered); |
3428 __ bind(&generic_stub); | 3427 __ bind(&generic_stub); |
3429 ICCompareStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, | 3428 CompareICStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, |
3430 CompareIC::GENERIC); | 3429 CompareIC::GENERIC); |
3431 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 3430 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
3432 | 3431 |
3433 __ bind(&maybe_undefined1); | 3432 __ bind(&maybe_undefined1); |
3434 if (Token::IsOrderedRelationalCompareOp(op())) { | 3433 if (Token::IsOrderedRelationalCompareOp(op())) { |
3435 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); | 3434 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); |
3436 __ b(ne, &miss); | 3435 __ b(ne, &miss); |
3437 __ JumpIfSmi(r1, &unordered); | 3436 __ JumpIfSmi(r1, &unordered); |
3438 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); | 3437 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); |
3439 __ b(ne, &maybe_undefined2); | 3438 __ b(ne, &maybe_undefined2); |
3440 __ jmp(&unordered); | 3439 __ jmp(&unordered); |
3441 } | 3440 } |
3442 | 3441 |
3443 __ bind(&maybe_undefined2); | 3442 __ bind(&maybe_undefined2); |
3444 if (Token::IsOrderedRelationalCompareOp(op())) { | 3443 if (Token::IsOrderedRelationalCompareOp(op())) { |
3445 __ CompareRoot(r1, Heap::kUndefinedValueRootIndex); | 3444 __ CompareRoot(r1, Heap::kUndefinedValueRootIndex); |
3446 __ b(eq, &unordered); | 3445 __ b(eq, &unordered); |
3447 } | 3446 } |
3448 | 3447 |
3449 __ bind(&miss); | 3448 __ bind(&miss); |
3450 GenerateMiss(masm); | 3449 GenerateMiss(masm); |
3451 } | 3450 } |
3452 | 3451 |
3453 | 3452 |
3454 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3453 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
3455 DCHECK(state() == CompareIC::INTERNALIZED_STRING); | 3454 DCHECK(state() == CompareIC::INTERNALIZED_STRING); |
3456 Label miss; | 3455 Label miss; |
3457 | 3456 |
3458 // Registers containing left and right operands respectively. | 3457 // Registers containing left and right operands respectively. |
3459 Register left = r1; | 3458 Register left = r1; |
3460 Register right = r0; | 3459 Register right = r0; |
3461 Register tmp1 = r2; | 3460 Register tmp1 = r2; |
3462 Register tmp2 = r3; | 3461 Register tmp2 = r3; |
3463 | 3462 |
3464 // Check that both operands are heap objects. | 3463 // Check that both operands are heap objects. |
(...skipping 17 matching lines...) Expand all Loading... |
3482 STATIC_ASSERT(EQUAL == 0); | 3481 STATIC_ASSERT(EQUAL == 0); |
3483 STATIC_ASSERT(kSmiTag == 0); | 3482 STATIC_ASSERT(kSmiTag == 0); |
3484 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); | 3483 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); |
3485 __ Ret(); | 3484 __ Ret(); |
3486 | 3485 |
3487 __ bind(&miss); | 3486 __ bind(&miss); |
3488 GenerateMiss(masm); | 3487 GenerateMiss(masm); |
3489 } | 3488 } |
3490 | 3489 |
3491 | 3490 |
3492 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { | 3491 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { |
3493 DCHECK(state() == CompareIC::UNIQUE_NAME); | 3492 DCHECK(state() == CompareIC::UNIQUE_NAME); |
3494 DCHECK(GetCondition() == eq); | 3493 DCHECK(GetCondition() == eq); |
3495 Label miss; | 3494 Label miss; |
3496 | 3495 |
3497 // Registers containing left and right operands respectively. | 3496 // Registers containing left and right operands respectively. |
3498 Register left = r1; | 3497 Register left = r1; |
3499 Register right = r0; | 3498 Register right = r0; |
3500 Register tmp1 = r2; | 3499 Register tmp1 = r2; |
3501 Register tmp2 = r3; | 3500 Register tmp2 = r3; |
3502 | 3501 |
(...skipping 18 matching lines...) Expand all Loading... |
3521 STATIC_ASSERT(EQUAL == 0); | 3520 STATIC_ASSERT(EQUAL == 0); |
3522 STATIC_ASSERT(kSmiTag == 0); | 3521 STATIC_ASSERT(kSmiTag == 0); |
3523 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); | 3522 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); |
3524 __ Ret(); | 3523 __ Ret(); |
3525 | 3524 |
3526 __ bind(&miss); | 3525 __ bind(&miss); |
3527 GenerateMiss(masm); | 3526 GenerateMiss(masm); |
3528 } | 3527 } |
3529 | 3528 |
3530 | 3529 |
3531 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { | 3530 void CompareICStub::GenerateStrings(MacroAssembler* masm) { |
3532 DCHECK(state() == CompareIC::STRING); | 3531 DCHECK(state() == CompareIC::STRING); |
3533 Label miss; | 3532 Label miss; |
3534 | 3533 |
3535 bool equality = Token::IsEqualityOp(op()); | 3534 bool equality = Token::IsEqualityOp(op()); |
3536 | 3535 |
3537 // Registers containing left and right operands respectively. | 3536 // Registers containing left and right operands respectively. |
3538 Register left = r1; | 3537 Register left = r1; |
3539 Register right = r0; | 3538 Register right = r0; |
3540 Register tmp1 = r2; | 3539 Register tmp1 = r2; |
3541 Register tmp2 = r3; | 3540 Register tmp2 = r3; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3600 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); | 3599 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); |
3601 } else { | 3600 } else { |
3602 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3601 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3603 } | 3602 } |
3604 | 3603 |
3605 __ bind(&miss); | 3604 __ bind(&miss); |
3606 GenerateMiss(masm); | 3605 GenerateMiss(masm); |
3607 } | 3606 } |
3608 | 3607 |
3609 | 3608 |
3610 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { | 3609 void CompareICStub::GenerateObjects(MacroAssembler* masm) { |
3611 DCHECK(state() == CompareIC::OBJECT); | 3610 DCHECK(state() == CompareIC::OBJECT); |
3612 Label miss; | 3611 Label miss; |
3613 __ and_(r2, r1, Operand(r0)); | 3612 __ and_(r2, r1, Operand(r0)); |
3614 __ JumpIfSmi(r2, &miss); | 3613 __ JumpIfSmi(r2, &miss); |
3615 | 3614 |
3616 __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE); | 3615 __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE); |
3617 __ b(ne, &miss); | 3616 __ b(ne, &miss); |
3618 __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE); | 3617 __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE); |
3619 __ b(ne, &miss); | 3618 __ b(ne, &miss); |
3620 | 3619 |
3621 DCHECK(GetCondition() == eq); | 3620 DCHECK(GetCondition() == eq); |
3622 __ sub(r0, r0, Operand(r1)); | 3621 __ sub(r0, r0, Operand(r1)); |
3623 __ Ret(); | 3622 __ Ret(); |
3624 | 3623 |
3625 __ bind(&miss); | 3624 __ bind(&miss); |
3626 GenerateMiss(masm); | 3625 GenerateMiss(masm); |
3627 } | 3626 } |
3628 | 3627 |
3629 | 3628 |
3630 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) { | 3629 void CompareICStub::GenerateKnownObjects(MacroAssembler* masm) { |
3631 Label miss; | 3630 Label miss; |
3632 __ and_(r2, r1, Operand(r0)); | 3631 __ and_(r2, r1, Operand(r0)); |
3633 __ JumpIfSmi(r2, &miss); | 3632 __ JumpIfSmi(r2, &miss); |
3634 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); | 3633 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); |
3635 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); | 3634 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); |
3636 __ cmp(r2, Operand(known_map_)); | 3635 __ cmp(r2, Operand(known_map_)); |
3637 __ b(ne, &miss); | 3636 __ b(ne, &miss); |
3638 __ cmp(r3, Operand(known_map_)); | 3637 __ cmp(r3, Operand(known_map_)); |
3639 __ b(ne, &miss); | 3638 __ b(ne, &miss); |
3640 | 3639 |
3641 __ sub(r0, r0, Operand(r1)); | 3640 __ sub(r0, r0, Operand(r1)); |
3642 __ Ret(); | 3641 __ Ret(); |
3643 | 3642 |
3644 __ bind(&miss); | 3643 __ bind(&miss); |
3645 GenerateMiss(masm); | 3644 GenerateMiss(masm); |
3646 } | 3645 } |
3647 | 3646 |
3648 | 3647 |
3649 | 3648 void CompareICStub::GenerateMiss(MacroAssembler* masm) { |
3650 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { | |
3651 { | 3649 { |
3652 // Call the runtime system in a fresh internal frame. | 3650 // Call the runtime system in a fresh internal frame. |
3653 ExternalReference miss = | 3651 ExternalReference miss = |
3654 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); | 3652 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); |
3655 | 3653 |
3656 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 3654 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
3657 __ Push(r1, r0); | 3655 __ Push(r1, r0); |
3658 __ Push(lr, r1, r0); | 3656 __ Push(lr, r1, r0); |
3659 __ mov(ip, Operand(Smi::FromInt(op()))); | 3657 __ mov(ip, Operand(Smi::FromInt(op()))); |
3660 __ push(ip); | 3658 __ push(ip); |
(...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4723 MemOperand(fp, 6 * kPointerSize), | 4721 MemOperand(fp, 6 * kPointerSize), |
4724 NULL); | 4722 NULL); |
4725 } | 4723 } |
4726 | 4724 |
4727 | 4725 |
4728 #undef __ | 4726 #undef __ |
4729 | 4727 |
4730 } } // namespace v8::internal | 4728 } } // namespace v8::internal |
4731 | 4729 |
4732 #endif // V8_TARGET_ARCH_ARM | 4730 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |