| %def invoke(helper="NterpUnimplemented"): |
| call SYMBOL($helper) |
| |
| %def op_invoke_custom(): |
| EXPORT_PC |
| movzwl 2(rPC), %edi // call_site index, first argument of runtime call. |
| jmp NterpCommonInvokeCustom |
| |
| %def op_invoke_custom_range(): |
| EXPORT_PC |
| movzwl 2(rPC), %edi // call_site index, first argument of runtime call. |
| jmp NterpCommonInvokeCustomRange |
| |
| %def invoke_direct_or_super(helper="", range=""): |
| EXPORT_PC |
| // Fast-path which gets the method from thread-local cache. |
| FETCH_FROM_THREAD_CACHE %rdi, 2f |
| 1: |
| // Load the first argument (the 'this' pointer). |
| movzwl 4(rPC), %r11d // arguments |
| .if !$range |
| andq $$0xf, %r11 |
| .endif |
| movl (rFP, %r11, 4), %esi |
| // NullPointerException check. |
| movl (%esi), %eax |
| jmp $helper |
| 2: |
| movq rSELF:THREAD_SELF_OFFSET, %rdi |
| movq 0(%rsp), %rsi |
| movq rPC, %rdx |
| call nterp_get_method |
| movq %rax, %rdi |
| testl MACRO_LITERAL(1), %eax |
| je 1b |
| andq $$-2, %rdi // Remove the extra bit that marks it's a String.<init> method. |
| .if $range |
| jmp NterpHandleStringInitRange |
| .else |
| jmp NterpHandleStringInit |
| .endif |
| |
| %def op_invoke_direct(): |
| % invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0") |
| |
| %def op_invoke_direct_range(): |
| % invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1") |
| |
| %def op_invoke_polymorphic(): |
| EXPORT_PC |
| // No need to fetch the target method. |
| // Load the first argument (the 'this' pointer). |
| movzwl 4(rPC), %r11d // arguments |
| andq $$0xf, %r11 |
| movl (rFP, %r11, 4), %esi |
| // NullPointerException check. |
| movl (%esi), %eax |
| jmp NterpCommonInvokePolymorphic |
| |
| %def op_invoke_polymorphic_range(): |
| EXPORT_PC |
| // No need to fetch the target method. |
| // Load the first argument (the 'this' pointer). |
| movzwl 4(rPC), %r11d // arguments |
| movl (rFP, %r11, 4), %esi |
| // NullPointerException check. |
| movl (%esi), %eax |
| jmp NterpCommonInvokePolymorphicRange |
| |
| %def invoke_interface(helper="", range=""): |
| EXPORT_PC |
| // Fast-path which gets the method from thread-local cache. |
| FETCH_FROM_THREAD_CACHE %rax, 2f |
| 1: |
| // First argument is the 'this' pointer. |
| movzwl 4(rPC), %r11d // arguments |
| .if !$range |
| andq $$0xf, %r11 |
| .endif |
| movl (rFP, %r11, 4), %esi |
| movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx |
| movq MIRROR_CLASS_IMT_PTR_OFFSET_64(%edx), %rdx |
| movq (%rdx, %rax, 8), %rdi |
| jmp $helper |
| 2: |
| movq rSELF:THREAD_SELF_OFFSET, %rdi |
| movq 0(%rsp), %rsi |
| movq rPC, %rdx |
| call nterp_get_method |
| jmp 1b |
| |
| %def op_invoke_interface(): |
| % invoke_interface(helper="NterpCommonInvokeInterface", range="0") |
| |
| %def op_invoke_interface_range(): |
| % invoke_interface(helper="NterpCommonInvokeInterfaceRange", range="1") |
| |
| %def invoke_static(helper=""): |
| EXPORT_PC |
| // Fast-path which gets the method from thread-local cache. |
| FETCH_FROM_THREAD_CACHE %rdi, 1f |
| jmp $helper |
| 1: |
| movq rSELF:THREAD_SELF_OFFSET, %rdi |
| movq 0(%rsp), %rsi |
| movq rPC, %rdx |
| call nterp_get_method |
| movq %rax, %rdi |
| jmp $helper |
| |
| %def op_invoke_static(): |
| % invoke_static(helper="NterpCommonInvokeStatic") |
| |
| %def op_invoke_static_range(): |
| % invoke_static(helper="NterpCommonInvokeStaticRange") |
| |
| %def op_invoke_super(): |
| % invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0") |
| |
| %def op_invoke_super_range(): |
| % invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1") |
| |
| %def invoke_virtual(helper="", range=""): |
| EXPORT_PC |
| // Fast-path which gets the method from thread-local cache. |
| FETCH_FROM_THREAD_CACHE %rdi, 2f |
| 1: |
| // First argument is the 'this' pointer. |
| movzwl 4(rPC), %r11d // arguments |
| .if !$range |
| andq $$0xf, %r11 |
| .endif |
| movl (rFP, %r11, 4), %esi |
| // Note: if esi is null, this will be handled by our SIGSEGV handler. |
| movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx |
| movq MIRROR_CLASS_VTABLE_OFFSET_64(%edx, %edi, 8), %rdi |
| jmp $helper |
| 2: |
| movq rSELF:THREAD_SELF_OFFSET, %rdi |
| movq 0(%rsp), %rsi |
| movq rPC, %rdx |
| call nterp_get_method |
| movl %eax, %edi |
| jmp 1b |
| |
| %def op_invoke_virtual(): |
| % invoke_virtual(helper="NterpCommonInvokeInstance", range="0") |
| |
| %def op_invoke_virtual_quick(): |
| EXPORT_PC |
| movzwl 2(rPC), %eax // offset |
| // First argument is the 'this' pointer. |
| movzwl 4(rPC), %r11d // arguments |
| andq $$0xf, %r11 |
| movl (rFP, %r11, 4), %esi |
| // Note: if esi is null, this will be handled by our SIGSEGV handler. |
| movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx |
| movq MIRROR_CLASS_VTABLE_OFFSET_64(%edx, %eax, 8), %rdi |
| jmp NterpCommonInvokeInstance |
| |
| %def op_invoke_virtual_range(): |
| % invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1") |
| |
| %def op_invoke_virtual_range_quick(): |
| EXPORT_PC |
| movzwl 2(rPC), %eax // offset |
| // First argument is the 'this' pointer. |
| movzwl 4(rPC), %r11d // arguments |
| movl (rFP, %r11, 4), %esi |
| // Note: if esi is null, this will be handled by our SIGSEGV handler. |
| movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx |
| movq MIRROR_CLASS_VTABLE_OFFSET_64(%edx, %eax, 8), %rdi |
| jmp NterpCommonInvokeInstanceRange |