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