compiledIC_sparc.cpp revision 11290:cb23e08014a8
154359Sroberto/* 254359Sroberto * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 354359Sroberto * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 454359Sroberto * 554359Sroberto * This code is free software; you can redistribute it and/or modify it 654359Sroberto * under the terms of the GNU General Public License version 2 only, as 754359Sroberto * published by the Free Software Foundation. 854359Sroberto * 954359Sroberto * This code is distributed in the hope that it will be useful, but WITHOUT 1054359Sroberto * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1154359Sroberto * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1254359Sroberto * version 2 for more details (a copy is included in the LICENSE file that 1354359Sroberto * accompanied this code). 1454359Sroberto * 1554359Sroberto * You should have received a copy of the GNU General Public License version 1654359Sroberto * 2 along with this work; if not, write to the Free Software Foundation, 1754359Sroberto * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1854359Sroberto * 1954359Sroberto * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2054359Sroberto * or visit www.oracle.com if you need additional information or have any 2154359Sroberto * questions. 2254359Sroberto * 2354359Sroberto */ 2454359Sroberto 2554359Sroberto#include "precompiled.hpp" 2654359Sroberto#include "asm/macroAssembler.inline.hpp" 2754359Sroberto#include "code/compiledIC.hpp" 2854359Sroberto#include "code/icBuffer.hpp" 2954359Sroberto#include "code/nmethod.hpp" 3054359Sroberto#include "memory/resourceArea.hpp" 3154359Sroberto#include "runtime/mutexLocker.hpp" 3254359Sroberto#include "runtime/safepoint.hpp" 3354359Sroberto#ifdef COMPILER2 3454359Sroberto#include "opto/matcher.hpp" 3554359Sroberto#endif 3654359Sroberto 3754359Sroberto// ---------------------------------------------------------------------------- 3854359Sroberto 3954359Sroberto#define __ _masm. 4054359Srobertoaddress CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { 4154359Sroberto // Stub is fixed up when the corresponding call is converted from calling 4254359Sroberto // compiled code to calling interpreted code. 4354359Sroberto // set (empty), G5 4454359Sroberto // jmp -1 4554359Sroberto 4654359Sroberto if (mark == NULL) { 4754359Sroberto mark = cbuf.insts_mark(); // Get mark within main instrs section. 4854359Sroberto } 4954359Sroberto 5054359Sroberto MacroAssembler _masm(&cbuf); 5154359Sroberto 5254359Sroberto address base = __ start_a_stub(to_interp_stub_size()); 5354359Sroberto if (base == NULL) { 5454359Sroberto return NULL; // CodeBuffer::expand failed. 5554359Sroberto } 5654359Sroberto 5754359Sroberto // Static stub relocation stores the instruction address of the call. 5854359Sroberto __ relocate(static_stub_Relocation::spec(mark)); 5954359Sroberto 6054359Sroberto __ set_metadata(NULL, as_Register(Matcher::inline_cache_reg_encode())); 61289764Sglebius 6254359Sroberto __ set_inst_mark(); 6354359Sroberto AddressLiteral addrlit(-1); 6454359Sroberto __ JUMP(addrlit, G3, 0); 6554359Sroberto 6654359Sroberto __ delayed()->nop(); 6754359Sroberto 6854359Sroberto assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size"); 6954359Sroberto 7054359Sroberto // Update current stubs pointer and restore code_end. 7154359Sroberto __ end_a_stub(); 7254359Sroberto return base; 7354359Sroberto} 7454359Sroberto#undef __ 7554359Sroberto 7654359Srobertoint CompiledStaticCall::to_interp_stub_size() { 7754359Sroberto // This doesn't need to be accurate but it must be larger or equal to 7854359Sroberto // the real size of the stub. 7954359Sroberto return (NativeMovConstReg::instruction_size + // sethi/setlo; 8054359Sroberto NativeJump::instruction_size + // sethi; jmp; nop 8154359Sroberto (TraceJumps ? 20 * BytesPerInstWord : 0) ); 8254359Sroberto} 8354359Sroberto 8454359Sroberto// Relocation entries for call stub, compiled java to interpreter. 8554359Srobertoint CompiledStaticCall::reloc_to_interp_stub() { 8654359Sroberto return 10; // 4 in emit_java_to_interp + 1 in Java_Static_Call 8754359Sroberto} 8854359Sroberto 8954359Srobertovoid CompiledStaticCall::set_to_interpreted(methodHandle callee, address entry) { 9054359Sroberto address stub = find_stub(); 9154359Sroberto guarantee(stub != NULL, "stub not found"); 9254359Sroberto 9354359Sroberto if (TraceICs) { 9454359Sroberto ResourceMark rm; 9554359Sroberto tty->print_cr("CompiledStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s", 9654359Sroberto p2i(instruction_address()), 9754359Sroberto callee->name_and_sig_as_C_string()); 9854359Sroberto } 9954359Sroberto 10054359Sroberto // Creation also verifies the object. 10154359Sroberto NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); 10254359Sroberto NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); 10354359Sroberto 10454359Sroberto#ifdef ASSERT 10554359Sroberto // read the value once 10654359Sroberto intptr_t data = method_holder->data(); 10754359Sroberto address destination = jump->jump_destination(); 10854359Sroberto assert(data == 0 || data == (intptr_t)callee(), 10954359Sroberto "a) MT-unsafe modification of inline cache"); 11054359Sroberto assert(destination == (address)-1 || destination == entry, 11154359Sroberto "b) MT-unsafe modification of inline cache"); 11254359Sroberto#endif 11354359Sroberto 11454359Sroberto // Update stub. 11554359Sroberto method_holder->set_data((intptr_t)callee()); 11654359Sroberto jump->set_jump_destination(entry); 11754359Sroberto 11854359Sroberto // Update jump to call. 11954359Sroberto set_destination_mt_safe(stub); 12054359Sroberto} 12154359Sroberto 12254359Srobertovoid CompiledStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { 12354359Sroberto assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call"); 12454359Sroberto // Reset stub. 12554359Sroberto address stub = static_stub->addr(); 12654359Sroberto assert(stub != NULL, "stub not found"); 12754359Sroberto // Creation also verifies the object. 12854359Sroberto NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); 12954359Sroberto NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); 13054359Sroberto method_holder->set_data(0); 13154359Sroberto jump->set_jump_destination((address)-1); 13254359Sroberto} 13354359Sroberto 13454359Sroberto//----------------------------------------------------------------------------- 13554359Sroberto// Non-product mode code 13654359Sroberto#ifndef PRODUCT 13754359Sroberto 13854359Srobertovoid CompiledStaticCall::verify() { 13954359Sroberto // Verify call. 14054359Sroberto NativeCall::verify(); 14154359Sroberto if (os::is_MP()) { 14254359Sroberto verify_alignment(); 14354359Sroberto } 14454359Sroberto 14554359Sroberto // Verify stub. 14654359Sroberto address stub = find_stub(); 14754359Sroberto assert(stub != NULL, "no stub found for static call"); 14854359Sroberto // Creation also verifies the object. 14954359Sroberto NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); 15054359Sroberto NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); 15154359Sroberto 15254359Sroberto // Verify state. 15354359Sroberto assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check"); 15454359Sroberto} 15554359Sroberto 15654359Sroberto#endif // !PRODUCT 15754359Sroberto