diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index b3d89863e..8df709ad0 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -1279,12 +1279,12 @@ class HandlerImpl { static int emit_deopt_handler(CodeBuffer& cbuf); static uint size_exception_handler() { - return MacroAssembler::far_codestub_branch_size(); + return MacroAssembler::far_branch_size(); } static uint size_deopt_handler() { // count one adr and one far branch instruction - return NativeInstruction::instruction_size + MacroAssembler::far_codestub_branch_size(); + return 4 * NativeInstruction::instruction_size; } }; @@ -2367,7 +2367,7 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) __ adr(lr, __ pc()); __ far_jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); - assert(__ offset() - offset == (int) size_deopt_handler(), "overflow"); + assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); __ end_a_stub(); return offset; } diff --git a/src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp b/src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp index 7d0483fb3..21c2a3cc7 100644 --- a/src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp @@ -52,15 +52,9 @@ void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached address start = __ pc(); Label l; __ ldr(rscratch2, l); - int jump_code_size = __ far_jump(ExternalAddress(entry_point)); - // IC stub code size is not expected to vary depending on target address. - // We use NOPs to make the [ldr + far_jump + nops + int64] stub size equal to ic_stub_code_size. - for (int size = NativeInstruction::instruction_size + jump_code_size + 8; - size < ic_stub_code_size(); size += NativeInstruction::instruction_size) { - __ nop(); - } + __ far_jump(ExternalAddress(entry_point)); + __ align(wordSize); __ bind(l); - assert((uintptr_t)__ pc() % wordSize == 0, ""); __ emit_int64((int64_t)cached_value); // Only need to invalidate the 1st two instructions - not the whole ic stub ICache::invalidate_range(code_begin, InlineCacheBuffer::ic_stub_code_size()); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index d89d655af..9e84077f9 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -397,27 +397,14 @@ void MacroAssembler::set_last_Java_frame(Register last_java_sp, } } -static inline bool target_needs_far_branch(address addr) { - // codecache size <= 128M - if (!MacroAssembler::far_branches()) { - return false; - } - // codecache size > 240M - if (MacroAssembler::codestub_branch_needs_far_jump()) { - return true; - } - // codecache size: 128M..240M - return !CodeCache::is_non_nmethod(addr); -} - void MacroAssembler::far_call(Address entry, CodeBuffer *cbuf, Register tmp) { assert(ReservedCodeCacheSize < 4*G, "branch out of range"); assert(CodeCache::find_blob(entry.target()) != NULL, "destination of far call not found in code cache"); - if (target_needs_far_branch(entry.target())) { + if (far_branches()) { uint64_t offset; // We can use ADRP here because we know that the total size of - // the code cache cannot exceed 2Gb (ADRP limit is 4GB). + // the code cache cannot exceed 2Gb. adrp(tmp, entry, offset); add(tmp, tmp, offset); if (cbuf) cbuf->set_insts_mark(); @@ -428,15 +415,14 @@ void MacroAssembler::far_call(Address entry, CodeBuffer *cbuf, Register tmp) { } } -int MacroAssembler::far_jump(Address entry, CodeBuffer *cbuf, Register tmp) { +void MacroAssembler::far_jump(Address entry, CodeBuffer *cbuf, Register tmp) { assert(ReservedCodeCacheSize < 4*G, "branch out of range"); assert(CodeCache::find_blob(entry.target()) != NULL, "destination of far call not found in code cache"); - address start = pc(); - if (target_needs_far_branch(entry.target())) { + if (far_branches()) { uint64_t offset; // We can use ADRP here because we know that the total size of - // the code cache cannot exceed 2Gb (ADRP limit is 4GB). + // the code cache cannot exceed 2Gb. adrp(tmp, entry, offset); add(tmp, tmp, offset); if (cbuf) cbuf->set_insts_mark(); @@ -445,7 +431,6 @@ int MacroAssembler::far_jump(Address entry, CodeBuffer *cbuf, Register tmp) { if (cbuf) cbuf->set_insts_mark(); b(entry); } - return pc() - start; } void MacroAssembler::reserved_stack_check() { diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index e403289e2..06733edd6 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -1086,18 +1086,13 @@ public: return ReservedCodeCacheSize > branch_range; } - // Check if branches to the the non nmethod section require a far jump - static bool codestub_branch_needs_far_jump() { - return CodeCache::max_distance_to_non_nmethod() > branch_range; - } - // Jumps that can reach anywhere in the code cache. // Trashes tmp. void far_call(Address entry, CodeBuffer *cbuf = NULL, Register tmp = rscratch1); - int far_jump(Address entry, CodeBuffer *cbuf = NULL, Register tmp = rscratch1); + void far_jump(Address entry, CodeBuffer *cbuf = NULL, Register tmp = rscratch1); - static int far_codestub_branch_size() { - if (codestub_branch_needs_far_jump()) { + static int far_branch_size() { + if (far_branches()) { return 3 * 4; // adrp, add, br } else { return 4; diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 28158adbc..1c6aa37b8 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -296,20 +296,19 @@ void CodeCache::initialize_heaps() { const size_t alignment = MAX2(ps, (size_t) os::vm_allocation_granularity()); non_nmethod_size = align_up(non_nmethod_size, alignment); profiled_size = align_down(profiled_size, alignment); - non_profiled_size = align_down(non_profiled_size, alignment); // Reserve one continuous chunk of memory for CodeHeaps and split it into // parts for the individual heaps. The memory layout looks like this: // ---------- high ----------- // Non-profiled nmethods - // Non-nmethods // Profiled nmethods + // Non-nmethods // ---------- low ------------ ReservedCodeSpace rs = reserve_heap_memory(cache_size, ps); - ReservedSpace profiled_space = rs.first_part(profiled_size); - ReservedSpace rest = rs.last_part(profiled_size); - ReservedSpace non_method_space = rest.first_part(non_nmethod_size); - ReservedSpace non_profiled_space = rest.last_part(non_nmethod_size); + ReservedSpace non_method_space = rs.first_part(non_nmethod_size); + ReservedSpace rest = rs.last_part(non_nmethod_size); + ReservedSpace profiled_space = rest.first_part(profiled_size); + ReservedSpace non_profiled_space = rest.last_part(profiled_size); // Non-nmethods (stubs, adapters, ...) add_heap(non_method_space, "CodeHeap 'non-nmethods'", CodeBlobType::NonNMethod); @@ -899,23 +898,6 @@ size_t CodeCache::max_capacity() { return max_cap; } -bool CodeCache::is_non_nmethod(address addr) { - CodeHeap* blob = get_code_heap(CodeBlobType::NonNMethod); - return blob->contains(addr); -} - -size_t CodeCache::max_distance_to_non_nmethod() { - if (!SegmentedCodeCache) { - return ReservedCodeCacheSize; - } else { - CodeHeap* blob = get_code_heap(CodeBlobType::NonNMethod); - // the max distance is minimized by placing the NonNMethod segment - // in between MethodProfiled and MethodNonProfiled segments - size_t dist1 = (size_t)blob->high() - (size_t)_low_bound; - size_t dist2 = (size_t)_high_bound - (size_t)blob->low(); - return dist1 > dist2 ? dist1 : dist2; - } -} // Returns the reverse free ratio. E.g., if 25% (1/4) of the code cache // is free, reverse_free_ratio() returns 4. diff --git a/src/hotspot/share/code/codeCache.hpp b/src/hotspot/share/code/codeCache.hpp index ca3bae1df..b1219de48 100644 --- a/src/hotspot/share/code/codeCache.hpp +++ b/src/hotspot/share/code/codeCache.hpp @@ -213,9 +213,6 @@ class CodeCache : AllStatic { static double reverse_free_ratio(); - static size_t max_distance_to_non_nmethod(); - static bool is_non_nmethod(address addr); - static void clear_inline_caches(); // clear all inline caches static void cleanup_inline_caches(); // clean unloaded/zombie nmethods from inline caches diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestFarJump.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestFarJump.java deleted file mode 100644 index f47331a6d..000000000 --- a/test/hotspot/jtreg/compiler/c2/aarch64/TestFarJump.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2022, BELLSOFT. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package compiler.c2.aarch64; - -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.*; - -/* - * @test - * @bug 8280872 - * @summary Far call to runtime stub should be generated with single instruction for CodeHeap up to 250MB - * @library /test/lib / - * - * @requires vm.flagless - * @requires os.arch=="aarch64" - * @requires vm.debug == false - * @requires vm.compiler2.enabled - * - * @run driver compiler.c2.aarch64.TestFarJump - */ -public class TestFarJump { - - // ADRP instruction encoding: - // |31 30 29 28|27 26 25 24|23 22 21 20|19 18 17 16|15 14 13 12|11 10 09 08|07 06 05 04|03 02 01 10| - // | 1|immlo| 1 0 0 0 0| immhi | Rd | - static boolean isADRP(int encoding) { - final int mask = 0b1001_1111; - final int val = 0b1001_0000; - return ((encoding >> 24) & mask) == val; - } - - // Looking for adrp instruction in binary/text assembly output: - // 0x0000ffff7ff1b7d0: c8ff ffd0 | 0801 1091 | 0001 1fd6 - // 0x0000ffff6bf20ee0: adrp x8, 0x0000ffff6bef1000 - static boolean containsADRP(String input) { - int index = input.indexOf(": "); - if (index == -1) { - return false; - } - input = input.substring(index + 1); - if (input.contains("adrp")) { - return true; - } - Pattern pattern = Pattern.compile("[0-9a-f ]*"); - Matcher matcher = pattern.matcher(input); - while (matcher.find()) { - String match = matcher.group(); - match = match.replace(" " , ""); - if (match.length() != 8) { - continue; - } - int dump = (int)Long.parseLong(match, 16); - int encoding = Integer.reverseBytes(dump); - // Check the first instruction only. The raw pointer can be confused with the encoded adrp instruction: - // emit_exception_handler() = far_call() + should_not_reach_here() = ADRP + ADD + BLR + DCPS1 + raw_pointer - return isADRP(encoding); - } - return false; - } - - static void runVM(boolean bigCodeHeap) throws Exception { - String className = TestFarJump.class.getName(); - String[] procArgs = { - "-XX:-Inline", - "-Xcomp", - "-Xbatch", - "-XX:+TieredCompilation", - "-XX:+SegmentedCodeCache", - "-XX:CompileOnly=" + className + "::main", - "-XX:ReservedCodeCacheSize=" + (bigCodeHeap ? "256M" : "200M"), - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+PrintAssembly", - className}; - - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(procArgs); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - List lines = output.asLines(); - - ListIterator itr = lines.listIterator(); - while (itr.hasNext()) { - String line = itr.next(); - if (line.contains("[Exception Handler]")) { - String next1 = itr.next(); - String next2 = itr.next(); - System.out.println(line); - System.out.println(next1); - System.out.println(next2); - boolean containsADRP = containsADRP(next1) || containsADRP(next2); - if (bigCodeHeap && !containsADRP) { - throw new RuntimeException("ADRP instruction is expected on far jump"); - } - if (!bigCodeHeap && containsADRP) { - throw new RuntimeException("for CodeHeap < 250MB the far jump is expected to be encoded with a single branch instruction"); - } - return; - } - } - throw new RuntimeException("Assembly output: exception Handler is not found"); - } - - public static void main(String[] args) throws Exception { - if (args.length == 0) { - // Main VM: fork VM with options - runVM(true); - runVM(false); - return; - } - if (args.length > 0) { - // We are in a forked VM. Just exit - System.out.println("Ok"); - } - } -} - -- 2.39.0