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