1/*
2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. 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 it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 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 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#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 COMPILER2
34#include "opto/matcher.hpp"
35#endif
36
37// ----------------------------------------------------------------------------
38
39#define __ _masm.
40address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
41  // Stub is fixed up when the corresponding call is converted from calling
42  // compiled code to calling interpreted code.
43  // set (empty), G5
44  // jmp -1
45
46  if (mark == NULL) {
47    mark = cbuf.insts_mark();  // Get mark within main instrs section.
48  }
49
50  MacroAssembler _masm(&cbuf);
51
52  address base = __ start_a_stub(to_interp_stub_size());
53  if (base == NULL) {
54    return NULL;  // CodeBuffer::expand failed.
55  }
56
57  // Static stub relocation stores the instruction address of the call.
58  __ relocate(static_stub_Relocation::spec(mark));
59
60  __ set_metadata(NULL, as_Register(Matcher::inline_cache_reg_encode()));
61
62  __ set_inst_mark();
63  AddressLiteral addrlit(-1);
64  __ JUMP(addrlit, G3, 0);
65
66  __ delayed()->nop();
67
68  assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size");
69
70  // Update current stubs pointer and restore code_end.
71  __ end_a_stub();
72  return base;
73}
74#undef __
75
76int CompiledStaticCall::to_interp_stub_size() {
77  // This doesn't need to be accurate but it must be larger or equal to
78  // the real size of the stub.
79  return (NativeMovConstReg::instruction_size +  // sethi/setlo;
80          NativeJump::instruction_size); // sethi; jmp; nop
81}
82
83// Relocation entries for call stub, compiled java to interpreter.
84int CompiledStaticCall::reloc_to_interp_stub() {
85  return 10;  // 4 in emit_java_to_interp + 1 in Java_Static_Call
86}
87
88void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
89  address stub = find_stub(/*is_aot*/ false);
90  guarantee(stub != NULL, "stub not found");
91
92  if (TraceICs) {
93    ResourceMark rm;
94    tty->print_cr("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
95                  p2i(instruction_address()),
96                  callee->name_and_sig_as_C_string());
97  }
98
99  // Creation also verifies the object.
100  NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
101  NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
102
103#ifdef ASSERT
104  // read the value once
105  intptr_t data = method_holder->data();
106  address destination = jump->jump_destination();
107  assert(data == 0 || data == (intptr_t)callee(),
108         "a) MT-unsafe modification of inline cache");
109  assert(destination == (address)-1 || destination == entry,
110         "b) MT-unsafe modification of inline cache");
111#endif
112
113  // Update stub.
114  method_holder->set_data((intptr_t)callee());
115  jump->set_jump_destination(entry);
116
117  // Update jump to call.
118  set_destination_mt_safe(stub);
119}
120
121void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
122  assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call");
123  // Reset stub.
124  address stub = static_stub->addr();
125  assert(stub != NULL, "stub not found");
126  // Creation also verifies the object.
127  NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
128  NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
129  method_holder->set_data(0);
130  jump->set_jump_destination((address)-1);
131}
132
133//-----------------------------------------------------------------------------
134// Non-product mode code
135#ifndef PRODUCT
136
137void CompiledDirectStaticCall::verify() {
138  // Verify call.
139  _call->verify();
140  if (os::is_MP()) {
141    _call->verify_alignment();
142  }
143
144  // Verify stub.
145  address stub = find_stub(/*is_aot*/ false);
146  assert(stub != NULL, "no stub found for static call");
147  // Creation also verifies the object.
148  NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
149  NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
150
151  // Verify state.
152  assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check");
153}
154
155#endif // !PRODUCT
156