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