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 2668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2679 CallAsMethod()); | 2679 CallAsMethod()); |
2680 | 2680 |
2681 // Unreachable. | 2681 // Unreachable. |
2682 __ stop("Unexpected code address"); | 2682 __ stop("Unexpected code address"); |
2683 } | 2683 } |
2684 | 2684 |
2685 | 2685 |
2686 void CallICStub::Generate(MacroAssembler* masm) { | 2686 void CallICStub::Generate(MacroAssembler* masm) { |
2687 // r1 - function | 2687 // r1 - function |
2688 // r3 - slot id (Smi) | 2688 // r3 - slot id (Smi) |
| 2689 const int with_types_offset = |
| 2690 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); |
| 2691 const int generic_offset = |
| 2692 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); |
2689 Label extra_checks_or_miss, slow_start; | 2693 Label extra_checks_or_miss, slow_start; |
2690 Label slow, non_function, wrap, cont; | 2694 Label slow, non_function, wrap, cont; |
2691 Label have_js_function; | 2695 Label have_js_function; |
2692 int argc = arg_count(); | 2696 int argc = arg_count(); |
2693 ParameterCount actual(argc); | 2697 ParameterCount actual(argc); |
2694 | 2698 |
2695 EmitLoadTypeFeedbackVector(masm, r2); | 2699 EmitLoadTypeFeedbackVector(masm, r2); |
2696 | 2700 |
2697 // The checks. First, does r1 match the recorded monomorphic target? | 2701 // The checks. First, does r1 match the recorded monomorphic target? |
2698 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); | 2702 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); |
(...skipping 18 matching lines...) Expand all Loading... |
2717 | 2721 |
2718 __ bind(&slow); | 2722 __ bind(&slow); |
2719 EmitSlowCase(masm, argc, &non_function); | 2723 EmitSlowCase(masm, argc, &non_function); |
2720 | 2724 |
2721 if (CallAsMethod()) { | 2725 if (CallAsMethod()) { |
2722 __ bind(&wrap); | 2726 __ bind(&wrap); |
2723 EmitWrapCase(masm, argc, &cont); | 2727 EmitWrapCase(masm, argc, &cont); |
2724 } | 2728 } |
2725 | 2729 |
2726 __ bind(&extra_checks_or_miss); | 2730 __ bind(&extra_checks_or_miss); |
2727 Label miss; | 2731 Label uninitialized, miss; |
2728 | 2732 |
2729 __ CompareRoot(r4, Heap::kmegamorphic_symbolRootIndex); | 2733 __ CompareRoot(r4, Heap::kmegamorphic_symbolRootIndex); |
2730 __ b(eq, &slow_start); | 2734 __ b(eq, &slow_start); |
| 2735 |
| 2736 // The following cases attempt to handle MISS cases without going to the |
| 2737 // runtime. |
| 2738 if (FLAG_trace_ic) { |
| 2739 __ jmp(&miss); |
| 2740 } |
| 2741 |
2731 __ CompareRoot(r4, Heap::kuninitialized_symbolRootIndex); | 2742 __ CompareRoot(r4, Heap::kuninitialized_symbolRootIndex); |
| 2743 __ b(eq, &uninitialized); |
| 2744 |
| 2745 // We are going megamorphic. If the feedback is a JSFunction, it is fine |
| 2746 // to handle it here. More complex cases are dealt with in the runtime. |
| 2747 __ AssertNotSmi(r4); |
| 2748 __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE); |
| 2749 __ b(ne, &miss); |
| 2750 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); |
| 2751 __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); |
| 2752 __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize)); |
| 2753 // We have to update statistics for runtime profiling. |
| 2754 __ ldr(r4, FieldMemOperand(r2, with_types_offset)); |
| 2755 __ sub(r4, r4, Operand(Smi::FromInt(1))); |
| 2756 __ str(r4, FieldMemOperand(r2, with_types_offset)); |
| 2757 __ ldr(r4, FieldMemOperand(r2, generic_offset)); |
| 2758 __ add(r4, r4, Operand(Smi::FromInt(1))); |
| 2759 __ str(r4, FieldMemOperand(r2, generic_offset)); |
| 2760 __ jmp(&slow_start); |
| 2761 |
| 2762 __ bind(&uninitialized); |
| 2763 |
| 2764 // We are going monomorphic, provided we actually have a JSFunction. |
| 2765 __ JumpIfSmi(r1, &miss); |
| 2766 |
| 2767 // Goto miss case if we do not have a function. |
| 2768 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); |
| 2769 __ b(ne, &miss); |
| 2770 |
| 2771 // Make sure the function is not the Array() function, which requires special |
| 2772 // behavior on MISS. |
| 2773 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4); |
| 2774 __ cmp(r1, r4); |
2732 __ b(eq, &miss); | 2775 __ b(eq, &miss); |
2733 | 2776 |
2734 if (!FLAG_trace_ic) { | 2777 // Update stats. |
2735 // We are going megamorphic. If the feedback is a JSFunction, it is fine | 2778 __ ldr(r4, FieldMemOperand(r2, with_types_offset)); |
2736 // to handle it here. More complex cases are dealt with in the runtime. | 2779 __ add(r4, r4, Operand(Smi::FromInt(1))); |
2737 __ AssertNotSmi(r4); | 2780 __ str(r4, FieldMemOperand(r2, with_types_offset)); |
2738 __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE); | |
2739 __ b(ne, &miss); | |
2740 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); | |
2741 __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); | |
2742 __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize)); | |
2743 // We have to update statistics for runtime profiling. | |
2744 const int with_types_offset = | |
2745 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); | |
2746 __ ldr(r4, FieldMemOperand(r2, with_types_offset)); | |
2747 __ sub(r4, r4, Operand(Smi::FromInt(1))); | |
2748 __ str(r4, FieldMemOperand(r2, with_types_offset)); | |
2749 const int generic_offset = | |
2750 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); | |
2751 __ ldr(r4, FieldMemOperand(r2, generic_offset)); | |
2752 __ add(r4, r4, Operand(Smi::FromInt(1))); | |
2753 __ str(r4, FieldMemOperand(r2, generic_offset)); | |
2754 __ jmp(&slow_start); | |
2755 } | |
2756 | 2781 |
2757 // We are here because tracing is on or we are going monomorphic. | 2782 // Store the function. |
| 2783 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); |
| 2784 __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 2785 __ str(r1, MemOperand(r4, 0)); |
| 2786 |
| 2787 // Update the write barrier. |
| 2788 __ mov(r5, r1); |
| 2789 __ RecordWrite(r2, r4, r5, kLRHasNotBeenSaved, kDontSaveFPRegs, |
| 2790 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
| 2791 __ jmp(&have_js_function); |
| 2792 |
| 2793 // We are here because tracing is on or we encountered a MISS case we can't |
| 2794 // handle here. |
2758 __ bind(&miss); | 2795 __ bind(&miss); |
2759 GenerateMiss(masm); | 2796 GenerateMiss(masm); |
2760 | 2797 |
2761 // the slow case | 2798 // the slow case |
2762 __ bind(&slow_start); | 2799 __ bind(&slow_start); |
2763 // Check that the function is really a JavaScript function. | 2800 // Check that the function is really a JavaScript function. |
2764 // r1: pushed function (to be verified) | 2801 // r1: pushed function (to be verified) |
2765 __ JumpIfSmi(r1, &non_function); | 2802 __ JumpIfSmi(r1, &non_function); |
2766 | 2803 |
2767 // Goto slow case if we do not have a function. | 2804 // Goto slow case if we do not have a function. |
(...skipping 1951 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4719 MemOperand(fp, 6 * kPointerSize), | 4756 MemOperand(fp, 6 * kPointerSize), |
4720 NULL); | 4757 NULL); |
4721 } | 4758 } |
4722 | 4759 |
4723 | 4760 |
4724 #undef __ | 4761 #undef __ |
4725 | 4762 |
4726 } } // namespace v8::internal | 4763 } } // namespace v8::internal |
4727 | 4764 |
4728 #endif // V8_TARGET_ARCH_ARM | 4765 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |