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