1/* 2 * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. 3 * Copyright 2008, 2009, 2010 Red Hat, Inc. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26#include "precompiled.hpp" 27#include "runtime/atomic.hpp" 28#include "runtime/biasedLocking.hpp" 29#include "runtime/deoptimization.hpp" 30#include "runtime/thread.hpp" 31#include "shark/llvmHeaders.hpp" 32#include "shark/sharkRuntime.hpp" 33#include "utilities/macros.hpp" 34#ifdef ZERO 35# include "stack_zero.inline.hpp" 36#endif 37 38using namespace llvm; 39 40JRT_ENTRY(int, SharkRuntime::find_exception_handler(JavaThread* thread, 41 int* indexes, 42 int num_indexes)) 43 constantPoolHandle pool(thread, method(thread)->constants()); 44 KlassHandle exc_klass(thread, ((oop) tos_at(thread, 0))->klass()); 45 46 for (int i = 0; i < num_indexes; i++) { 47 Klass* tmp = pool->klass_at(indexes[i], CHECK_0); 48 KlassHandle chk_klass(thread, tmp); 49 50 if (exc_klass() == chk_klass()) 51 return i; 52 53 if (exc_klass()->is_subtype_of(chk_klass())) 54 return i; 55 } 56 57 return -1; 58JRT_END 59 60JRT_ENTRY(void, SharkRuntime::monitorenter(JavaThread* thread, 61 BasicObjectLock* lock)) 62 if (PrintBiasedLockingStatistics) 63 Atomic::inc(BiasedLocking::slow_path_entry_count_addr()); 64 65 Handle object(thread, lock->obj()); 66 assert(Universe::heap()->is_in_reserved_or_null(object()), "should be"); 67 if (UseBiasedLocking) { 68 // Retry fast entry if bias is revoked to avoid unnecessary inflation 69 ObjectSynchronizer::fast_enter(object, lock->lock(), true, CHECK); 70 } else { 71 ObjectSynchronizer::slow_enter(object, lock->lock(), CHECK); 72 } 73 assert(Universe::heap()->is_in_reserved_or_null(lock->obj()), "should be"); 74JRT_END 75 76JRT_ENTRY(void, SharkRuntime::monitorexit(JavaThread* thread, 77 BasicObjectLock* lock)) 78 Handle object(thread, lock->obj()); 79 assert(Universe::heap()->is_in_reserved_or_null(object()), "should be"); 80 if (lock == NULL || object()->is_unlocked()) { 81 THROW(vmSymbols::java_lang_IllegalMonitorStateException()); 82 } 83 ObjectSynchronizer::slow_exit(object(), lock->lock(), thread); 84JRT_END 85 86JRT_ENTRY(void, SharkRuntime::new_instance(JavaThread* thread, int index)) 87 Klass* k_oop = method(thread)->constants()->klass_at(index, CHECK); 88 instanceKlassHandle klass(THREAD, k_oop); 89 90 // Make sure we are not instantiating an abstract klass 91 klass->check_valid_for_instantiation(true, CHECK); 92 93 // Make sure klass is initialized 94 klass->initialize(CHECK); 95 96 // At this point the class may not be fully initialized 97 // because of recursive initialization. If it is fully 98 // initialized & has_finalized is not set, we rewrite 99 // it into its fast version (Note: no locking is needed 100 // here since this is an atomic byte write and can be 101 // done more than once). 102 // 103 // Note: In case of classes with has_finalized we don't 104 // rewrite since that saves us an extra check in 105 // the fast version which then would call the 106 // slow version anyway (and do a call back into 107 // Java). 108 // If we have a breakpoint, then we don't rewrite 109 // because the _breakpoint bytecode would be lost. 110 oop obj = klass->allocate_instance(CHECK); 111 thread->set_vm_result(obj); 112JRT_END 113 114JRT_ENTRY(void, SharkRuntime::newarray(JavaThread* thread, 115 BasicType type, 116 int size)) 117 oop obj = oopFactory::new_typeArray(type, size, CHECK); 118 thread->set_vm_result(obj); 119JRT_END 120 121JRT_ENTRY(void, SharkRuntime::anewarray(JavaThread* thread, 122 int index, 123 int size)) 124 Klass* klass = method(thread)->constants()->klass_at(index, CHECK); 125 objArrayOop obj = oopFactory::new_objArray(klass, size, CHECK); 126 thread->set_vm_result(obj); 127JRT_END 128 129JRT_ENTRY(void, SharkRuntime::multianewarray(JavaThread* thread, 130 int index, 131 int ndims, 132 int* dims)) 133 Klass* klass = method(thread)->constants()->klass_at(index, CHECK); 134 oop obj = ArrayKlass::cast(klass)->multi_allocate(ndims, dims, CHECK); 135 thread->set_vm_result(obj); 136JRT_END 137 138JRT_ENTRY(void, SharkRuntime::register_finalizer(JavaThread* thread, 139 oop object)) 140 assert(object->is_oop(), "should be"); 141 assert(object->klass()->has_finalizer(), "should have"); 142 InstanceKlass::register_finalizer(instanceOop(object), CHECK); 143JRT_END 144 145JRT_ENTRY(void, SharkRuntime::throw_ArithmeticException(JavaThread* thread, 146 const char* file, 147 int line)) 148 Exceptions::_throw_msg( 149 thread, file, line, 150 vmSymbols::java_lang_ArithmeticException(), 151 ""); 152JRT_END 153 154JRT_ENTRY(void, SharkRuntime::throw_ArrayIndexOutOfBoundsException( 155 JavaThread* thread, 156 const char* file, 157 int line, 158 int index)) 159 char msg[jintAsStringSize]; 160 snprintf(msg, sizeof(msg), "%d", index); 161 Exceptions::_throw_msg( 162 thread, file, line, 163 vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), 164 msg); 165JRT_END 166 167JRT_ENTRY(void, SharkRuntime::throw_ClassCastException(JavaThread* thread, 168 const char* file, 169 int line)) 170 Exceptions::_throw_msg( 171 thread, file, line, 172 vmSymbols::java_lang_ClassCastException(), 173 ""); 174JRT_END 175 176JRT_ENTRY(void, SharkRuntime::throw_NullPointerException(JavaThread* thread, 177 const char* file, 178 int line)) 179 Exceptions::_throw_msg( 180 thread, file, line, 181 vmSymbols::java_lang_NullPointerException(), 182 ""); 183JRT_END 184 185// Non-VM calls 186// Nothing in these must ever GC! 187 188void SharkRuntime::dump(const char *name, intptr_t value) { 189 oop valueOop = (oop) value; 190 tty->print("%s = ", name); 191 if (valueOop->is_oop(true)) 192 valueOop->print_on(tty); 193 else if (value >= ' ' && value <= '~') 194 tty->print("'%c' (%d)", value, value); 195 else 196 tty->print("%p", value); 197 tty->print_cr(""); 198} 199 200bool SharkRuntime::is_subtype_of(Klass* check_klass, Klass* object_klass) { 201 return object_klass->is_subtype_of(check_klass); 202} 203 204int SharkRuntime::uncommon_trap(JavaThread* thread, int trap_request) { 205 Thread *THREAD = thread; 206 207 // In C2, uncommon_trap_blob creates a frame, so all the various 208 // deoptimization functions expect to find the frame of the method 209 // being deopted one frame down on the stack. We create a dummy 210 // frame to mirror this. 211 FakeStubFrame *stubframe = FakeStubFrame::build(CHECK_0); 212 thread->push_zero_frame(stubframe); 213 214 // Initiate the trap 215 thread->set_last_Java_frame(); 216 Deoptimization::UnrollBlock *urb = 217 Deoptimization::uncommon_trap(thread, trap_request, Deoptimization::Unpack_uncommon_trap); 218 thread->reset_last_Java_frame(); 219 assert(urb->unpack_kind() == Deoptimization::Unpack_uncommon_trap, "expected Unpack_uncommon_trap"); 220 221 // Pop our dummy frame and the frame being deoptimized 222 thread->pop_zero_frame(); 223 thread->pop_zero_frame(); 224 225 // Push skeleton frames 226 int number_of_frames = urb->number_of_frames(); 227 for (int i = 0; i < number_of_frames; i++) { 228 intptr_t size = urb->frame_sizes()[i]; 229 InterpreterFrame *frame = InterpreterFrame::build(size, CHECK_0); 230 thread->push_zero_frame(frame); 231 } 232 233 // Push another dummy frame 234 stubframe = FakeStubFrame::build(CHECK_0); 235 thread->push_zero_frame(stubframe); 236 237 // Fill in the skeleton frames 238 thread->set_last_Java_frame(); 239 Deoptimization::unpack_frames(thread, Deoptimization::Unpack_uncommon_trap); 240 thread->reset_last_Java_frame(); 241 242 // Pop our dummy frame 243 thread->pop_zero_frame(); 244 245 // Fall back into the interpreter 246 return number_of_frames; 247} 248 249FakeStubFrame* FakeStubFrame::build(TRAPS) { 250 ZeroStack *stack = ((JavaThread *) THREAD)->zero_stack(); 251 stack->overflow_check(header_words, CHECK_NULL); 252 253 stack->push(0); // next_frame, filled in later 254 intptr_t *fp = stack->sp(); 255 assert(fp - stack->sp() == next_frame_off, "should be"); 256 257 stack->push(FAKE_STUB_FRAME); 258 assert(fp - stack->sp() == frame_type_off, "should be"); 259 260 return (FakeStubFrame *) fp; 261} 262