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), %edi // 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), %edi // 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("%rdi", 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), %r11d // arguments 21*795d594fSAndroid Build Coastguard Worker .if !$range 22*795d594fSAndroid Build Coastguard Worker andq $$0xf, %r11 23*795d594fSAndroid Build Coastguard Worker .endif 24*795d594fSAndroid Build Coastguard Worker movl (rFP, %r11, 4), %esi 25*795d594fSAndroid Build Coastguard Worker // NullPointerException check. 26*795d594fSAndroid Build Coastguard Worker movl (%esi), %eax 27*795d594fSAndroid Build Coastguard Worker jmp $helper 28*795d594fSAndroid Build Coastguard Worker2: 29*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rdi 30*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %rsi 31*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 32*795d594fSAndroid Build Coastguard Worker call nterp_get_method 33*795d594fSAndroid Build Coastguard Worker movq %rax, %rdi 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 andq $$-2, %rdi // 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), %r11d // arguments 58*795d594fSAndroid Build Coastguard Worker andq $$0xf, %r11 59*795d594fSAndroid Build Coastguard Worker movl (rFP, %r11, 4), %esi 60*795d594fSAndroid Build Coastguard Worker // NullPointerException check. 61*795d594fSAndroid Build Coastguard Worker movl (%esi), %eax 62*795d594fSAndroid Build Coastguard Worker jmp NterpCommonInvokePolymorphic 63*795d594fSAndroid Build Coastguard Worker 64*795d594fSAndroid Build Coastguard Worker%def op_invoke_polymorphic_range(): 65*795d594fSAndroid Build Coastguard Worker EXPORT_PC 66*795d594fSAndroid Build Coastguard Worker // No need to fetch the target method. 67*795d594fSAndroid Build Coastguard Worker // Load the first argument (the 'this' pointer). 68*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r11d // arguments 69*795d594fSAndroid Build Coastguard Worker movl (rFP, %r11, 4), %esi 70*795d594fSAndroid Build Coastguard Worker // NullPointerException check. 71*795d594fSAndroid Build Coastguard Worker movl (%esi), %eax 72*795d594fSAndroid Build Coastguard Worker jmp NterpCommonInvokePolymorphicRange 73*795d594fSAndroid Build Coastguard Worker 74*795d594fSAndroid Build Coastguard Worker%def invoke_interface(helper="", range=""): 75*795d594fSAndroid Build Coastguard Worker% slow_path = add_slow_path(op_invoke_interface_slow_path) 76*795d594fSAndroid Build Coastguard Worker EXPORT_PC 77*795d594fSAndroid Build Coastguard Worker // Fast-path which gets the interface method from thread-local cache. 78*795d594fSAndroid Build Coastguard Worker% fetch_from_thread_cache("%rax", miss_label=slow_path) 79*795d594fSAndroid Build Coastguard Worker.L${opcode}_resume: 80*795d594fSAndroid Build Coastguard Worker // First argument is the 'this' pointer. 81*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r11d // arguments 82*795d594fSAndroid Build Coastguard Worker .if !$range 83*795d594fSAndroid Build Coastguard Worker andq $$0xf, %r11 84*795d594fSAndroid Build Coastguard Worker .endif 85*795d594fSAndroid Build Coastguard Worker movl (rFP, %r11, 4), %esi 86*795d594fSAndroid Build Coastguard Worker movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx 87*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF edx 88*795d594fSAndroid Build Coastguard Worker // Test the first two bits of the fetched ArtMethod: 89*795d594fSAndroid Build Coastguard Worker // - If the first bit is set, this is a method on j.l.Object 90*795d594fSAndroid Build Coastguard Worker // - If the second bit is set, this is a default method. 91*795d594fSAndroid Build Coastguard Worker testl $$3, %eax 92*795d594fSAndroid Build Coastguard Worker jne 2f 93*795d594fSAndroid Build Coastguard Worker movzw ART_METHOD_IMT_INDEX_OFFSET(%rax), %ecx 94*795d594fSAndroid Build Coastguard Worker1: 95*795d594fSAndroid Build Coastguard Worker movq MIRROR_CLASS_IMT_PTR_OFFSET_64(%edx), %rdx 96*795d594fSAndroid Build Coastguard Worker movq (%rdx, %rcx, 8), %rdi 97*795d594fSAndroid Build Coastguard Worker jmp $helper 98*795d594fSAndroid Build Coastguard Worker2: 99*795d594fSAndroid Build Coastguard Worker testl $$1, %eax 100*795d594fSAndroid Build Coastguard Worker .if $range 101*795d594fSAndroid Build Coastguard Worker jne NterpHandleInvokeInterfaceOnObjectMethodRange 102*795d594fSAndroid Build Coastguard Worker .else 103*795d594fSAndroid Build Coastguard Worker jne NterpHandleInvokeInterfaceOnObjectMethod 104*795d594fSAndroid Build Coastguard Worker .endif 105*795d594fSAndroid Build Coastguard Worker // Default method 106*795d594fSAndroid Build Coastguard Worker andq $$-4, %rax 107*795d594fSAndroid Build Coastguard Worker movzw ART_METHOD_METHOD_INDEX_OFFSET(%rax), %ecx 108*795d594fSAndroid Build Coastguard Worker andl $$ART_METHOD_IMT_MASK, %ecx 109*795d594fSAndroid Build Coastguard Worker jmp 1b 110*795d594fSAndroid Build Coastguard Worker 111*795d594fSAndroid Build Coastguard Worker%def op_invoke_interface_slow_path(): 112*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rdi 113*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %rsi 114*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 115*795d594fSAndroid Build Coastguard Worker call nterp_get_method 116*795d594fSAndroid Build Coastguard Worker jmp .L${opcode}_resume 117*795d594fSAndroid Build Coastguard Worker 118*795d594fSAndroid Build Coastguard Worker%def op_invoke_interface(): 119*795d594fSAndroid Build Coastguard Worker% invoke_interface(helper="NterpCommonInvokeInterface", range="0") 120*795d594fSAndroid Build Coastguard Worker 121*795d594fSAndroid Build Coastguard Worker%def op_invoke_interface_range(): 122*795d594fSAndroid Build Coastguard Worker% invoke_interface(helper="NterpCommonInvokeInterfaceRange", range="1") 123*795d594fSAndroid Build Coastguard Worker 124*795d594fSAndroid Build Coastguard Worker%def invoke_static(helper=""): 125*795d594fSAndroid Build Coastguard Worker EXPORT_PC 126*795d594fSAndroid Build Coastguard Worker // Fast-path which gets the method from thread-local cache. 127*795d594fSAndroid Build Coastguard Worker% fetch_from_thread_cache("%rdi", miss_label="1f") 128*795d594fSAndroid Build Coastguard Worker jmp $helper 129*795d594fSAndroid Build Coastguard Worker1: 130*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rdi 131*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %rsi 132*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 133*795d594fSAndroid Build Coastguard Worker call nterp_get_method 134*795d594fSAndroid Build Coastguard Worker movq %rax, %rdi 135*795d594fSAndroid Build Coastguard Worker jmp $helper 136*795d594fSAndroid Build Coastguard Worker 137*795d594fSAndroid Build Coastguard Worker%def op_invoke_static(): 138*795d594fSAndroid Build Coastguard Worker% invoke_static(helper="NterpCommonInvokeStatic") 139*795d594fSAndroid Build Coastguard Worker 140*795d594fSAndroid Build Coastguard Worker%def op_invoke_static_range(): 141*795d594fSAndroid Build Coastguard Worker% invoke_static(helper="NterpCommonInvokeStaticRange") 142*795d594fSAndroid Build Coastguard Worker 143*795d594fSAndroid Build Coastguard Worker%def op_invoke_super(): 144*795d594fSAndroid Build Coastguard Worker% invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="1") 145*795d594fSAndroid Build Coastguard Worker 146*795d594fSAndroid Build Coastguard Worker%def op_invoke_super_range(): 147*795d594fSAndroid Build Coastguard Worker% invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="1") 148*795d594fSAndroid Build Coastguard Worker 149*795d594fSAndroid Build Coastguard Worker%def invoke_virtual(helper="", range=""): 150*795d594fSAndroid Build Coastguard Worker EXPORT_PC 151*795d594fSAndroid Build Coastguard Worker // Fast-path which gets the method from thread-local cache. 152*795d594fSAndroid Build Coastguard Worker% fetch_from_thread_cache("%rdi", miss_label="2f") 153*795d594fSAndroid Build Coastguard Worker1: 154*795d594fSAndroid Build Coastguard Worker // First argument is the 'this' pointer. 155*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r11d // arguments 156*795d594fSAndroid Build Coastguard Worker .if !$range 157*795d594fSAndroid Build Coastguard Worker andq $$0xf, %r11 158*795d594fSAndroid Build Coastguard Worker .endif 159*795d594fSAndroid Build Coastguard Worker movl (rFP, %r11, 4), %esi 160*795d594fSAndroid Build Coastguard Worker // Note: if esi is null, this will be handled by our SIGSEGV handler. 161*795d594fSAndroid Build Coastguard Worker movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx 162*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF edx 163*795d594fSAndroid Build Coastguard Worker movq MIRROR_CLASS_VTABLE_OFFSET_64(%edx, %edi, 8), %rdi 164*795d594fSAndroid Build Coastguard Worker jmp $helper 165*795d594fSAndroid Build Coastguard Worker2: 166*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rdi 167*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %rsi 168*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 169*795d594fSAndroid Build Coastguard Worker call nterp_get_method 170*795d594fSAndroid Build Coastguard Worker movl %eax, %edi 171*795d594fSAndroid Build Coastguard Worker jmp 1b 172*795d594fSAndroid Build Coastguard Worker 173*795d594fSAndroid Build Coastguard Worker%def op_invoke_virtual(): 174*795d594fSAndroid Build Coastguard Worker% invoke_virtual(helper="NterpCommonInvokeInstance", range="0") 175*795d594fSAndroid Build Coastguard Worker 176*795d594fSAndroid Build Coastguard Worker%def op_invoke_virtual_range(): 177*795d594fSAndroid Build Coastguard Worker% invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1") 178