1%def invoke(helper="NterpUnimplemented"): 2 call SYMBOL($helper) 3 4%def op_invoke_custom(): 5 EXPORT_PC 6 movzwl 2(rPC), %eax // 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), %eax // 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("%eax", miss_label="2f") 181: 19 // Load the first argument (the 'this' pointer). 20 movzwl 4(rPC), %ecx // arguments 21 .if !$range 22 andl $$0xf, %ecx 23 .endif 24 movl (rFP, %ecx, 4), %ecx 25 // NullPointerException check. 26 testl %ecx, %ecx 27 je common_errNullObject 28 jmp $helper 292: 30 movl rSELF:THREAD_SELF_OFFSET, ARG0 31 movl 0(%esp), ARG1 32 movl rPC, ARG2 33 call nterp_get_method 34 .if $is_super 35 jmp 1b 36 .else 37 testl MACRO_LITERAL(1), %eax 38 je 1b 39 andl $$-2, %eax // 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), %ecx // arguments 58 andl $$0xf, %ecx 59 movl (rFP, %ecx, 4), %ecx 60 // NullPointerException check. 61 testl %ecx, %ecx 62 je common_errNullObject 63 jmp NterpCommonInvokePolymorphic 64 65%def op_invoke_polymorphic_range(): 66 EXPORT_PC 67 // No need to fetch the target method. 68 // Load the first argument (the 'this' pointer). 69 movzwl 4(rPC), %ecx // arguments 70 movl (rFP, %ecx, 4), %ecx 71 // NullPointerException check. 72 testl %ecx, %ecx 73 je common_errNullObject 74 jmp NterpCommonInvokePolymorphicRange 75 76%def invoke_interface(helper="", range=""): 77% slow_path = add_slow_path(op_invoke_interface_slow_path) 78 EXPORT_PC 79 // Fast-path which gets the interface method from thread-local cache. 80% fetch_from_thread_cache("%eax", miss_label=slow_path) 81.L${opcode}_resume: 82 // First argument is the 'this' pointer. 83 movzwl 4(rPC), %ecx // arguments 84 .if !$range 85 andl $$0xf, %ecx 86 .endif 87 movl (rFP, %ecx, 4), %ecx 88 movl MIRROR_OBJECT_CLASS_OFFSET(%ecx), %edx 89 UNPOISON_HEAP_REF edx 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 testl $$3, %eax 94 jne 2f 95 // Save interface method as hidden argument. 96 movd %eax, %xmm7 97 movzw ART_METHOD_IMT_INDEX_OFFSET(%eax), %eax 981: 99 movl MIRROR_CLASS_IMT_PTR_OFFSET_32(%edx), %edx 100 movl (%edx, %eax, 4), %eax 101 jmp $helper 1022: 103 testl $$1, %eax 104 .if $range 105 jne NterpHandleInvokeInterfaceOnObjectMethodRange 106 .else 107 jne NterpHandleInvokeInterfaceOnObjectMethod 108 .endif 109 // Default method 110 andl $$-4, %eax 111 // Save interface method as hidden argument. 112 movd %eax, %xmm7 113 movzw ART_METHOD_METHOD_INDEX_OFFSET(%eax), %eax 114 andl $$ART_METHOD_IMT_MASK, %eax 115 jmp 1b 116 117%def op_invoke_interface_slow_path(): 118 movl rSELF:THREAD_SELF_OFFSET, ARG0 119 movl 0(%esp), ARG1 120 movl rPC, ARG2 121 call nterp_get_method 122 jmp .L${opcode}_resume 123 124%def op_invoke_interface(): 125% invoke_interface(helper="NterpCommonInvokeInterface", range="0") 126 127%def op_invoke_interface_range(): 128% invoke_interface(helper="NterpCommonInvokeInterfaceRange", range="1") 129 130%def invoke_static(helper=""): 131 EXPORT_PC 132 // Fast-path which gets the method from thread-local cache. 133% fetch_from_thread_cache("%eax", miss_label="1f") 134 jmp $helper 1351: 136 movl rSELF:THREAD_SELF_OFFSET, ARG0 137 movl 0(%esp), ARG1 138 movl rPC, ARG2 139 call nterp_get_method 140 jmp $helper 141 142%def op_invoke_static(): 143% invoke_static(helper="NterpCommonInvokeStatic") 144 145%def op_invoke_static_range(): 146% invoke_static(helper="NterpCommonInvokeStaticRange") 147 148%def op_invoke_super(): 149% invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="1") 150 151%def op_invoke_super_range(): 152% invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="1") 153 154%def invoke_virtual(helper="", range=""): 155 EXPORT_PC 156 // Fast-path which gets the method from thread-local cache. 157% fetch_from_thread_cache("%eax", miss_label="2f") 1581: 159 // First argument is the 'this' pointer. 160 movzwl 4(rPC), %ecx // arguments 161 .if !$range 162 andl $$0xf, %ecx 163 .endif 164 movl (rFP, %ecx, 4), %ecx 165 // Note: if ecx is null, this will be handled by our SIGSEGV handler. 166 movl MIRROR_OBJECT_CLASS_OFFSET(%ecx), %edx 167 UNPOISON_HEAP_REF edx 168 movl MIRROR_CLASS_VTABLE_OFFSET_32(%edx, %eax, 4), %eax 169 jmp $helper 1702: 171 movl rSELF:THREAD_SELF_OFFSET, ARG0 172 movl 0(%esp), ARG1 173 movl rPC, ARG2 174 call nterp_get_method 175 jmp 1b 176 177%def op_invoke_virtual(): 178% invoke_virtual(helper="NterpCommonInvokeInstance", range="0") 179 180%def op_invoke_virtual_range(): 181% invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1") 182