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, 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_helper(lambda: 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, ${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 // Test the first two bits of the fetched ArtMethod: 91 // - If the first bit is set, this is a method on j.l.Object 92 // - If the second bit is set, this is a default method. 93 tst r4, #3 94 bne 2f 95 ldrh r3, [r4, #ART_METHOD_IMT_INDEX_OFFSET] 961: 97 ldr r2, [r2, #MIRROR_CLASS_IMT_PTR_OFFSET_32] 98 ldr r0, [r2, r3, lsl #2] 99 .if $range 100 b NterpCommonInvokeInterfaceRange 101 .else 102 b NterpCommonInvokeInterface 103 .endif 1042: 105 tst r4, #1 106 bne 3f 107 and r4, r4, #-4 108 ldrh r3, [r4, #ART_METHOD_METHOD_INDEX_OFFSET] 109 and r3, r3, #ART_METHOD_IMT_MASK 110 b 1b 1113: 112 lsr r4, r4, #16 113 add r2, r2, #MIRROR_CLASS_VTABLE_OFFSET_32 114 ldr r0, [r2, r4, lsl #2] 115 .if $range 116 b NterpCommonInvokeInstanceRange 117 .else 118 b NterpCommonInvokeInstance 119 .endif 120 121%def op_invoke_interface_slow_path(): 122 mov r0, rSELF 123 ldr r1, [sp] 124 mov r2, rPC 125 bl nterp_get_method 126 mov r4, r0 127 b .L${opcode}_resume 128 129%def op_invoke_interface(): 130% invoke_interface(range="0") 131 132%def op_invoke_interface_range(): 133% invoke_interface(range="1") 134 135%def invoke_static(helper=""): 136 EXPORT_PC 137 // Fast-path which gets the method from thread-local cache. 138 FETCH_FROM_THREAD_CACHE r0, 1f 139 b $helper 1401: 141 mov r0, rSELF 142 ldr r1, [sp] 143 mov r2, rPC 144 bl nterp_get_method 145 b $helper 146 147%def op_invoke_static(): 148% invoke_static(helper="NterpCommonInvokeStatic") 149 150%def op_invoke_static_range(): 151% invoke_static(helper="NterpCommonInvokeStaticRange") 152 153%def invoke_virtual(helper="", range=""): 154 EXPORT_PC 155 // Fast-path which gets the vtable offset from thread-local cache. 156 FETCH_FROM_THREAD_CACHE r2, 2f 1571: 158 FETCH r1, 2 159 .if !$range 160 and r1, r1, #0xf 161 .endif 162 GET_VREG r1, r1 163 // Note: if r1 is null, this will be handled by our SIGSEGV handler. 164 ldr r0, [r1, #MIRROR_OBJECT_CLASS_OFFSET] 165 add r0, r0, #MIRROR_CLASS_VTABLE_OFFSET_32 166 ldr r0, [r0, r2, lsl #2] 167 b $helper 1682: 169 mov r0, rSELF 170 ldr r1, [sp] 171 mov r2, rPC 172 bl nterp_get_method 173 mov r2, r0 174 b 1b 175 176%def op_invoke_virtual(): 177% invoke_virtual(helper="NterpCommonInvokeInstance", range="0") 178 179%def op_invoke_virtual_range(): 180% invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1") 181