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 39 address 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 // size of C2 call stub, compiled java to interpretor 89 int CompiledStaticCall::to_interp_stub_size() { 90 return 8 * NativeInstruction::instruction_size; 91 } 92 93 // Relocation entries for call stub, compiled java to interpreter. 94 int CompiledStaticCall::reloc_to_interp_stub() { 95 return 10; // 4 in emit_to_interp_stub + 1 in Java_Static_Call 96 } 97 #endif // COMPILER2 || JVMCI 98 99 void CompiledStaticCall::set_to_interpreted(methodHandle callee, address entry) { 100 address stub = find_stub(); 101 guarantee(stub != NULL, "stub not found"); 102 103 if (TraceICs) { 104 ResourceMark rm; 105 tty->print_cr("CompiledStaticCall@" 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 // Update jump to call. 129 set_destination_mt_safe(stub); 130 } 131 132 void CompiledStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { 133 assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call"); 134 // Reset stub. 135 address stub = static_stub->addr(); 136 assert(stub != NULL, "stub not found"); 137 // Creation also verifies the object. 138 NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); 139 NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); 140 method_holder->set_data(0); 141 jump->set_jump_destination((address)-1); 142 } 143 144 //----------------------------------------------------------------------------- 145 // Non-product mode code 146 #ifndef PRODUCT 147 148 void CompiledStaticCall::verify() { 149 // Verify call. 150 NativeCall::verify(); 151 if (os::is_MP()) { 152 verify_alignment(); 153 } 154 155 // Verify stub. 156 address stub = find_stub(); 157 assert(stub != NULL, "no stub found for static call"); 158 // Creation also verifies the object. 159 NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); 160 NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); 161 162 // Verify state. 163 assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check"); 164 } 165 166 #endif // !PRODUCT