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 // Test the first two bits of the fetched ArtMethod: 90 // - If the first bit is set, this is a method on j.l.Object 91 // - If the second bit is set, this is a default method. 92 testl $$3, %eax 93 jne 2f 94 // Save interface method as hidden argument. 95 movd %eax, %xmm7 96 movzw ART_METHOD_IMT_INDEX_OFFSET(%eax), %eax 971: 98 movl MIRROR_CLASS_IMT_PTR_OFFSET_32(%edx), %edx 99 movl (%edx, %eax, 4), %eax 100 jmp $helper 1012: 102 testl $$1, %eax 103 .if $range 104 jne NterpHandleInvokeInterfaceOnObjectMethodRange 105 .else 106 jne NterpHandleInvokeInterfaceOnObjectMethod 107 .endif 108 // Default method 109 andl $$-4, %eax 110 // Save interface method as hidden argument. 111 movd %eax, %xmm7 112 movzw ART_METHOD_METHOD_INDEX_OFFSET(%eax), %eax 113 andl $$ART_METHOD_IMT_MASK, %eax 114 jmp 1b 115 116%def op_invoke_interface_slow_path(): 117 movl rSELF:THREAD_SELF_OFFSET, ARG0 118 movl 0(%esp), ARG1 119 movl rPC, ARG2 120 call nterp_get_method 121 jmp .L${opcode}_resume 122 123%def op_invoke_interface(): 124% invoke_interface(helper="NterpCommonInvokeInterface", range="0") 125 126%def op_invoke_interface_range(): 127% invoke_interface(helper="NterpCommonInvokeInterfaceRange", range="1") 128 129%def invoke_static(helper=""): 130 EXPORT_PC 131 // Fast-path which gets the method from thread-local cache. 132% fetch_from_thread_cache("%eax", miss_label="1f") 133 jmp $helper 1341: 135 movl rSELF:THREAD_SELF_OFFSET, ARG0 136 movl 0(%esp), ARG1 137 movl rPC, ARG2 138 call nterp_get_method 139 jmp $helper 140 141%def op_invoke_static(): 142% invoke_static(helper="NterpCommonInvokeStatic") 143 144%def op_invoke_static_range(): 145% invoke_static(helper="NterpCommonInvokeStaticRange") 146 147%def op_invoke_super(): 148% invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="1") 149 150%def op_invoke_super_range(): 151% invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="1") 152 153%def invoke_virtual(helper="", range=""): 154 EXPORT_PC 155 // Fast-path which gets the method from thread-local cache. 156% fetch_from_thread_cache("%eax", miss_label="2f") 1571: 158 // First argument is the 'this' pointer. 159 movzwl 4(rPC), %ecx // arguments 160 .if !$range 161 andl $$0xf, %ecx 162 .endif 163 movl (rFP, %ecx, 4), %ecx 164 // Note: if ecx is null, this will be handled by our SIGSEGV handler. 165 movl MIRROR_OBJECT_CLASS_OFFSET(%ecx), %edx 166 movl MIRROR_CLASS_VTABLE_OFFSET_32(%edx, %eax, 4), %eax 167 jmp $helper 1682: 169 movl rSELF:THREAD_SELF_OFFSET, ARG0 170 movl 0(%esp), ARG1 171 movl rPC, ARG2 172 call nterp_get_method 173 jmp 1b 174 175%def op_invoke_virtual(): 176% invoke_virtual(helper="NterpCommonInvokeInstance", range="0") 177 178%def op_invoke_virtual_range(): 179% invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1") 180