1%def op_invoke_custom(): 2 EXPORT_PC 3 FETCH r0, 1 // call_site index, first argument of runtime call. 4 b NterpCommonInvokeCustom 5 6%def op_invoke_custom_range(): 7 EXPORT_PC 8 FETCH r0, 1 // call_site index, first argument of runtime call. 9 b NterpCommonInvokeCustomRange 10 11%def invoke_direct_or_super(helper="", range="", is_super=""): 12 EXPORT_PC 13 // Fast-path which gets the method from thread-local cache. 14% fetch_from_thread_cache("r0", miss_label="2f") 151: 16 // Load the first argument (the 'this' pointer). 17 FETCH r1, 2 18 .if !$range 19 and r1, r1, #0xf 20 .endif 21 GET_VREG r1, r1 22 cmp r1, #0 23 beq common_errNullObject // bail if null 24 b $helper 252: 26 mov r0, rSELF 27 ldr r1, [sp] 28 mov r2, rPC 29 bl nterp_get_method 30 .if $is_super 31 b 1b 32 .else 33 tst r0, #1 34 beq 1b 35 and r0, r0, #-2 // Remove the extra bit that marks it's a String.<init> method. 36 .if $range 37 b NterpHandleStringInitRange 38 .else 39 b NterpHandleStringInit 40 .endif 41 .endif 42 43%def op_invoke_direct(): 44% invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="0") 45 46%def op_invoke_direct_range(): 47% invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="0") 48 49%def op_invoke_super(): 50% invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="1") 51 52%def op_invoke_super_range(): 53% invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="1") 54 55%def op_invoke_polymorphic(): 56 EXPORT_PC 57 // No need to fetch the target method. 58 // Load the first argument (the 'this' pointer). 59 FETCH r1, 2 60 and r1, r1, #0xf 61 GET_VREG r1, r1 62 cmp r1, #0 63 beq common_errNullObject // bail if null 64 b NterpCommonInvokePolymorphic 65 66%def op_invoke_polymorphic_range(): 67 EXPORT_PC 68 // No need to fetch the target method. 69 // Load the first argument (the 'this' pointer). 70 FETCH r1, 2 71 GET_VREG r1, r1 72 cmp r1, #0 73 beq common_errNullObject // bail if null 74 b NterpCommonInvokePolymorphicRange 75 76%def invoke_interface(range=""): 77% slow_path = add_slow_path(op_invoke_interface_slow_path) 78 EXPORT_PC 79 // Fast-path which gets the method from thread-local cache. 80% fetch_from_thread_cache("r4", miss_label=slow_path) 81.L${opcode}_resume: 82 // First argument is the 'this' pointer. 83 FETCH r1, 2 84 .if !$range 85 and r1, r1, #0xf 86 .endif 87 GET_VREG r1, r1 88 // Note: if r1 is null, this will be handled by our SIGSEGV handler. 89 ldr r2, [r1, #MIRROR_OBJECT_CLASS_OFFSET] 90 UNPOISON_HEAP_REF r2 91 // Test the first two bits of the fetched ArtMethod: 92 // - If the first bit is set, this is a method on j.l.Object 93 // - If the second bit is set, this is a default method. 94 tst r4, #3 95 bne 2f 96 ldrh r3, [r4, #ART_METHOD_IMT_INDEX_OFFSET] 971: 98 ldr r2, [r2, #MIRROR_CLASS_IMT_PTR_OFFSET_32] 99 ldr r0, [r2, r3, lsl #2] 100 .if $range 101 b NterpCommonInvokeInterfaceRange 102 .else 103 b NterpCommonInvokeInterface 104 .endif 1052: 106 tst r4, #1 107 bne 3f 108 and r4, r4, #-4 109 ldrh r3, [r4, #ART_METHOD_METHOD_INDEX_OFFSET] 110 and r3, r3, #ART_METHOD_IMT_MASK 111 b 1b 1123: 113 lsr r4, r4, #16 114 add r2, r2, #MIRROR_CLASS_VTABLE_OFFSET_32 115 ldr r0, [r2, r4, lsl #2] 116 .if $range 117 b NterpCommonInvokeInstanceRange 118 .else 119 b NterpCommonInvokeInstance 120 .endif 121 122%def op_invoke_interface_slow_path(): 123 mov r0, rSELF 124 ldr r1, [sp] 125 mov r2, rPC 126 bl nterp_get_method 127 mov r4, r0 128 b .L${opcode}_resume 129 130%def op_invoke_interface(): 131% invoke_interface(range="0") 132 133%def op_invoke_interface_range(): 134% invoke_interface(range="1") 135 136%def invoke_static(helper=""): 137 EXPORT_PC 138 // Fast-path which gets the method from thread-local cache. 139% fetch_from_thread_cache("r0", miss_label="1f") 140 b $helper 1411: 142 mov r0, rSELF 143 ldr r1, [sp] 144 mov r2, rPC 145 bl nterp_get_method 146 b $helper 147 148%def op_invoke_static(): 149% invoke_static(helper="NterpCommonInvokeStatic") 150 151%def op_invoke_static_range(): 152% invoke_static(helper="NterpCommonInvokeStaticRange") 153 154%def invoke_virtual(helper="", range=""): 155 EXPORT_PC 156 // Fast-path which gets the vtable offset from thread-local cache. 157% fetch_from_thread_cache("r2", miss_label="2f") 1581: 159 FETCH r1, 2 160 .if !$range 161 and r1, r1, #0xf 162 .endif 163 GET_VREG r1, r1 164 // Note: if r1 is null, this will be handled by our SIGSEGV handler. 165 ldr r0, [r1, #MIRROR_OBJECT_CLASS_OFFSET] 166 UNPOISON_HEAP_REF r0 167 add r0, r0, #MIRROR_CLASS_VTABLE_OFFSET_32 168 ldr r0, [r0, r2, lsl #2] 169 b $helper 1702: 171 mov r0, rSELF 172 ldr r1, [sp] 173 mov r2, rPC 174 bl nterp_get_method 175 mov r2, r0 176 b 1b 177 178%def op_invoke_virtual(): 179% invoke_virtual(helper="NterpCommonInvokeInstance", range="0") 180 181%def op_invoke_virtual_range(): 182% invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1") 183