OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 1736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1748 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1748 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1749 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1749 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1750 | 1750 |
1751 __ testl(FieldOperand(input, String::kHashFieldOffset), | 1751 __ testl(FieldOperand(input, String::kHashFieldOffset), |
1752 Immediate(String::kContainsCachedArrayIndexMask)); | 1752 Immediate(String::kContainsCachedArrayIndexMask)); |
1753 EmitBranch(true_block, false_block, equal); | 1753 EmitBranch(true_block, false_block, equal); |
1754 } | 1754 } |
1755 | 1755 |
1756 | 1756 |
1757 // Branches to a label or falls through with the answer in the z flag. | 1757 // Branches to a label or falls through with the answer in the z flag. |
1758 // Trashes the temp register and possibly input (if it and temp are aliased). | 1758 // Trashes the temp register. |
1759 void LCodeGen::EmitClassOfTest(Label* is_true, | 1759 void LCodeGen::EmitClassOfTest(Label* is_true, |
1760 Label* is_false, | 1760 Label* is_false, |
1761 Handle<String> class_name, | 1761 Handle<String> class_name, |
1762 Register input, | 1762 Register input, |
1763 Register temp, | 1763 Register temp, |
1764 Register scratch) { | 1764 Register temp2) { |
| 1765 ASSERT(!input.is(temp)); |
| 1766 ASSERT(!input.is(temp2)); |
| 1767 ASSERT(!temp.is(temp2)); |
| 1768 |
1765 __ JumpIfSmi(input, is_false); | 1769 __ JumpIfSmi(input, is_false); |
1766 | 1770 |
1767 if (class_name->IsEqualTo(CStrVector("Function"))) { | 1771 if (class_name->IsEqualTo(CStrVector("Function"))) { |
1768 // Assuming the following assertions, we can use the same compares to test | 1772 // Assuming the following assertions, we can use the same compares to test |
1769 // for both being a function type and being in the object type range. | 1773 // for both being a function type and being in the object type range. |
1770 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); | 1774 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); |
1771 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == | 1775 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == |
1772 FIRST_SPEC_OBJECT_TYPE + 1); | 1776 FIRST_SPEC_OBJECT_TYPE + 1); |
1773 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == | 1777 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == |
1774 LAST_SPEC_OBJECT_TYPE - 1); | 1778 LAST_SPEC_OBJECT_TYPE - 1); |
1775 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 1779 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
1776 __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp); | 1780 __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp); |
1777 __ j(below, is_false); | 1781 __ j(below, is_false); |
1778 __ j(equal, is_true); | 1782 __ j(equal, is_true); |
1779 __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE); | 1783 __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE); |
1780 __ j(equal, is_true); | 1784 __ j(equal, is_true); |
1781 } else { | 1785 } else { |
1782 // Faster code path to avoid two compares: subtract lower bound from the | 1786 // Faster code path to avoid two compares: subtract lower bound from the |
1783 // actual type and do a signed compare with the width of the type range. | 1787 // actual type and do a signed compare with the width of the type range. |
1784 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); | 1788 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); |
1785 __ movq(scratch, FieldOperand(temp, Map::kInstanceTypeOffset)); | 1789 __ movq(temp2, FieldOperand(temp, Map::kInstanceTypeOffset)); |
1786 __ subb(scratch, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 1790 __ subb(temp2, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
1787 __ cmpb(scratch, | 1791 __ cmpb(temp2, |
1788 Immediate(static_cast<int8_t>(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - | 1792 Immediate(static_cast<int8_t>(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - |
1789 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE))); | 1793 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE))); |
1790 __ j(above, is_false); | 1794 __ j(above, is_false); |
1791 } | 1795 } |
1792 | 1796 |
1793 // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. | 1797 // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. |
1794 // Check if the constructor in the map is a function. | 1798 // Check if the constructor in the map is a function. |
1795 __ movq(temp, FieldOperand(temp, Map::kConstructorOffset)); | 1799 __ movq(temp, FieldOperand(temp, Map::kConstructorOffset)); |
1796 | 1800 |
1797 // Objects with a non-function constructor have class 'Object'. | 1801 // Objects with a non-function constructor have class 'Object'. |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1890 __ JumpIfSmi(object, &false_result); | 1894 __ JumpIfSmi(object, &false_result); |
1891 | 1895 |
1892 // This is the inlined call site instanceof cache. The two occurences of the | 1896 // This is the inlined call site instanceof cache. The two occurences of the |
1893 // hole value will be patched to the last map/result pair generated by the | 1897 // hole value will be patched to the last map/result pair generated by the |
1894 // instanceof stub. | 1898 // instanceof stub. |
1895 Label cache_miss; | 1899 Label cache_miss; |
1896 // Use a temp register to avoid memory operands with variable lengths. | 1900 // Use a temp register to avoid memory operands with variable lengths. |
1897 Register map = ToRegister(instr->TempAt(0)); | 1901 Register map = ToRegister(instr->TempAt(0)); |
1898 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); | 1902 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); |
1899 __ bind(deferred->map_check()); // Label for calculating code patching. | 1903 __ bind(deferred->map_check()); // Label for calculating code patching. |
1900 __ movq(kScratchRegister, factory()->the_hole_value(), | 1904 Handle<JSGlobalPropertyCell> cache_cell = |
1901 RelocInfo::EMBEDDED_OBJECT); | 1905 factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); |
1902 __ cmpq(map, kScratchRegister); // Patched to cached map. | 1906 __ movq(kScratchRegister, cache_cell, RelocInfo::GLOBAL_PROPERTY_CELL); |
| 1907 __ cmpq(map, Operand(kScratchRegister, 0)); |
1903 __ j(not_equal, &cache_miss, Label::kNear); | 1908 __ j(not_equal, &cache_miss, Label::kNear); |
1904 // Patched to load either true or false. | 1909 // Patched to load either true or false. |
1905 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); | 1910 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); |
1906 #ifdef DEBUG | 1911 #ifdef DEBUG |
1907 // Check that the code size between patch label and patch sites is invariant. | 1912 // Check that the code size between patch label and patch sites is invariant. |
1908 Label end_of_patched_code; | 1913 Label end_of_patched_code; |
1909 __ bind(&end_of_patched_code); | 1914 __ bind(&end_of_patched_code); |
1910 ASSERT(true); | 1915 ASSERT(true); |
1911 #endif | 1916 #endif |
1912 __ jmp(&done); | 1917 __ jmp(&done); |
(...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2629 RecordPosition(pointers->position()); | 2634 RecordPosition(pointers->position()); |
2630 | 2635 |
2631 // Invoke function. | 2636 // Invoke function. |
2632 __ SetCallKind(rcx, call_kind); | 2637 __ SetCallKind(rcx, call_kind); |
2633 if (*function == *info()->closure()) { | 2638 if (*function == *info()->closure()) { |
2634 __ CallSelf(); | 2639 __ CallSelf(); |
2635 } else { | 2640 } else { |
2636 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 2641 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
2637 } | 2642 } |
2638 | 2643 |
2639 // Setup deoptimization. | 2644 // Set up deoptimization. |
2640 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); | 2645 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); |
2641 | 2646 |
2642 // Restore context. | 2647 // Restore context. |
2643 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2648 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2644 } | 2649 } |
2645 | 2650 |
2646 | 2651 |
2647 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 2652 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
2648 ASSERT(ToRegister(instr->result()).is(rax)); | 2653 ASSERT(ToRegister(instr->result()).is(rax)); |
2649 __ LoadHeapObject(rdi, instr->function()); | 2654 __ LoadHeapObject(rdi, instr->function()); |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2919 MathPowStub stub(MathPowStub::INTEGER); | 2924 MathPowStub stub(MathPowStub::INTEGER); |
2920 __ CallStub(&stub); | 2925 __ CallStub(&stub); |
2921 } else { | 2926 } else { |
2922 ASSERT(exponent_type.IsDouble()); | 2927 ASSERT(exponent_type.IsDouble()); |
2923 MathPowStub stub(MathPowStub::DOUBLE); | 2928 MathPowStub stub(MathPowStub::DOUBLE); |
2924 __ CallStub(&stub); | 2929 __ CallStub(&stub); |
2925 } | 2930 } |
2926 } | 2931 } |
2927 | 2932 |
2928 | 2933 |
| 2934 void LCodeGen::DoRandom(LRandom* instr) { |
| 2935 // Having marked this instruction as a call we can use any |
| 2936 // registers. |
| 2937 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 2938 |
| 2939 // Choose the right register for the first argument depending on |
| 2940 // calling convention. |
| 2941 #ifdef _WIN64 |
| 2942 ASSERT(ToRegister(instr->InputAt(0)).is(rcx)); |
| 2943 Register global_object = rcx; |
| 2944 #else |
| 2945 ASSERT(ToRegister(instr->InputAt(0)).is(rdi)); |
| 2946 Register global_object = rdi; |
| 2947 #endif |
| 2948 |
| 2949 __ PrepareCallCFunction(1); |
| 2950 __ movq(global_object, |
| 2951 FieldOperand(global_object, GlobalObject::kGlobalContextOffset)); |
| 2952 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); |
| 2953 |
| 2954 // Convert 32 random bits in rax to 0.(32 random bits) in a double |
| 2955 // by computing: |
| 2956 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). |
| 2957 __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. |
| 2958 __ movd(xmm2, rcx); |
| 2959 __ movd(xmm1, rax); |
| 2960 __ cvtss2sd(xmm2, xmm2); |
| 2961 __ xorps(xmm1, xmm2); |
| 2962 __ subsd(xmm1, xmm2); |
| 2963 } |
| 2964 |
| 2965 |
2929 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { | 2966 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { |
2930 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 2967 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
2931 TranscendentalCacheStub stub(TranscendentalCache::LOG, | 2968 TranscendentalCacheStub stub(TranscendentalCache::LOG, |
2932 TranscendentalCacheStub::UNTAGGED); | 2969 TranscendentalCacheStub::UNTAGGED); |
2933 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2970 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
2934 } | 2971 } |
2935 | 2972 |
2936 | 2973 |
2937 void LCodeGen::DoMathTan(LUnaryMathOperation* instr) { | 2974 void LCodeGen::DoMathTan(LUnaryMathOperation* instr) { |
2938 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 2975 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3503 Condition is_smi = __ CheckSmi(input); | 3540 Condition is_smi = __ CheckSmi(input); |
3504 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); | 3541 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); |
3505 } | 3542 } |
3506 __ SmiToInteger32(input, input); | 3543 __ SmiToInteger32(input, input); |
3507 } | 3544 } |
3508 | 3545 |
3509 | 3546 |
3510 void LCodeGen::EmitNumberUntagD(Register input_reg, | 3547 void LCodeGen::EmitNumberUntagD(Register input_reg, |
3511 XMMRegister result_reg, | 3548 XMMRegister result_reg, |
3512 bool deoptimize_on_undefined, | 3549 bool deoptimize_on_undefined, |
| 3550 bool deoptimize_on_minus_zero, |
3513 LEnvironment* env) { | 3551 LEnvironment* env) { |
3514 Label load_smi, done; | 3552 Label load_smi, done; |
3515 | 3553 |
3516 // Smi check. | 3554 // Smi check. |
3517 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); | 3555 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); |
3518 | 3556 |
3519 // Heap number map check. | 3557 // Heap number map check. |
3520 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 3558 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
3521 Heap::kHeapNumberMapRootIndex); | 3559 Heap::kHeapNumberMapRootIndex); |
3522 if (deoptimize_on_undefined) { | 3560 if (deoptimize_on_undefined) { |
3523 DeoptimizeIf(not_equal, env); | 3561 DeoptimizeIf(not_equal, env); |
3524 } else { | 3562 } else { |
3525 Label heap_number; | 3563 Label heap_number; |
3526 __ j(equal, &heap_number, Label::kNear); | 3564 __ j(equal, &heap_number, Label::kNear); |
3527 | 3565 |
3528 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | 3566 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
3529 DeoptimizeIf(not_equal, env); | 3567 DeoptimizeIf(not_equal, env); |
3530 | 3568 |
3531 // Convert undefined to NaN. Compute NaN as 0/0. | 3569 // Convert undefined to NaN. Compute NaN as 0/0. |
3532 __ xorps(result_reg, result_reg); | 3570 __ xorps(result_reg, result_reg); |
3533 __ divsd(result_reg, result_reg); | 3571 __ divsd(result_reg, result_reg); |
3534 __ jmp(&done, Label::kNear); | 3572 __ jmp(&done, Label::kNear); |
3535 | 3573 |
3536 __ bind(&heap_number); | 3574 __ bind(&heap_number); |
3537 } | 3575 } |
3538 // Heap number to XMM conversion. | 3576 // Heap number to XMM conversion. |
3539 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3577 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3578 if (deoptimize_on_minus_zero) { |
| 3579 XMMRegister xmm_scratch = xmm0; |
| 3580 __ xorps(xmm_scratch, xmm_scratch); |
| 3581 __ ucomisd(xmm_scratch, result_reg); |
| 3582 __ j(not_equal, &done, Label::kNear); |
| 3583 __ movmskpd(kScratchRegister, result_reg); |
| 3584 __ testq(kScratchRegister, Immediate(1)); |
| 3585 DeoptimizeIf(not_zero, env); |
| 3586 } |
3540 __ jmp(&done, Label::kNear); | 3587 __ jmp(&done, Label::kNear); |
3541 | 3588 |
3542 // Smi to XMM conversion | 3589 // Smi to XMM conversion |
3543 __ bind(&load_smi); | 3590 __ bind(&load_smi); |
3544 __ SmiToInteger32(kScratchRegister, input_reg); | 3591 __ SmiToInteger32(kScratchRegister, input_reg); |
3545 __ cvtlsi2sd(result_reg, kScratchRegister); | 3592 __ cvtlsi2sd(result_reg, kScratchRegister); |
3546 __ bind(&done); | 3593 __ bind(&done); |
3547 } | 3594 } |
3548 | 3595 |
3549 | 3596 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3621 LOperand* input = instr->InputAt(0); | 3668 LOperand* input = instr->InputAt(0); |
3622 ASSERT(input->IsRegister()); | 3669 ASSERT(input->IsRegister()); |
3623 LOperand* result = instr->result(); | 3670 LOperand* result = instr->result(); |
3624 ASSERT(result->IsDoubleRegister()); | 3671 ASSERT(result->IsDoubleRegister()); |
3625 | 3672 |
3626 Register input_reg = ToRegister(input); | 3673 Register input_reg = ToRegister(input); |
3627 XMMRegister result_reg = ToDoubleRegister(result); | 3674 XMMRegister result_reg = ToDoubleRegister(result); |
3628 | 3675 |
3629 EmitNumberUntagD(input_reg, result_reg, | 3676 EmitNumberUntagD(input_reg, result_reg, |
3630 instr->hydrogen()->deoptimize_on_undefined(), | 3677 instr->hydrogen()->deoptimize_on_undefined(), |
| 3678 instr->hydrogen()->deoptimize_on_minus_zero(), |
3631 instr->environment()); | 3679 instr->environment()); |
3632 } | 3680 } |
3633 | 3681 |
3634 | 3682 |
3635 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 3683 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
3636 LOperand* input = instr->InputAt(0); | 3684 LOperand* input = instr->InputAt(0); |
3637 ASSERT(input->IsDoubleRegister()); | 3685 ASSERT(input->IsDoubleRegister()); |
3638 LOperand* result = instr->result(); | 3686 LOperand* result = instr->result(); |
3639 ASSERT(result->IsRegister()); | 3687 ASSERT(result->IsRegister()); |
3640 | 3688 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3740 isolate()->factory()->NewJSGlobalPropertyCell(target); | 3788 isolate()->factory()->NewJSGlobalPropertyCell(target); |
3741 __ movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL); | 3789 __ movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL); |
3742 __ cmpq(reg, Operand(kScratchRegister, 0)); | 3790 __ cmpq(reg, Operand(kScratchRegister, 0)); |
3743 } else { | 3791 } else { |
3744 __ Cmp(reg, target); | 3792 __ Cmp(reg, target); |
3745 } | 3793 } |
3746 DeoptimizeIf(not_equal, instr->environment()); | 3794 DeoptimizeIf(not_equal, instr->environment()); |
3747 } | 3795 } |
3748 | 3796 |
3749 | 3797 |
| 3798 void LCodeGen::DoCheckMapCommon(Register reg, |
| 3799 Handle<Map> map, |
| 3800 CompareMapMode mode, |
| 3801 LEnvironment* env) { |
| 3802 Label success; |
| 3803 __ CompareMap(reg, map, &success, mode); |
| 3804 DeoptimizeIf(not_equal, env); |
| 3805 __ bind(&success); |
| 3806 } |
| 3807 |
| 3808 |
3750 void LCodeGen::DoCheckMap(LCheckMap* instr) { | 3809 void LCodeGen::DoCheckMap(LCheckMap* instr) { |
3751 LOperand* input = instr->InputAt(0); | 3810 LOperand* input = instr->InputAt(0); |
3752 ASSERT(input->IsRegister()); | 3811 ASSERT(input->IsRegister()); |
3753 Register reg = ToRegister(input); | 3812 Register reg = ToRegister(input); |
3754 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), | 3813 Handle<Map> map = instr->hydrogen()->map(); |
3755 instr->hydrogen()->map()); | 3814 DoCheckMapCommon(reg, map, instr->hydrogen()->mode(), instr->environment()); |
3756 DeoptimizeIf(not_equal, instr->environment()); | |
3757 } | 3815 } |
3758 | 3816 |
3759 | 3817 |
3760 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 3818 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
3761 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); | 3819 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); |
3762 Register result_reg = ToRegister(instr->result()); | 3820 Register result_reg = ToRegister(instr->result()); |
3763 Register temp_reg = ToRegister(instr->TempAt(0)); | 3821 Register temp_reg = ToRegister(instr->TempAt(0)); |
3764 __ ClampDoubleToUint8(value_reg, xmm0, result_reg, temp_reg); | 3822 __ ClampDoubleToUint8(value_reg, xmm0, result_reg, temp_reg); |
3765 } | 3823 } |
3766 | 3824 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3812 Register reg = ToRegister(instr->TempAt(0)); | 3870 Register reg = ToRegister(instr->TempAt(0)); |
3813 | 3871 |
3814 Handle<JSObject> holder = instr->holder(); | 3872 Handle<JSObject> holder = instr->holder(); |
3815 Handle<JSObject> current_prototype = instr->prototype(); | 3873 Handle<JSObject> current_prototype = instr->prototype(); |
3816 | 3874 |
3817 // Load prototype object. | 3875 // Load prototype object. |
3818 __ LoadHeapObject(reg, current_prototype); | 3876 __ LoadHeapObject(reg, current_prototype); |
3819 | 3877 |
3820 // Check prototype maps up to the holder. | 3878 // Check prototype maps up to the holder. |
3821 while (!current_prototype.is_identical_to(holder)) { | 3879 while (!current_prototype.is_identical_to(holder)) { |
3822 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), | 3880 DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), |
3823 Handle<Map>(current_prototype->map())); | 3881 ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); |
3824 DeoptimizeIf(not_equal, instr->environment()); | |
3825 current_prototype = | 3882 current_prototype = |
3826 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); | 3883 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); |
3827 // Load next prototype object. | 3884 // Load next prototype object. |
3828 __ LoadHeapObject(reg, current_prototype); | 3885 __ LoadHeapObject(reg, current_prototype); |
3829 } | 3886 } |
3830 | 3887 |
3831 // Check the holder map. | 3888 // Check the holder map. |
3832 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), | 3889 DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), |
3833 Handle<Map>(current_prototype->map())); | 3890 ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); |
3834 DeoptimizeIf(not_equal, instr->environment()); | |
3835 } | 3891 } |
3836 | 3892 |
3837 | 3893 |
3838 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 3894 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
3839 Heap* heap = isolate()->heap(); | 3895 Heap* heap = isolate()->heap(); |
3840 ElementsKind boilerplate_elements_kind = | 3896 ElementsKind boilerplate_elements_kind = |
3841 instr->hydrogen()->boilerplate_elements_kind(); | 3897 instr->hydrogen()->boilerplate_elements_kind(); |
3842 | 3898 |
3843 // Deopt if the array literal boilerplate ElementsKind is of a type different | 3899 // Deopt if the array literal boilerplate ElementsKind is of a type different |
3844 // than the expected one. The check isn't necessary if the boilerplate has | 3900 // than the expected one. The check isn't necessary if the boilerplate has |
3845 // already been converted to FAST_ELEMENTS. | 3901 // already been converted to FAST_ELEMENTS. |
3846 if (boilerplate_elements_kind != FAST_ELEMENTS) { | 3902 if (boilerplate_elements_kind != FAST_ELEMENTS) { |
3847 __ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object()); | 3903 __ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object()); |
3848 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 3904 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
3849 // Load the map's "bit field 2". | 3905 // Load the map's "bit field 2". |
3850 __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); | 3906 __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); |
3851 // Retrieve elements_kind from bit field 2. | 3907 // Retrieve elements_kind from bit field 2. |
3852 __ and_(rbx, Immediate(Map::kElementsKindMask)); | 3908 __ and_(rbx, Immediate(Map::kElementsKindMask)); |
3853 __ cmpb(rbx, Immediate(boilerplate_elements_kind << | 3909 __ cmpb(rbx, Immediate(boilerplate_elements_kind << |
3854 Map::kElementsKindShift)); | 3910 Map::kElementsKindShift)); |
3855 DeoptimizeIf(not_equal, instr->environment()); | 3911 DeoptimizeIf(not_equal, instr->environment()); |
3856 } | 3912 } |
3857 | 3913 |
3858 // Setup the parameters to the stub/runtime call. | 3914 // Set up the parameters to the stub/runtime call. |
3859 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 3915 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
3860 __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); | 3916 __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); |
3861 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); | 3917 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); |
3862 // Boilerplate already exists, constant elements are never accessed. | 3918 // Boilerplate already exists, constant elements are never accessed. |
3863 // Pass an empty fixed array. | 3919 // Pass an empty fixed array. |
3864 __ Push(Handle<FixedArray>(heap->empty_fixed_array())); | 3920 __ Push(Handle<FixedArray>(heap->empty_fixed_array())); |
3865 | 3921 |
3866 // Pick the right runtime function or stub to call. | 3922 // Pick the right runtime function or stub to call. |
3867 int length = instr->hydrogen()->length(); | 3923 int length = instr->hydrogen()->length(); |
3868 if (instr->hydrogen()->IsCopyOnWrite()) { | 3924 if (instr->hydrogen()->IsCopyOnWrite()) { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3949 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); | 4005 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); |
3950 EmitDeepCopy(instr->hydrogen()->boilerplate(), rax, rbx, &offset); | 4006 EmitDeepCopy(instr->hydrogen()->boilerplate(), rax, rbx, &offset); |
3951 ASSERT_EQ(size, offset); | 4007 ASSERT_EQ(size, offset); |
3952 } | 4008 } |
3953 | 4009 |
3954 | 4010 |
3955 void LCodeGen::DoObjectLiteralGeneric(LObjectLiteralGeneric* instr) { | 4011 void LCodeGen::DoObjectLiteralGeneric(LObjectLiteralGeneric* instr) { |
3956 Handle<FixedArray> constant_properties = | 4012 Handle<FixedArray> constant_properties = |
3957 instr->hydrogen()->constant_properties(); | 4013 instr->hydrogen()->constant_properties(); |
3958 | 4014 |
3959 // Setup the parameters to the stub/runtime call. | 4015 // Set up the parameters to the stub/runtime call. |
3960 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 4016 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
3961 __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); | 4017 __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); |
3962 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); | 4018 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); |
3963 __ Push(constant_properties); | 4019 __ Push(constant_properties); |
3964 int flags = instr->hydrogen()->fast_elements() | 4020 int flags = instr->hydrogen()->fast_elements() |
3965 ? ObjectLiteral::kFastElements | 4021 ? ObjectLiteral::kFastElements |
3966 : ObjectLiteral::kNoFlags; | 4022 : ObjectLiteral::kNoFlags; |
3967 flags |= instr->hydrogen()->has_function() | 4023 flags |= instr->hydrogen()->has_function() |
3968 ? ObjectLiteral::kHasFunction | 4024 ? ObjectLiteral::kHasFunction |
3969 : ObjectLiteral::kNoFlags; | 4025 : ObjectLiteral::kNoFlags; |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4329 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 4385 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
4330 ASSERT(osr_pc_offset_ == -1); | 4386 ASSERT(osr_pc_offset_ == -1); |
4331 osr_pc_offset_ = masm()->pc_offset(); | 4387 osr_pc_offset_ = masm()->pc_offset(); |
4332 } | 4388 } |
4333 | 4389 |
4334 #undef __ | 4390 #undef __ |
4335 | 4391 |
4336 } } // namespace v8::internal | 4392 } } // namespace v8::internal |
4337 | 4393 |
4338 #endif // V8_TARGET_ARCH_X64 | 4394 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |