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/nativeInst.hpp"
30#include "code/nmethod.hpp"
31#include "memory/resourceArea.hpp"
32#include "runtime/mutexLocker.hpp"
33#include "runtime/safepoint.hpp"
34
35// ----------------------------------------------------------------------------
36#if defined(COMPILER2) || INCLUDE_JVMCI
37#define __ _masm.
38// emit call stub, compiled java to interpreter
39address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
40  // Stub is fixed up when the corresponding call is converted from calling
41  // compiled code to calling interpreted code.
42  // set (empty), R9
43  // b -1
44
45  if (mark == NULL) {
46    mark = cbuf.insts_mark();  // get mark within main instrs section
47  }
48
49  MacroAssembler _masm(&cbuf);
50
51  address base = __ start_a_stub(to_interp_stub_size());
52  if (base == NULL) {
53    return NULL;  // CodeBuffer::expand failed
54  }
55
56  // static stub relocation stores the instruction address of the call
57  __ relocate(static_stub_Relocation::spec(mark));
58
59  InlinedMetadata object_literal(NULL);
60  // single instruction, see NativeMovConstReg::next_instruction_address() in
61  // CompiledStaticCall::set_to_interpreted()
62  __ ldr_literal(Rmethod, object_literal);
63
64  __ set_inst_mark(); // Who uses this?
65
66  bool near_range = __ cache_fully_reachable();
67  InlinedAddress dest((address)-1);
68  address branch_site = __ pc();
69  if (near_range) {
70    __ b(branch_site); // special NativeJump -1 destination
71  } else {
72    // Can't trash LR, FP, or argument registers
73    __ indirect_jump(dest, Rtemp);
74  }
75  __ bind_literal(object_literal); // includes spec_for_immediate reloc
76  if (!near_range) {
77    __ bind_literal(dest); // special NativeJump -1 destination
78  }
79
80  assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size");
81
82  // Update current stubs pointer and restore code_end.
83  __ end_a_stub();
84  return base;
85}
86#undef __
87
88// Relocation entries for call stub, compiled java to interpreter.
89int CompiledStaticCall::reloc_to_interp_stub() {
90  return 10;  // 4 in emit_to_interp_stub + 1 in Java_Static_Call
91}
92#endif // COMPILER2 || JVMCI
93
94// size of C2 call stub, compiled java to interpretor
95int CompiledStaticCall::to_interp_stub_size() {
96  return 8 * NativeInstruction::instruction_size;
97}
98
99void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
100  address stub = find_stub(/*is_aot*/ false);
101  guarantee(stub != NULL, "stub not found");
102
103  if (TraceICs) {
104    ResourceMark rm;
105    tty->print_cr("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
106                  p2i(instruction_address()),
107                  callee->name_and_sig_as_C_string());
108  }
109
110  // Creation also verifies the object.
111  NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
112  NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
113
114#ifdef ASSERT
115  // read the value once
116  volatile intptr_t data = method_holder->data();
117  volatile address destination = jump->jump_destination();
118  assert(data == 0 || data == (intptr_t)callee(),
119         "a) MT-unsafe modification of inline cache");
120  assert(destination == (address)-1 || destination == entry,
121         "b) MT-unsafe modification of inline cache");
122#endif
123
124  // Update stub.
125  method_holder->set_data((intptr_t)callee());
126  jump->set_jump_destination(entry);
127
128  ICache::invalidate_range(stub, to_interp_stub_size());
129
130  // Update jump to call.
131  set_destination_mt_safe(stub);
132}
133
134void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
135  assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call");
136  // Reset stub.
137  address stub = static_stub->addr();
138  assert(stub != NULL, "stub not found");
139  // Creation also verifies the object.
140  NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
141  NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
142  method_holder->set_data(0);
143  jump->set_jump_destination((address)-1);
144}
145
146//-----------------------------------------------------------------------------
147// Non-product mode code
148#ifndef PRODUCT
149
150void CompiledDirectStaticCall::verify() {
151  // Verify call.
152  _call->verify();
153  if (os::is_MP()) {
154    _call->verify_alignment();
155  }
156
157  // Verify stub.
158  address stub = find_stub(/*is_aot*/ false);
159  assert(stub != NULL, "no stub found for static call");
160  // Creation also verifies the object.
161  NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
162  NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
163
164  // Verify state.
165  assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check");
166}
167
168#endif // !PRODUCT
169