Path: blob/master/src/hotspot/cpu/ppc/compiledIC_ppc.cpp
40930 views
/*1* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.2* Copyright (c) 2012, 2015 SAP SE. All rights reserved.3* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.4*5* This code is free software; you can redistribute it and/or modify it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/2425#include "precompiled.hpp"26#include "asm/macroAssembler.inline.hpp"27#include "code/compiledIC.hpp"28#include "code/icBuffer.hpp"29#include "code/nmethod.hpp"30#include "memory/resourceArea.hpp"31#include "runtime/mutexLocker.hpp"32#include "runtime/safepoint.hpp"33#ifdef COMPILER234#include "opto/matcher.hpp"35#endif3637// ----------------------------------------------------------------------------3839// A PPC CompiledDirectStaticCall looks like this:40//41// >>>> consts42//43// [call target1]44// [IC cache]45// [call target2]46//47// <<<< consts48// >>>> insts49//50// bl offset16 -+ -+ ??? // How many bits available?51// | |52// <<<< insts | |53// >>>> stubs | |54// | |- trampoline_stub_Reloc55// trampoline stub: | <-+56// r2 = toc |57// r2 = [r2 + offset] | // Load call target1 from const section58// mtctr r2 |59// bctr |- static_stub_Reloc60// comp_to_interp_stub: <---+61// r1 = toc62// ICreg = [r1 + IC_offset] // Load IC from const section63// r1 = [r1 + offset] // Load call target2 from const section64// mtctr r165// bctr66//67// <<<< stubs68//69// The call instruction in the code either70// - branches directly to a compiled method if offset encodable in instruction71// - branches to the trampoline stub if offset to compiled method not encodable72// - branches to the compiled_to_interp stub if target interpreted73//74// Further there are three relocations from the loads to the constants in75// the constant section.76//77// Usage of r1 and r2 in the stubs allows to distinguish them.7879const int IC_pos_in_java_to_interp_stub = 8;80#define __ _masm.81address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = NULL*/) {82#ifdef COMPILER283if (mark == NULL) {84// Get the mark within main instrs section which is set to the address of the call.85mark = cbuf.insts_mark();86}8788// Note that the code buffer's insts_mark is always relative to insts.89// That's why we must use the macroassembler to generate a stub.90MacroAssembler _masm(&cbuf);9192// Start the stub.93address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size());94if (stub == NULL) {95return NULL; // CodeCache is full96}9798// For java_to_interp stubs we use R11_scratch1 as scratch register99// and in call trampoline stubs we use R12_scratch2. This way we100// can distinguish them (see is_NativeCallTrampolineStub_at()).101Register reg_scratch = R11_scratch1;102103// Create a static stub relocation which relates this stub104// with the call instruction at insts_call_instruction_offset in the105// instructions code-section.106__ relocate(static_stub_Relocation::spec(mark));107const int stub_start_offset = __ offset();108109// Now, create the stub's code:110// - load the TOC111// - load the inline cache oop from the constant pool112// - load the call target from the constant pool113// - call114__ calculate_address_from_global_toc(reg_scratch, __ method_toc());115AddressLiteral ic = __ allocate_metadata_address((Metadata *)NULL);116bool success = __ load_const_from_method_toc(as_Register(Matcher::inline_cache_reg_encode()),117ic, reg_scratch, /*fixed_size*/ true);118if (!success) {119return NULL; // CodeCache is full120}121122if (ReoptimizeCallSequences) {123__ b64_patchable((address)-1, relocInfo::none);124} else {125AddressLiteral a((address)-1);126success = __ load_const_from_method_toc(reg_scratch, a, reg_scratch, /*fixed_size*/ true);127if (!success) {128return NULL; // CodeCache is full129}130__ mtctr(reg_scratch);131__ bctr();132}133134// FIXME: Assert that the stub can be identified and patched.135136// Java_to_interp_stub_size should be good.137assert((__ offset() - stub_start_offset) <= CompiledStaticCall::to_interp_stub_size(),138"should be good size");139assert(!is_NativeCallTrampolineStub_at(__ addr_at(stub_start_offset)),140"must not confuse java_to_interp with trampoline stubs");141142// End the stub.143__ end_a_stub();144return stub;145#else146ShouldNotReachHere();147return NULL;148#endif149}150#undef __151152// Size of java_to_interp stub, this doesn't need to be accurate but it must153// be larger or equal to the real size of the stub.154// Used for optimization in Compile::Shorten_branches.155int CompiledStaticCall::to_interp_stub_size() {156return 12 * BytesPerInstWord;157}158159// Relocation entries for call stub, compiled java to interpreter.160// Used for optimization in Compile::Shorten_branches.161int CompiledStaticCall::reloc_to_interp_stub() {162return 5;163}164165void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {166address stub = find_stub();167guarantee(stub != NULL, "stub not found");168169if (TraceICs) {170ResourceMark rm;171tty->print_cr("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",172p2i(instruction_address()),173callee->name_and_sig_as_C_string());174}175176// Creation also verifies the object.177NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + IC_pos_in_java_to_interp_stub);178NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());179180verify_mt_safe(callee, entry, method_holder, jump);181182// Update stub.183method_holder->set_data((intptr_t)callee());184jump->set_jump_destination(entry);185186// Update jump to call.187set_destination_mt_safe(stub);188}189190void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {191// Reset stub.192address stub = static_stub->addr();193assert(stub != NULL, "stub not found");194assert(CompiledICLocker::is_safe(stub), "mt unsafe call");195// Creation also verifies the object.196NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + IC_pos_in_java_to_interp_stub);197NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());198method_holder->set_data(0);199jump->set_jump_destination((address)-1);200}201202//-----------------------------------------------------------------------------203// Non-product mode code204#ifndef PRODUCT205206void CompiledDirectStaticCall::verify() {207// Verify call.208_call->verify();209_call->verify_alignment();210211// Verify stub.212address stub = find_stub();213assert(stub != NULL, "no stub found for static call");214// Creation also verifies the object.215NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + IC_pos_in_java_to_interp_stub);216NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());217218// Verify state.219assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check");220}221222#endif // !PRODUCT223224225