diff options
author | 2021-01-14 23:40:53 +0000 | |
---|---|---|
committer | 2021-01-15 00:36:13 +0000 | |
commit | f1d06474baa2f7c00761db39099b89ddab71bbe4 (patch) | |
tree | 9924ce87e34d1058a0d12e963e3a94fbd3d1539d | |
parent | 4c176b9de6c430422395017910633bcb001b2e84 (diff) |
Revert "Improve invokeinterface for nterp."
This reverts commit c0d392be9172c4c60b3e81b0123489ec3036c401.
Bug: 177554973
Reason for revert: Fix crash when enabling 'Select to Speak'
Change-Id: If2865cc1dfc11e6bd27ed533da10f53521e3e613
-rw-r--r-- | runtime/art_method-inl.h | 8 | ||||
-rw-r--r-- | runtime/art_method.h | 3 | ||||
-rw-r--r-- | runtime/image.cc | 3 | ||||
-rw-r--r-- | runtime/imtable-inl.h | 6 | ||||
-rw-r--r-- | runtime/imtable.h | 5 | ||||
-rw-r--r-- | runtime/interpreter/mterp/arm64ng/invoke.S | 38 | ||||
-rw-r--r-- | runtime/interpreter/mterp/arm64ng/main.S | 35 | ||||
-rw-r--r-- | runtime/interpreter/mterp/armng/invoke.S | 42 | ||||
-rw-r--r-- | runtime/interpreter/mterp/armng/main.S | 40 | ||||
-rw-r--r-- | runtime/interpreter/mterp/nterp.cc | 19 | ||||
-rw-r--r-- | runtime/interpreter/mterp/x86_64ng/invoke.S | 39 | ||||
-rw-r--r-- | runtime/interpreter/mterp/x86_64ng/main.S | 49 | ||||
-rw-r--r-- | tools/cpp-define-generator/art_method.def | 3 |
13 files changed, 135 insertions, 155 deletions
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h index b2a27f36d2..291438284f 100644 --- a/runtime/art_method-inl.h +++ b/runtime/art_method-inl.h @@ -423,8 +423,10 @@ inline uint16_t ArtMethod::GetCounter() { } inline uint32_t ArtMethod::GetImtIndex() { - if (LIKELY(IsAbstract())) { - return imt_index_; + if (LIKELY(IsAbstract() && imt_index_ != 0)) { + uint16_t imt_index = ~imt_index_; + DCHECK_EQ(imt_index, ImTable::GetImtIndex(this)) << PrettyMethod(); + return imt_index; } else { return ImTable::GetImtIndex(this); } @@ -432,7 +434,7 @@ inline uint32_t ArtMethod::GetImtIndex() { inline void ArtMethod::CalculateAndSetImtIndex() { DCHECK(IsAbstract()) << PrettyMethod(); - imt_index_ = ImTable::GetImtIndex(this); + imt_index_ = ~ImTable::GetImtIndex(this); } } // namespace art diff --git a/runtime/art_method.h b/runtime/art_method.h index 31b81d40df..b21a18ddba 100644 --- a/runtime/art_method.h +++ b/runtime/art_method.h @@ -792,7 +792,8 @@ class ArtMethod final { // Non-abstract methods: The hotness we measure for this method. Not atomic, // as we allow missing increments: if the method is hot, we will see it eventually. uint16_t hotness_count_; - // Abstract methods: IMT index. + // Abstract methods: IMT index (bitwise negated) or zero if it was not cached. + // The negation is needed to distinguish zero index and missing cached entry. uint16_t imt_index_; }; diff --git a/runtime/image.cc b/runtime/image.cc index 94174485d5..6f88481f89 100644 --- a/runtime/image.cc +++ b/runtime/image.cc @@ -29,8 +29,7 @@ namespace art { const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' }; -// Last change: IMT index for default methods. -const uint8_t ImageHeader::kImageVersion[] = { '0', '8', '9', '\0' }; +const uint8_t ImageHeader::kImageVersion[] = { '0', '8', '8', '\0' }; // Remove DexCache arrays. ImageHeader::ImageHeader(uint32_t image_reservation_size, uint32_t component_count, diff --git a/runtime/imtable-inl.h b/runtime/imtable-inl.h index 71ece99a21..21e3eb1f23 100644 --- a/runtime/imtable-inl.h +++ b/runtime/imtable-inl.h @@ -83,12 +83,6 @@ inline void ImTable::GetImtHashComponents(ArtMethod* method, } inline uint32_t ImTable::GetImtIndex(ArtMethod* method) { - if (!method->IsAbstract()) { - // For default methods, where we cannot store the imt_index, we use the - // method_index instead. We mask it with the closest power of two to - // simplify the interpreter. - return method->GetMethodIndex() & (ImTable::kSizeTruncToPowerOfTwo - 1); - } uint32_t class_hash, name_hash, signature_hash; GetImtHashComponents(method, &class_hash, &name_hash, &signature_hash); diff --git a/runtime/imtable.h b/runtime/imtable.h index df10cda816..5db3d07ec2 100644 --- a/runtime/imtable.h +++ b/runtime/imtable.h @@ -17,7 +17,6 @@ #ifndef ART_RUNTIME_IMTABLE_H_ #define ART_RUNTIME_IMTABLE_H_ -#include "base/bit_utils.h" #include "base/casts.h" #include "base/enums.h" #include "base/locks.h" @@ -35,10 +34,6 @@ class ImTable { // (non-marker) interfaces. // When this value changes, old images become incompatible, so image file version must change too. static constexpr size_t kSize = 43; - // Default methods cannot store the imt_index, so instead we make its IMT index depend on the - // method_index and mask it with the closest power of 2 of kSize - 1. This - // is to simplify fetching it in the interpreter. - static constexpr size_t kSizeTruncToPowerOfTwo = TruncToPowerOfTwo(kSize); uint8_t* AddressOfElement(size_t index, PointerSize pointer_size) { return reinterpret_cast<uint8_t*>(this) + OffsetOfElement(index, pointer_size); diff --git a/runtime/interpreter/mterp/arm64ng/invoke.S b/runtime/interpreter/mterp/arm64ng/invoke.S index ac45a35e6c..4a7ec49582 100644 --- a/runtime/interpreter/mterp/arm64ng/invoke.S +++ b/runtime/interpreter/mterp/arm64ng/invoke.S @@ -72,7 +72,7 @@ %def invoke_interface(range=""): EXPORT_PC // Fast-path which gets the method from thread-local cache. - FETCH_FROM_THREAD_CACHE x26, 5f + FETCH_FROM_THREAD_CACHE x0, 2f 1: // First argument is the 'this' pointer. FETCH w1, 2 @@ -82,42 +82,26 @@ GET_VREG w1, w1 // Note: if w1 is null, this will be handled by our SIGSEGV handler. ldr w2, [x1, #MIRROR_OBJECT_CLASS_OFFSET] - // Test the first two bits of the fetched ArtMethod: - // - If the first bit is set, this is a method on j.l.Object - // - If the second bit is set, this is a default method. - tst w26, #0x3 - b.ne 3f - ldrh w3, [x26, #ART_METHOD_IMT_INDEX_OFFSET] -2: ldr x2, [x2, #MIRROR_CLASS_IMT_PTR_OFFSET_64] - ldr x0, [x2, w3, uxtw #3] + ldr x0, [x2, w0, uxtw #3] .if $range b NterpCommonInvokeInterfaceRange .else b NterpCommonInvokeInterface .endif -3: - tbnz w26, #0, 4f - and x26, x26, #-4 - ldrh w3, [x26, #ART_METHOD_METHOD_INDEX_OFFSET] - and w3, w3, #ART_METHOD_IMT_MASK - b 2b -4: - lsr w26, w26, #16 - add w2, w2, #MIRROR_CLASS_VTABLE_OFFSET_64 - ldr x0, [x2, w26, uxtw #3] - .if $range - b NterpCommonInvokeInstanceRange - .else - b NterpCommonInvokeInstance - .endif -5: +2: mov x0, xSELF ldr x1, [sp] mov x2, xPC bl nterp_get_method - mov x26, x0 - b 1b + // For j.l.Object interface calls, the high bit is set. Also the method index is 16bits. + tbz w0, #31, 1b + and w0, w0, #0xffff + .if $range + b NterpHandleInvokeInterfaceOnObjectMethodRange + .else + b NterpHandleInvokeInterfaceOnObjectMethod + .endif %def op_invoke_interface(): % invoke_interface(range="0") diff --git a/runtime/interpreter/mterp/arm64ng/main.S b/runtime/interpreter/mterp/arm64ng/main.S index b6d9db696f..8223a1bcd0 100644 --- a/runtime/interpreter/mterp/arm64ng/main.S +++ b/runtime/interpreter/mterp/arm64ng/main.S @@ -862,7 +862,6 @@ END \name // - xINST contains shorty (in callee-save to switch over return value after call). // - x0 contains method // - x1 contains 'this' pointer for instance method. - // - for interface calls, x26 contains the interface method. add x9, xINST, #1 // shorty + 1 ; ie skip return arg character FETCH w11, 2 // arguments .if \is_string_init @@ -904,8 +903,10 @@ END \name bl art_quick_invoke_custom .else .if \is_interface - // Setup hidden argument. - mov ip2, x26 + // Setup hidden argument. As we don't have access to the interface method, + // just pass the method from the IMT. If the method is the conflict trampoline, + // this will make the stub go to runtime, otherwise the hidden argument is unused. + mov ip2, x0 .endif ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64] blr lr @@ -1101,7 +1102,6 @@ END \name // - xINST contains shorty (in callee-save to switch over return value after call). // - x0 contains method // - x1 contains 'this' pointer for instance method. - // - for interface calls, x26 contains the interface method. add x9, xINST, #1 // shorty + 1 ; ie skip return arg character FETCH w10, 2 // arguments .if \is_string_init @@ -1154,8 +1154,10 @@ END \name bl art_quick_invoke_custom .else .if \is_interface - // Setup hidden argument. - mov ip2, x26 + // Setup hidden argument. As we don't have access to the interface method, + // just pass the method from the IMT. If the method is the conflict trampoline, + // this will make the stub go to runtime, otherwise the hidden argument is unused. + mov ip2, x0 .endif ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64] blr lr @@ -1580,6 +1582,27 @@ NterpHandleHotnessOverflow: // Jump to the compiled code. br xFP +NterpHandleInvokeInterfaceOnObjectMethodRange: + // First argument is the 'this' pointer. + FETCH w1, 2 + GET_VREG w1, w1 + // Note: x1 is null, this will be handled by our SIGSEGV handler. + ldr w2, [x1, #MIRROR_OBJECT_CLASS_OFFSET] + add w2, w2, #MIRROR_CLASS_VTABLE_OFFSET_64 + ldr x0, [x2, w0, sxtw #3] + b NterpCommonInvokeInstanceRange + +NterpHandleInvokeInterfaceOnObjectMethod: + // First argument is the 'this' pointer. + FETCH w1, 2 + and w1, w1, #0xf + GET_VREG w1, w1 + // Note: x1 is null, this will be handled by our SIGSEGV handler. + ldr w2, [x1, #MIRROR_OBJECT_CLASS_OFFSET] + add w2, w2, #MIRROR_CLASS_VTABLE_OFFSET_64 + ldr x0, [x2, w0, sxtw #3] + b NterpCommonInvokeInstance + // This is the logical end of ExecuteNterpImpl, where the frame info applies. // EndExecuteNterpImpl includes the methods below as we want the runtime to // see them as part of the Nterp PCs. diff --git a/runtime/interpreter/mterp/armng/invoke.S b/runtime/interpreter/mterp/armng/invoke.S index 151890f385..47678dc799 100644 --- a/runtime/interpreter/mterp/armng/invoke.S +++ b/runtime/interpreter/mterp/armng/invoke.S @@ -74,11 +74,10 @@ b NterpCommonInvokePolymorphicRange %def invoke_interface(range=""): -% slow_path = add_helper(lambda: op_invoke_interface_slow_path()) EXPORT_PC // Fast-path which gets the method from thread-local cache. - FETCH_FROM_THREAD_CACHE r4, ${slow_path} -.L${opcode}_resume: + FETCH_FROM_THREAD_CACHE r0, 2f +1: // First argument is the 'this' pointer. FETCH r1, 2 .if !$range @@ -87,44 +86,27 @@ GET_VREG r1, r1 // Note: if r1 is null, this will be handled by our SIGSEGV handler. ldr r2, [r1, #MIRROR_OBJECT_CLASS_OFFSET] - // Test the first two bits of the fetched ArtMethod: - // - If the first bit is set, this is a method on j.l.Object - // - If the second bit is set, this is a default method. - tst r4, #3 - bne 2f - ldrh r3, [r4, #ART_METHOD_IMT_INDEX_OFFSET] -1: ldr r2, [r2, #MIRROR_CLASS_IMT_PTR_OFFSET_32] - ldr r0, [r2, r3, uxtw #2] + ldr r0, [r2, r0, uxtw #2] .if $range b NterpCommonInvokeInterfaceRange .else b NterpCommonInvokeInterface .endif 2: - tst r4, #1 - bne 3f - and r4, r4, #-4 - ldrh r3, [r4, #ART_METHOD_METHOD_INDEX_OFFSET] - and r3, r3, #ART_METHOD_IMT_MASK - b 1b -3: - lsr r4, r4, #16 - add r2, r2, #MIRROR_CLASS_VTABLE_OFFSET_32 - ldr r0, [r2, r4, lsl #2] - .if $range - b NterpCommonInvokeInstanceRange - .else - b NterpCommonInvokeInstance - .endif - -%def op_invoke_interface_slow_path(): mov r0, rSELF ldr r1, [sp] mov r2, rPC bl nterp_get_method - mov r4, r0 - b .L${opcode}_resume + // For j.l.Object interface calls, the high bit is set. Also the method index is 16bits. + cmp r0, #0 + bge 1b + ubfx r0, r0, #0, #16 + .if $range + b NterpHandleInvokeInterfaceOnObjectMethodRange + .else + b NterpHandleInvokeInterfaceOnObjectMethod + .endif %def op_invoke_interface(): % invoke_interface(range="0") diff --git a/runtime/interpreter/mterp/armng/main.S b/runtime/interpreter/mterp/armng/main.S index 7095f58e53..680c8ad1d0 100644 --- a/runtime/interpreter/mterp/armng/main.S +++ b/runtime/interpreter/mterp/armng/main.S @@ -961,10 +961,6 @@ END \name .endif .Lcall_compiled_code_\suffix: - .if \is_interface - // Save hidden argument. - vmov s16, r4 - .endif GET_SHORTY rINST, \is_interface, \is_polymorphic, \is_custom // From this point: // - rINST contains shorty (in callee-save to switch over return value after call). @@ -1026,8 +1022,10 @@ END \name bl art_quick_invoke_custom .else .if \is_interface - // Setup hidden argument. - vmov ip, s16 + // Setup hidden argument. As we don't have access to the interface method, + // just pass the method from the IMT. If the method is the conflict trampoline, + // this will make the stub go to runtime, otherwise the hidden argument is unused. + mov ip, r0 .endif ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32] blx lr @@ -1162,10 +1160,6 @@ END \name .endif .Lcall_compiled_code_range_\suffix: - .if \is_interface - // Save hidden argument. - vmov s16, r4 - .endif GET_SHORTY rINST, \is_interface, \is_polymorphic, \is_custom // From this point: // - rINST contains shorty (in callee-save to switch over return value after call). @@ -1223,8 +1217,10 @@ END \name bl art_quick_invoke_custom .else .if \is_interface - // Setup hidden argument. - vmov ip, s16 + // Setup hidden argument. As we don't have access to the interface method, + // just pass the method from the IMT. If the method is the conflict trampoline, + // this will make the stub go to runtime, otherwise the hidden argument is unused. + mov ip, r0 .endif ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32] blx lr @@ -1555,6 +1551,26 @@ NterpNewArray: bl art_quick_read_barrier_mark_reg00 b 1b +NterpHandleInvokeInterfaceOnObjectMethodRange: + // First argument is the 'this' pointer. + FETCH r1, 2 + GET_VREG r1, r1 + // Note: if r1 is null, this will be handled by our SIGSEGV handler. + ldr r2, [r1, #MIRROR_OBJECT_CLASS_OFFSET] + add r2, r2, #MIRROR_CLASS_VTABLE_OFFSET_32 + ldr r0, [r2, r0, lsl #2] + b NterpCommonInvokeInstanceRange + +NterpHandleInvokeInterfaceOnObjectMethod: + // First argument is the 'this' pointer. + FETCH r1, 2 + and r1, r1, #0xf + GET_VREG r1, r1 + // Note: if r1 is null, this will be handled by our SIGSEGV handler. + ldr r2, [r1, #MIRROR_OBJECT_CLASS_OFFSET] + add r2, r2, #MIRROR_CLASS_VTABLE_OFFSET_32 + ldr r0, [r2, r0, lsl #2] + b NterpCommonInvokeInstance NterpHandleHotnessOverflow: add r1, rPC, rINST, lsl #1 diff --git a/runtime/interpreter/mterp/nterp.cc b/runtime/interpreter/mterp/nterp.cc index 20d830551b..48f483f462 100644 --- a/runtime/interpreter/mterp/nterp.cc +++ b/runtime/interpreter/mterp/nterp.cc @@ -384,23 +384,18 @@ extern "C" size_t NterpGetMethod(Thread* self, ArtMethod* caller, uint16_t* dex_ } if (invoke_type == kInterface) { - size_t result = 0u; if (resolved_method->GetDeclaringClass()->IsObjectClass()) { - // Set the low bit to notify the interpreter it should do a vtable call. + // Don't update the cache and return a value with high bit set to notify the + // interpreter it should do a vtable call instead. DCHECK_LT(resolved_method->GetMethodIndex(), 0x10000); - result = (resolved_method->GetMethodIndex() << 16) | 1U; + return resolved_method->GetMethodIndex() | (1U << 31); } else { DCHECK(resolved_method->GetDeclaringClass()->IsInterface()); - if (!resolved_method->IsAbstract()) { - // Set the second bit to notify the interpreter this is a default - // method. - result = reinterpret_cast<size_t>(resolved_method) | 2U; - } else { - result = reinterpret_cast<size_t>(resolved_method); - } + UpdateCache(self, dex_pc_ptr, resolved_method->GetImtIndex()); + // TODO: We should pass the resolved method, and have nterp fetch the IMT + // index. Unfortunately, this doesn't work for default methods. + return resolved_method->GetImtIndex(); } - UpdateCache(self, dex_pc_ptr, result); - return result; } else if (resolved_method->GetDeclaringClass()->IsStringClass() && !resolved_method->IsStatic() && resolved_method->IsConstructor()) { diff --git a/runtime/interpreter/mterp/x86_64ng/invoke.S b/runtime/interpreter/mterp/x86_64ng/invoke.S index ebe2fcf4cf..b7885b4b68 100644 --- a/runtime/interpreter/mterp/x86_64ng/invoke.S +++ b/runtime/interpreter/mterp/x86_64ng/invoke.S @@ -72,11 +72,10 @@ jmp NterpCommonInvokePolymorphicRange %def invoke_interface(helper="", range=""): -% slow_path = add_helper(lambda: op_invoke_interface_slow_path()) EXPORT_PC - // Fast-path which gets the interface method from thread-local cache. - FETCH_FROM_THREAD_CACHE %rax, ${slow_path} -.L${opcode}_resume: + // 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 @@ -84,35 +83,23 @@ .endif movl (rFP, %r11, 4), %esi movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx - // Test the first two bits of the fetched ArtMethod: - // - If the first bit is set, this is a method on j.l.Object - // - If the second bit is set, this is a default method. - testl $$3, %eax - jne 2f - movzw ART_METHOD_IMT_INDEX_OFFSET(%rax), %ecx -1: movq MIRROR_CLASS_IMT_PTR_OFFSET_64(%edx), %rdx - movq (%rdx, %rcx, 8), %rdi + movq (%rdx, %rax, 8), %rdi jmp $helper 2: - testl $$1, %eax - .if $range - jne NterpHandleInvokeInterfaceOnObjectMethodRange - .else - jne NterpHandleInvokeInterfaceOnObjectMethod - .endif - // Default method - andq $$-4, %rax - movzw ART_METHOD_METHOD_INDEX_OFFSET(%rax), %ecx - andl $$ART_METHOD_IMT_MASK, %ecx - jmp 1b - -%def op_invoke_interface_slow_path(): movq rSELF:THREAD_SELF_OFFSET, %rdi movq 0(%rsp), %rsi movq rPC, %rdx call nterp_get_method - jmp .L${opcode}_resume + testl %eax, %eax + jns 1b + // For j.l.Object interface calls, the high bit is set. Also the method index is 16bits. + andl LITERAL(0xffff), %eax + .if $range + jmp NterpHandleInvokeInterfaceOnObjectMethodRange + .else + jmp NterpHandleInvokeInterfaceOnObjectMethod + .endif %def op_invoke_interface(): % invoke_interface(helper="NterpCommonInvokeInterface", range="0") diff --git a/runtime/interpreter/mterp/x86_64ng/main.S b/runtime/interpreter/mterp/x86_64ng/main.S index fa5f4e4374..705ffae10f 100644 --- a/runtime/interpreter/mterp/x86_64ng/main.S +++ b/runtime/interpreter/mterp/x86_64ng/main.S @@ -464,7 +464,7 @@ END_FUNCTION \name // Uses rax as temporary. .macro LOOP_OVER_SHORTY_LOADING_GPRS gpr_reg64, gpr_reg32, inst, shorty, arg_index, finished 1: // LOOP - movb (REG_VAR(shorty)), %al // al := *shorty + movb (REG_VAR(shorty)), %al // bl := *shorty addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished je VAR(finished) @@ -531,7 +531,7 @@ END_FUNCTION \name // Uses rax as temporary. .macro LOOP_RANGE_OVER_SHORTY_LOADING_XMMS xmm_reg, shorty, arg_index, stack_index, finished 1: // LOOP - movb (REG_VAR(shorty)), %al // al := *shorty + movb (REG_VAR(shorty)), %al // bl := *shorty addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished je VAR(finished) @@ -605,7 +605,7 @@ END_FUNCTION \name // Uses rax as temporary. .macro LOOP_RANGE_OVER_SHORTY_LOADING_GPRS gpr_reg64, gpr_reg32, shorty, arg_index, stack_index, finished 1: // LOOP - movb (REG_VAR(shorty)), %al // al := *shorty + movb (REG_VAR(shorty)), %al // bl := *shorty addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished je VAR(finished) @@ -706,7 +706,7 @@ END_FUNCTION \name // Uses rax as temporary. .macro LOOP_OVER_SHORTY_STORING_GPRS gpr_reg64, gpr_reg32, shorty, arg_index, regs, refs, finished 1: // LOOP - movb (REG_VAR(shorty)), %al // al := *shorty + movb (REG_VAR(shorty)), %al // bl := *shorty addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished je VAR(finished) @@ -746,7 +746,7 @@ END_FUNCTION \name // (The trade-off is different for passing arguments and receiving them.) .macro LOOP_OVER_FPs shorty, arg_index, regs, stack_ptr, finished 1: // LOOP - movb (REG_VAR(shorty)), %al // al := *shorty + movb (REG_VAR(shorty)), %al // bl := *shorty addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished je VAR(finished) @@ -778,7 +778,7 @@ END_FUNCTION \name // Uses rax as temporary. .macro LOOP_OVER_INTs shorty, arg_index, regs, refs, stack_ptr, finished 1: // LOOP - movb (REG_VAR(shorty)), %al // al := *shorty + movb (REG_VAR(shorty)), %al // bl := *shorty addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished je VAR(finished) @@ -1041,11 +1041,10 @@ END_FUNCTION \name movq %rax, \dest .endm -// Uses r9 as temporary. .macro DO_ENTRY_POINT_CHECK call_compiled_code // On entry, the method is %rdi, the instance is %rsi - leaq ExecuteNterpImpl(%rip), %r9 - cmpq %r9, ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) + leaq ExecuteNterpImpl(%rip), %rax + cmpq %rax, ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) jne VAR(call_compiled_code) movq ART_METHOD_DATA_OFFSET_64(%rdi), %rax @@ -1085,10 +1084,6 @@ END_FUNCTION \name .endif .Lcall_compiled_code_\suffix: - .if \is_interface - // Save interface method, used for conflict resolution, in a callee-save register. - movq %rax, %xmm12 - .endif GET_SHORTY rINSTq, \is_interface, \is_polymorphic, \is_custom // From this point: // - rISNTq contains shorty (in callee-save to switch over return value after call). @@ -1135,7 +1130,10 @@ END_FUNCTION \name call SYMBOL(art_quick_invoke_custom) .else .if \is_interface - movq %xmm12, %rax + // Setup hidden argument. As we don't have access to the interface method, + // just pass the method from the IMT. If the method is the conflict trampoline, + // this will make the stub go to runtime, otherwise the hidden argument is unused. + movq %rdi, %rax .endif call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method. .endif @@ -1182,10 +1180,6 @@ END_FUNCTION \name .endif .Lcall_compiled_code_range_\suffix: - .if \is_interface - // Save interface method, used for conflict resolution, in a callee-saved register. - movq %rax, %xmm12 - .endif GET_SHORTY rINSTq, \is_interface, \is_polymorphic, \is_custom // From this point: // - rINSTq contains shorty (in callee-save to switch over return value after call). @@ -1238,8 +1232,10 @@ END_FUNCTION \name call SYMBOL(art_quick_invoke_custom) .else .if \is_interface - // Set the hidden argument for conflict resolution. - movq %xmm12, %rax + // Setup hidden argument. As we don't have access to the interface method, + // just pass the method from the IMT. If the method is the conflict trampoline, + // this will make the stub go to runtime, otherwise the hidden argument is unused. + movq %rdi, %rax .endif call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method. .endif @@ -1986,12 +1982,21 @@ NterpHandleHotnessOverflow: jmp *%rbx NterpHandleInvokeInterfaceOnObjectMethodRange: - shrl $$16, %eax + // 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 NterpHandleInvokeInterfaceOnObjectMethod: - shrl $$16, %eax + // First argument is the 'this' pointer. + movzwl 4(rPC), %r11d // arguments + andq MACRO_LITERAL(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 diff --git a/tools/cpp-define-generator/art_method.def b/tools/cpp-define-generator/art_method.def index 7b5606f935..097d4662e1 100644 --- a/tools/cpp-define-generator/art_method.def +++ b/tools/cpp-define-generator/art_method.def @@ -16,15 +16,12 @@ #if ASM_DEFINE_INCLUDE_DEPENDENCIES #include "art_method.h" -#include "imtable.h" #endif ASM_DEFINE(ART_METHOD_ACCESS_FLAGS_OFFSET, art::ArtMethod::AccessFlagsOffset().Int32Value()) ASM_DEFINE(ART_METHOD_IS_STATIC_FLAG, art::kAccStatic) -ASM_DEFINE(ART_METHOD_IMT_MASK, - art::ImTable::kSizeTruncToPowerOfTwo - 1) ASM_DEFINE(ART_METHOD_DECLARING_CLASS_OFFSET, art::ArtMethod::DeclaringClassOffset().Int32Value()) ASM_DEFINE(ART_METHOD_JNI_OFFSET_32, |