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 2694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2705 CallFunctionNoFeedback(masm, | 2705 CallFunctionNoFeedback(masm, |
2706 arg_count(), | 2706 arg_count(), |
2707 true, | 2707 true, |
2708 CallAsMethod()); | 2708 CallAsMethod()); |
2709 | 2709 |
2710 // Unreachable. | 2710 // Unreachable. |
2711 __ stop("Unexpected code address"); | 2711 __ stop("Unexpected code address"); |
2712 } | 2712 } |
2713 | 2713 |
2714 | 2714 |
2715 void CallIC_RoundStub::Generate(MacroAssembler* masm) { | |
2716 Register function = r1; | |
2717 Register vector = r2; | |
2718 Register slot = r3; | |
2719 | |
2720 Register temp1 = r0; | |
2721 Register temp2 = r4; | |
2722 DwVfpRegister double_temp1 = d1; | |
2723 DwVfpRegister double_temp2 = d2; | |
2724 Label tail, miss; | |
2725 | |
2726 // Ensure nobody has snuck in another function. | |
2727 __ BranchIfNotBuiltin(function, temp1, kMathRound, &miss); | |
2728 | |
2729 if (arg_count() > 0) { | |
2730 __ ldr(temp1, MemOperand(sp, (arg_count() - 1) * kPointerSize)); | |
2731 Handle<Map> map = isolate()->factory()->heap_number_map(); | |
2732 __ CheckMap(temp1, temp2, map, &tail, DO_SMI_CHECK); | |
2733 __ sub(temp1, temp1, Operand(kHeapObjectTag)); | |
2734 __ vldr(double_temp1, temp1, HeapNumber::kValueOffset); | |
2735 | |
2736 // If the number is >0, it doesn't round to -0 | |
2737 __ Vmov(double_temp2, 0, temp1); | |
2738 __ VFPCompareAndSetFlags(double_temp1, double_temp2); | |
2739 __ b(gt, &tail); | |
2740 | |
2741 // If the number is <-.5, it doesn't round to -0 | |
2742 __ Vmov(double_temp2, -.5, temp1); | |
2743 __ VFPCompareAndSetFlags(double_temp1, double_temp2); | |
2744 __ b(lt, &tail); | |
2745 | |
2746 // +0 doesn't round to -0 | |
2747 __ VmovHigh(temp1, double_temp1); | |
2748 __ cmp(temp1, Operand(0x80000000)); | |
2749 __ b(ne, &tail); | |
2750 | |
2751 __ mov(temp1, Operand(slot, LSL, 1)); | |
2752 __ add(temp1, temp1, vector); | |
2753 __ Move(temp2, Operand(Smi::FromInt(kHasReturnedMinusZeroSentinel))); | |
2754 __ str(temp2, | |
2755 FieldMemOperand(temp1, FixedArray::kHeaderSize + kPointerSize)); | |
2756 } | |
2757 | |
2758 __ bind(&tail); | |
2759 // The slow case, we need this no matter what to complete a call after a miss. | |
2760 CallFunctionNoFeedback(masm, arg_count(), true, CallAsMethod()); | |
2761 | |
2762 // Unreachable. | |
2763 __ stop("Unreachable"); | |
2764 | |
2765 __ bind(&miss); | |
2766 GenerateMiss(masm); | |
2767 __ b(&tail); | |
2768 } | |
2769 | |
2770 | |
2771 void CallIC_FloorStub::Generate(MacroAssembler* masm) { | |
2772 Register function = r1; | |
2773 Register vector = r2; | |
2774 Register slot = r3; | |
2775 | |
2776 Register temp1 = r0; | |
2777 Register temp2 = r4; | |
2778 DwVfpRegister double_temp = d1; | |
2779 Label tail, miss; | |
2780 | |
2781 // Ensure nobody has snuck in another function. | |
2782 __ BranchIfNotBuiltin(function, temp1, kMathFloor, &miss); | |
2783 | |
2784 if (arg_count() > 0) { | |
2785 __ ldr(temp1, MemOperand(sp, (arg_count() - 1) * kPointerSize)); | |
2786 Handle<Map> map = isolate()->factory()->heap_number_map(); | |
2787 __ CheckMap(temp1, temp2, map, &tail, DO_SMI_CHECK); | |
2788 __ sub(temp1, temp1, Operand(kHeapObjectTag)); | |
2789 __ vldr(double_temp, temp1, HeapNumber::kValueOffset); | |
2790 | |
2791 // Only -0 floors to -0. | |
2792 __ VmovHigh(temp1, double_temp); | |
2793 __ cmp(temp1, Operand(0x80000000)); | |
2794 __ b(ne, &tail); | |
2795 __ VmovLow(temp1, double_temp); | |
2796 __ cmp(temp1, Operand(0)); | |
2797 __ b(ne, &tail); | |
2798 | |
2799 __ mov(temp1, Operand(slot, LSL, 1)); | |
2800 __ add(temp1, temp1, vector); | |
2801 __ Move(temp2, Operand(Smi::FromInt(kHasReturnedMinusZeroSentinel))); | |
2802 __ str(temp2, | |
2803 FieldMemOperand(temp1, FixedArray::kHeaderSize + kPointerSize)); | |
2804 } | |
2805 | |
2806 __ bind(&tail); | |
2807 // The slow case, we need this no matter what to complete a call after a miss. | |
2808 CallFunctionNoFeedback(masm, arg_count(), true, CallAsMethod()); | |
2809 | |
2810 // Unreachable. | |
2811 __ stop("Unreachable"); | |
2812 | |
2813 __ bind(&miss); | |
2814 GenerateMiss(masm); | |
2815 __ b(&tail); | |
2816 } | |
2817 | |
2818 | |
2819 void CallIC_CeilStub::Generate(MacroAssembler* masm) { | |
2820 Register function = r1; | |
2821 Register vector = r2; | |
2822 Register slot = r3; | |
2823 | |
2824 Register temp1 = r0; | |
2825 Register temp2 = r4; | |
2826 DwVfpRegister double_temp1 = d1; | |
2827 DwVfpRegister double_temp2 = d2; | |
2828 Label tail, miss; | |
2829 | |
2830 // Ensure nobody has snuck in another function. | |
2831 __ BranchIfNotBuiltin(function, temp1, kMathCeil, &miss); | |
2832 | |
2833 if (arg_count() > 0) { | |
2834 __ ldr(temp1, MemOperand(sp, (arg_count() - 1) * kPointerSize)); | |
2835 Handle<Map> map = isolate()->factory()->heap_number_map(); | |
2836 __ CheckMap(temp1, temp2, map, &tail, DO_SMI_CHECK); | |
2837 __ sub(temp1, temp1, Operand(kHeapObjectTag)); | |
2838 __ vldr(double_temp1, temp1, HeapNumber::kValueOffset); | |
2839 | |
2840 // If the number is >0, it doesn't round to -0 | |
2841 __ Vmov(double_temp2, 0, temp1); | |
2842 __ VFPCompareAndSetFlags(double_temp1, double_temp2); | |
2843 __ b(gt, &tail); | |
2844 | |
2845 // If the number is <=-1, it doesn't round to -0 | |
2846 __ Vmov(double_temp2, -1, temp1); | |
2847 __ VFPCompareAndSetFlags(double_temp1, double_temp2); | |
2848 __ b(le, &tail); | |
2849 | |
2850 // +0 doesn't round to -0. | |
2851 __ VmovHigh(temp1, double_temp1); | |
2852 __ cmp(temp1, Operand(0x80000000)); | |
2853 __ b(ne, &tail); | |
2854 | |
2855 __ mov(temp1, Operand(slot, LSL, 1)); | |
2856 __ add(temp1, temp1, vector); | |
2857 __ Move(temp2, Operand(Smi::FromInt(kHasReturnedMinusZeroSentinel))); | |
2858 __ str(temp2, | |
2859 FieldMemOperand(temp1, FixedArray::kHeaderSize + kPointerSize)); | |
2860 } | |
2861 | |
2862 __ bind(&tail); | |
2863 // The slow case, we need this no matter what to complete a call after a miss. | |
2864 CallFunctionNoFeedback(masm, arg_count(), true, CallAsMethod()); | |
2865 | |
2866 // Unreachable. | |
2867 __ stop("Unreachable"); | |
2868 | |
2869 __ bind(&miss); | |
2870 GenerateMiss(masm); | |
2871 __ b(&tail); | |
2872 } | |
2873 | |
2874 | |
2875 void CallICStub::Generate(MacroAssembler* masm) { | 2715 void CallICStub::Generate(MacroAssembler* masm) { |
2876 // r1 - function | 2716 // r1 - function |
2877 // r3 - slot id (Smi) | 2717 // r3 - slot id (Smi) |
2878 // r2 - vector | 2718 // r2 - vector |
2879 const int with_types_offset = | 2719 const int with_types_offset = |
2880 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); | 2720 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); |
2881 const int generic_offset = | 2721 const int generic_offset = |
2882 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); | 2722 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); |
2883 Label extra_checks_or_miss, slow_start; | 2723 Label extra_checks_or_miss, slow_start; |
2884 Label slow, non_function, wrap, cont; | 2724 Label slow, non_function, wrap, cont; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2975 // Goto miss case if we do not have a function. | 2815 // Goto miss case if we do not have a function. |
2976 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); | 2816 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); |
2977 __ b(ne, &miss); | 2817 __ b(ne, &miss); |
2978 | 2818 |
2979 // Make sure the function is not the Array() function, which requires special | 2819 // Make sure the function is not the Array() function, which requires special |
2980 // behavior on MISS. | 2820 // behavior on MISS. |
2981 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4); | 2821 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4); |
2982 __ cmp(r1, r4); | 2822 __ cmp(r1, r4); |
2983 __ b(eq, &miss); | 2823 __ b(eq, &miss); |
2984 | 2824 |
2985 // Some builtin functions require special handling, miss to the runtime. | |
2986 __ ldr(r0, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | |
2987 __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kFunctionDataOffset)); | |
2988 __ cmp(r0, Operand(Smi::FromInt(0))); | |
2989 __ b(ne, &miss); | |
2990 | |
2991 // Update stats. | 2825 // Update stats. |
2992 __ ldr(r4, FieldMemOperand(r2, with_types_offset)); | 2826 __ ldr(r4, FieldMemOperand(r2, with_types_offset)); |
2993 __ add(r4, r4, Operand(Smi::FromInt(1))); | 2827 __ add(r4, r4, Operand(Smi::FromInt(1))); |
2994 __ str(r4, FieldMemOperand(r2, with_types_offset)); | 2828 __ str(r4, FieldMemOperand(r2, with_types_offset)); |
2995 | 2829 |
2996 // Store the function. Use a stub since we need a frame for allocation. | 2830 // Store the function. Use a stub since we need a frame for allocation. |
2997 // r2 - vector | 2831 // r2 - vector |
2998 // r3 - slot | 2832 // r3 - slot |
2999 // r1 - function | 2833 // r1 - function |
3000 { | 2834 { |
(...skipping 1523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4524 } | 4358 } |
4525 | 4359 |
4526 | 4360 |
4527 void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) { | 4361 void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) { |
4528 EmitLoadTypeFeedbackVector(masm, r2); | 4362 EmitLoadTypeFeedbackVector(masm, r2); |
4529 CallIC_ArrayStub stub(isolate(), state()); | 4363 CallIC_ArrayStub stub(isolate(), state()); |
4530 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 4364 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
4531 } | 4365 } |
4532 | 4366 |
4533 | 4367 |
4534 void CallIC_RoundTrampolineStub::Generate(MacroAssembler* masm) { | |
4535 EmitLoadTypeFeedbackVector(masm, r2); | |
4536 CallIC_RoundStub stub(isolate(), state()); | |
4537 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | |
4538 } | |
4539 | |
4540 | |
4541 void CallIC_FloorTrampolineStub::Generate(MacroAssembler* masm) { | |
4542 EmitLoadTypeFeedbackVector(masm, r2); | |
4543 CallIC_FloorStub stub(isolate(), state()); | |
4544 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | |
4545 } | |
4546 | |
4547 | |
4548 void CallIC_CeilTrampolineStub::Generate(MacroAssembler* masm) { | |
4549 EmitLoadTypeFeedbackVector(masm, r2); | |
4550 CallIC_CeilStub stub(isolate(), state()); | |
4551 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | |
4552 } | |
4553 | |
4554 | |
4555 void VectorRawLoadStub::Generate(MacroAssembler* masm) { | 4368 void VectorRawLoadStub::Generate(MacroAssembler* masm) { |
4556 GenerateImpl(masm, false); | 4369 GenerateImpl(masm, false); |
4557 } | 4370 } |
4558 | 4371 |
4559 | 4372 |
4560 void VectorRawLoadStub::GenerateForTrampoline(MacroAssembler* masm) { | 4373 void VectorRawLoadStub::GenerateForTrampoline(MacroAssembler* masm) { |
4561 GenerateImpl(masm, true); | 4374 GenerateImpl(masm, true); |
4562 } | 4375 } |
4563 | 4376 |
4564 | 4377 |
(...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5470 kStackUnwindSpace, NULL, | 5283 kStackUnwindSpace, NULL, |
5471 MemOperand(fp, 6 * kPointerSize), NULL); | 5284 MemOperand(fp, 6 * kPointerSize), NULL); |
5472 } | 5285 } |
5473 | 5286 |
5474 | 5287 |
5475 #undef __ | 5288 #undef __ |
5476 | 5289 |
5477 } } // namespace v8::internal | 5290 } } // namespace v8::internal |
5478 | 5291 |
5479 #endif // V8_TARGET_ARCH_ARM | 5292 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |