Wed, 27 Apr 2016 01:25:04 +0800
Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/
changeset: 6782:28b50d07f6f8
tag: jdk8u25-b17
aoqi@0 | 1 | /* |
aoqi@0 | 2 | * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. |
aoqi@0 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
aoqi@0 | 4 | * |
aoqi@0 | 5 | * This code is free software; you can redistribute it and/or modify it |
aoqi@0 | 6 | * under the terms of the GNU General Public License version 2 only, as |
aoqi@0 | 7 | * published by the Free Software Foundation. |
aoqi@0 | 8 | * |
aoqi@0 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
aoqi@0 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
aoqi@0 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
aoqi@0 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
aoqi@0 | 13 | * accompanied this code). |
aoqi@0 | 14 | * |
aoqi@0 | 15 | * You should have received a copy of the GNU General Public License version |
aoqi@0 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
aoqi@0 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
aoqi@0 | 18 | * |
aoqi@0 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
aoqi@0 | 20 | * or visit www.oracle.com if you need additional information or have any |
aoqi@0 | 21 | * questions. |
aoqi@0 | 22 | * |
aoqi@0 | 23 | */ |
aoqi@0 | 24 | |
aoqi@0 | 25 | // no precompiled headers |
aoqi@0 | 26 | #include "asm/macroAssembler.hpp" |
aoqi@0 | 27 | #include "classfile/classLoader.hpp" |
aoqi@0 | 28 | #include "classfile/systemDictionary.hpp" |
aoqi@0 | 29 | #include "classfile/vmSymbols.hpp" |
aoqi@0 | 30 | #include "code/icBuffer.hpp" |
aoqi@0 | 31 | #include "code/vtableStubs.hpp" |
aoqi@0 | 32 | #include "interpreter/interpreter.hpp" |
aoqi@0 | 33 | #include "jvm_solaris.h" |
aoqi@0 | 34 | #include "memory/allocation.inline.hpp" |
aoqi@0 | 35 | #include "mutex_solaris.inline.hpp" |
aoqi@0 | 36 | #include "nativeInst_sparc.hpp" |
aoqi@0 | 37 | #include "os_share_solaris.hpp" |
aoqi@0 | 38 | #include "prims/jniFastGetField.hpp" |
aoqi@0 | 39 | #include "prims/jvm.h" |
aoqi@0 | 40 | #include "prims/jvm_misc.hpp" |
aoqi@0 | 41 | #include "runtime/arguments.hpp" |
aoqi@0 | 42 | #include "runtime/extendedPC.hpp" |
aoqi@0 | 43 | #include "runtime/frame.inline.hpp" |
aoqi@0 | 44 | #include "runtime/interfaceSupport.hpp" |
aoqi@0 | 45 | #include "runtime/java.hpp" |
aoqi@0 | 46 | #include "runtime/javaCalls.hpp" |
aoqi@0 | 47 | #include "runtime/mutexLocker.hpp" |
aoqi@0 | 48 | #include "runtime/osThread.hpp" |
aoqi@0 | 49 | #include "runtime/sharedRuntime.hpp" |
aoqi@0 | 50 | #include "runtime/stubRoutines.hpp" |
aoqi@0 | 51 | #include "runtime/thread.inline.hpp" |
aoqi@0 | 52 | #include "runtime/timer.hpp" |
aoqi@0 | 53 | #include "utilities/events.hpp" |
aoqi@0 | 54 | #include "utilities/vmError.hpp" |
aoqi@0 | 55 | |
aoqi@0 | 56 | # include <signal.h> // needed first to avoid name collision for "std" with SC 5.0 |
aoqi@0 | 57 | |
aoqi@0 | 58 | // put OS-includes here |
aoqi@0 | 59 | # include <sys/types.h> |
aoqi@0 | 60 | # include <sys/mman.h> |
aoqi@0 | 61 | # include <pthread.h> |
aoqi@0 | 62 | # include <errno.h> |
aoqi@0 | 63 | # include <dlfcn.h> |
aoqi@0 | 64 | # include <stdio.h> |
aoqi@0 | 65 | # include <unistd.h> |
aoqi@0 | 66 | # include <sys/resource.h> |
aoqi@0 | 67 | # include <thread.h> |
aoqi@0 | 68 | # include <sys/stat.h> |
aoqi@0 | 69 | # include <sys/time.h> |
aoqi@0 | 70 | # include <sys/filio.h> |
aoqi@0 | 71 | # include <sys/utsname.h> |
aoqi@0 | 72 | # include <sys/systeminfo.h> |
aoqi@0 | 73 | # include <sys/socket.h> |
aoqi@0 | 74 | # include <sys/lwp.h> |
aoqi@0 | 75 | # include <pwd.h> |
aoqi@0 | 76 | # include <poll.h> |
aoqi@0 | 77 | # include <sys/lwp.h> |
aoqi@0 | 78 | |
aoqi@0 | 79 | # define _STRUCTURED_PROC 1 // this gets us the new structured proc interfaces of 5.6 & later |
aoqi@0 | 80 | # include <sys/procfs.h> // see comment in <sys/procfs.h> |
aoqi@0 | 81 | |
aoqi@0 | 82 | #define MAX_PATH (2 * K) |
aoqi@0 | 83 | |
aoqi@0 | 84 | // Minimum stack size for the VM. It's easier to document a constant |
aoqi@0 | 85 | // but it's different for x86 and sparc because the page sizes are different. |
aoqi@0 | 86 | #ifdef _LP64 |
aoqi@0 | 87 | size_t os::Solaris::min_stack_allowed = 128*K; |
aoqi@0 | 88 | #else |
aoqi@0 | 89 | size_t os::Solaris::min_stack_allowed = 96*K; |
aoqi@0 | 90 | #endif |
aoqi@0 | 91 | |
aoqi@0 | 92 | int os::Solaris::max_register_window_saves_before_flushing() { |
aoqi@0 | 93 | // We should detect this at run time. For now, filling |
aoqi@0 | 94 | // in with a constant. |
aoqi@0 | 95 | return 8; |
aoqi@0 | 96 | } |
aoqi@0 | 97 | |
aoqi@0 | 98 | static void handle_unflushed_register_windows(gwindows_t *win) { |
aoqi@0 | 99 | int restore_count = win->wbcnt; |
aoqi@0 | 100 | int i; |
aoqi@0 | 101 | |
aoqi@0 | 102 | for(i=0; i<restore_count; i++) { |
aoqi@0 | 103 | address sp = ((address)win->spbuf[i]) + STACK_BIAS; |
aoqi@0 | 104 | address reg_win = (address)&win->wbuf[i]; |
aoqi@0 | 105 | memcpy(sp,reg_win,sizeof(struct rwindow)); |
aoqi@0 | 106 | } |
aoqi@0 | 107 | } |
aoqi@0 | 108 | |
aoqi@0 | 109 | char* os::non_memory_address_word() { |
aoqi@0 | 110 | // Must never look like an address returned by reserve_memory, |
aoqi@0 | 111 | // even in its subfields (as defined by the CPU immediate fields, |
aoqi@0 | 112 | // if the CPU splits constants across multiple instructions). |
aoqi@0 | 113 | // On SPARC, 0 != %hi(any real address), because there is no |
aoqi@0 | 114 | // allocation in the first 1Kb of the virtual address space. |
aoqi@0 | 115 | return (char*) 0; |
aoqi@0 | 116 | } |
aoqi@0 | 117 | |
aoqi@0 | 118 | // Validate a ucontext retrieved from walking a uc_link of a ucontext. |
aoqi@0 | 119 | // There are issues with libthread giving out uc_links for different threads |
aoqi@0 | 120 | // on the same uc_link chain and bad or circular links. |
aoqi@0 | 121 | // |
aoqi@0 | 122 | bool os::Solaris::valid_ucontext(Thread* thread, ucontext_t* valid, ucontext_t* suspect) { |
aoqi@0 | 123 | if (valid >= suspect || |
aoqi@0 | 124 | valid->uc_stack.ss_flags != suspect->uc_stack.ss_flags || |
aoqi@0 | 125 | valid->uc_stack.ss_sp != suspect->uc_stack.ss_sp || |
aoqi@0 | 126 | valid->uc_stack.ss_size != suspect->uc_stack.ss_size) { |
aoqi@0 | 127 | DEBUG_ONLY(tty->print_cr("valid_ucontext: failed test 1");) |
aoqi@0 | 128 | return false; |
aoqi@0 | 129 | } |
aoqi@0 | 130 | |
aoqi@0 | 131 | if (thread->is_Java_thread()) { |
aoqi@0 | 132 | if (!valid_stack_address(thread, (address)suspect)) { |
aoqi@0 | 133 | DEBUG_ONLY(tty->print_cr("valid_ucontext: uc_link not in thread stack");) |
aoqi@0 | 134 | return false; |
aoqi@0 | 135 | } |
aoqi@0 | 136 | address _sp = (address)((intptr_t)suspect->uc_mcontext.gregs[REG_SP] + STACK_BIAS); |
aoqi@0 | 137 | if (!valid_stack_address(thread, _sp) || |
aoqi@0 | 138 | !frame::is_valid_stack_pointer(((JavaThread*)thread)->base_of_stack_pointer(), (intptr_t*)_sp)) { |
aoqi@0 | 139 | DEBUG_ONLY(tty->print_cr("valid_ucontext: stackpointer not in thread stack");) |
aoqi@0 | 140 | return false; |
aoqi@0 | 141 | } |
aoqi@0 | 142 | } |
aoqi@0 | 143 | return true; |
aoqi@0 | 144 | } |
aoqi@0 | 145 | |
aoqi@0 | 146 | // We will only follow one level of uc_link since there are libthread |
aoqi@0 | 147 | // issues with ucontext linking and it is better to be safe and just |
aoqi@0 | 148 | // let caller retry later. |
aoqi@0 | 149 | ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread, |
aoqi@0 | 150 | ucontext_t *uc) { |
aoqi@0 | 151 | |
aoqi@0 | 152 | ucontext_t *retuc = NULL; |
aoqi@0 | 153 | |
aoqi@0 | 154 | // Sometimes the topmost register windows are not properly flushed. |
aoqi@0 | 155 | // i.e., if the kernel would have needed to take a page fault |
aoqi@0 | 156 | if (uc != NULL && uc->uc_mcontext.gwins != NULL) { |
aoqi@0 | 157 | ::handle_unflushed_register_windows(uc->uc_mcontext.gwins); |
aoqi@0 | 158 | } |
aoqi@0 | 159 | |
aoqi@0 | 160 | if (uc != NULL) { |
aoqi@0 | 161 | if (uc->uc_link == NULL) { |
aoqi@0 | 162 | // cannot validate without uc_link so accept current ucontext |
aoqi@0 | 163 | retuc = uc; |
aoqi@0 | 164 | } else if (os::Solaris::valid_ucontext(thread, uc, uc->uc_link)) { |
aoqi@0 | 165 | // first ucontext is valid so try the next one |
aoqi@0 | 166 | uc = uc->uc_link; |
aoqi@0 | 167 | if (uc->uc_link == NULL) { |
aoqi@0 | 168 | // cannot validate without uc_link so accept current ucontext |
aoqi@0 | 169 | retuc = uc; |
aoqi@0 | 170 | } else if (os::Solaris::valid_ucontext(thread, uc, uc->uc_link)) { |
aoqi@0 | 171 | // the ucontext one level down is also valid so return it |
aoqi@0 | 172 | retuc = uc; |
aoqi@0 | 173 | } |
aoqi@0 | 174 | } |
aoqi@0 | 175 | } |
aoqi@0 | 176 | return retuc; |
aoqi@0 | 177 | } |
aoqi@0 | 178 | |
aoqi@0 | 179 | // Assumes ucontext is valid |
aoqi@0 | 180 | ExtendedPC os::Solaris::ucontext_get_ExtendedPC(ucontext_t *uc) { |
aoqi@0 | 181 | address pc = (address)uc->uc_mcontext.gregs[REG_PC]; |
aoqi@0 | 182 | // set npc to zero to avoid using it for safepoint, good for profiling only |
aoqi@0 | 183 | return ExtendedPC(pc); |
aoqi@0 | 184 | } |
aoqi@0 | 185 | |
aoqi@0 | 186 | // Assumes ucontext is valid |
aoqi@0 | 187 | intptr_t* os::Solaris::ucontext_get_sp(ucontext_t *uc) { |
aoqi@0 | 188 | return (intptr_t*)((intptr_t)uc->uc_mcontext.gregs[REG_SP] + STACK_BIAS); |
aoqi@0 | 189 | } |
aoqi@0 | 190 | |
aoqi@0 | 191 | // Solaris X86 only |
aoqi@0 | 192 | intptr_t* os::Solaris::ucontext_get_fp(ucontext_t *uc) { |
aoqi@0 | 193 | ShouldNotReachHere(); |
aoqi@0 | 194 | return NULL; |
aoqi@0 | 195 | } |
aoqi@0 | 196 | |
aoqi@0 | 197 | address os::Solaris::ucontext_get_pc(ucontext_t *uc) { |
aoqi@0 | 198 | return (address) uc->uc_mcontext.gregs[REG_PC]; |
aoqi@0 | 199 | } |
aoqi@0 | 200 | |
aoqi@0 | 201 | |
aoqi@0 | 202 | // For Forte Analyzer AsyncGetCallTrace profiling support - thread |
aoqi@0 | 203 | // is currently interrupted by SIGPROF. |
aoqi@0 | 204 | // |
aoqi@0 | 205 | // ret_fp parameter is only used by Solaris X86. |
aoqi@0 | 206 | // |
aoqi@0 | 207 | // The difference between this and os::fetch_frame_from_context() is that |
aoqi@0 | 208 | // here we try to skip nested signal frames. |
aoqi@0 | 209 | ExtendedPC os::Solaris::fetch_frame_from_ucontext(Thread* thread, |
aoqi@0 | 210 | ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) { |
aoqi@0 | 211 | |
aoqi@0 | 212 | assert(thread != NULL, "just checking"); |
aoqi@0 | 213 | assert(ret_sp != NULL, "just checking"); |
aoqi@0 | 214 | assert(ret_fp == NULL, "just checking"); |
aoqi@0 | 215 | |
aoqi@0 | 216 | ucontext_t *luc = os::Solaris::get_valid_uc_in_signal_handler(thread, uc); |
aoqi@0 | 217 | |
aoqi@0 | 218 | return os::fetch_frame_from_context(luc, ret_sp, ret_fp); |
aoqi@0 | 219 | } |
aoqi@0 | 220 | |
aoqi@0 | 221 | |
aoqi@0 | 222 | // ret_fp parameter is only used by Solaris X86. |
aoqi@0 | 223 | ExtendedPC os::fetch_frame_from_context(void* ucVoid, |
aoqi@0 | 224 | intptr_t** ret_sp, intptr_t** ret_fp) { |
aoqi@0 | 225 | |
aoqi@0 | 226 | ExtendedPC epc; |
aoqi@0 | 227 | ucontext_t *uc = (ucontext_t*)ucVoid; |
aoqi@0 | 228 | |
aoqi@0 | 229 | if (uc != NULL) { |
aoqi@0 | 230 | epc = os::Solaris::ucontext_get_ExtendedPC(uc); |
aoqi@0 | 231 | if (ret_sp) *ret_sp = os::Solaris::ucontext_get_sp(uc); |
aoqi@0 | 232 | } else { |
aoqi@0 | 233 | // construct empty ExtendedPC for return value checking |
aoqi@0 | 234 | epc = ExtendedPC(NULL); |
aoqi@0 | 235 | if (ret_sp) *ret_sp = (intptr_t *)NULL; |
aoqi@0 | 236 | } |
aoqi@0 | 237 | |
aoqi@0 | 238 | return epc; |
aoqi@0 | 239 | } |
aoqi@0 | 240 | |
aoqi@0 | 241 | frame os::fetch_frame_from_context(void* ucVoid) { |
aoqi@0 | 242 | intptr_t* sp; |
aoqi@0 | 243 | intptr_t* fp; |
aoqi@0 | 244 | ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); |
aoqi@0 | 245 | return frame(sp, frame::unpatchable, epc.pc()); |
aoqi@0 | 246 | } |
aoqi@0 | 247 | |
aoqi@0 | 248 | frame os::get_sender_for_C_frame(frame* fr) { |
aoqi@0 | 249 | return frame(fr->sender_sp(), frame::unpatchable, fr->sender_pc()); |
aoqi@0 | 250 | } |
aoqi@0 | 251 | |
aoqi@0 | 252 | // Returns an estimate of the current stack pointer. Result must be guaranteed to |
aoqi@0 | 253 | // point into the calling threads stack, and be no lower than the current stack |
aoqi@0 | 254 | // pointer. |
aoqi@0 | 255 | address os::current_stack_pointer() { |
aoqi@0 | 256 | volatile int dummy; |
aoqi@0 | 257 | address sp = (address)&dummy + 8; // %%%% need to confirm if this is right |
aoqi@0 | 258 | return sp; |
aoqi@0 | 259 | } |
aoqi@0 | 260 | |
aoqi@0 | 261 | frame os::current_frame() { |
aoqi@0 | 262 | intptr_t* sp = StubRoutines::Sparc::flush_callers_register_windows_func()(); |
aoqi@0 | 263 | frame myframe(sp, frame::unpatchable, |
aoqi@0 | 264 | CAST_FROM_FN_PTR(address, os::current_frame)); |
aoqi@0 | 265 | if (os::is_first_C_frame(&myframe)) { |
aoqi@0 | 266 | // stack is not walkable |
aoqi@0 | 267 | return frame(NULL, NULL, NULL); |
aoqi@0 | 268 | } else { |
aoqi@0 | 269 | return os::get_sender_for_C_frame(&myframe); |
aoqi@0 | 270 | } |
aoqi@0 | 271 | } |
aoqi@0 | 272 | |
aoqi@0 | 273 | static int threadgetstate(thread_t tid, int *flags, lwpid_t *lwp, stack_t *ss, gregset_t rs, lwpstatus_t *lwpstatus) { |
aoqi@0 | 274 | char lwpstatusfile[PROCFILE_LENGTH]; |
aoqi@0 | 275 | int lwpfd, err; |
aoqi@0 | 276 | |
aoqi@0 | 277 | if (err = os::Solaris::thr_getstate(tid, flags, lwp, ss, rs)) |
aoqi@0 | 278 | return (err); |
aoqi@0 | 279 | if (*flags == TRS_LWPID) { |
aoqi@0 | 280 | sprintf(lwpstatusfile, "/proc/%d/lwp/%d/lwpstatus", getpid(), |
aoqi@0 | 281 | *lwp); |
aoqi@0 | 282 | if ((lwpfd = ::open(lwpstatusfile, O_RDONLY)) < 0) { |
aoqi@0 | 283 | perror("thr_mutator_status: open lwpstatus"); |
aoqi@0 | 284 | return (EINVAL); |
aoqi@0 | 285 | } |
aoqi@0 | 286 | if (pread(lwpfd, lwpstatus, sizeof (lwpstatus_t), (off_t)0) != |
aoqi@0 | 287 | sizeof (lwpstatus_t)) { |
aoqi@0 | 288 | perror("thr_mutator_status: read lwpstatus"); |
aoqi@0 | 289 | (void) ::close(lwpfd); |
aoqi@0 | 290 | return (EINVAL); |
aoqi@0 | 291 | } |
aoqi@0 | 292 | (void) ::close(lwpfd); |
aoqi@0 | 293 | } |
aoqi@0 | 294 | return (0); |
aoqi@0 | 295 | } |
aoqi@0 | 296 | |
aoqi@0 | 297 | |
aoqi@0 | 298 | bool os::is_allocatable(size_t bytes) { |
aoqi@0 | 299 | #ifdef _LP64 |
aoqi@0 | 300 | return true; |
aoqi@0 | 301 | #else |
aoqi@0 | 302 | return (bytes <= (size_t)3835*M); |
aoqi@0 | 303 | #endif |
aoqi@0 | 304 | } |
aoqi@0 | 305 | |
aoqi@0 | 306 | extern "C" JNIEXPORT int |
aoqi@0 | 307 | JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, |
aoqi@0 | 308 | int abort_if_unrecognized) { |
aoqi@0 | 309 | ucontext_t* uc = (ucontext_t*) ucVoid; |
aoqi@0 | 310 | |
aoqi@0 | 311 | Thread* t = ThreadLocalStorage::get_thread_slow(); |
aoqi@0 | 312 | |
aoqi@0 | 313 | // Must do this before SignalHandlerMark, if crash protection installed we will longjmp away |
aoqi@0 | 314 | // (no destructors can be run) |
aoqi@0 | 315 | os::WatcherThreadCrashProtection::check_crash_protection(sig, t); |
aoqi@0 | 316 | |
aoqi@0 | 317 | SignalHandlerMark shm(t); |
aoqi@0 | 318 | |
aoqi@0 | 319 | if(sig == SIGPIPE || sig == SIGXFSZ) { |
aoqi@0 | 320 | if (os::Solaris::chained_handler(sig, info, ucVoid)) { |
aoqi@0 | 321 | return true; |
aoqi@0 | 322 | } else { |
aoqi@0 | 323 | if (PrintMiscellaneous && (WizardMode || Verbose)) { |
aoqi@0 | 324 | char buf[64]; |
aoqi@0 | 325 | warning("Ignoring %s - see 4229104 or 6499219", |
aoqi@0 | 326 | os::exception_name(sig, buf, sizeof(buf))); |
aoqi@0 | 327 | |
aoqi@0 | 328 | } |
aoqi@0 | 329 | return true; |
aoqi@0 | 330 | } |
aoqi@0 | 331 | } |
aoqi@0 | 332 | |
aoqi@0 | 333 | JavaThread* thread = NULL; |
aoqi@0 | 334 | VMThread* vmthread = NULL; |
aoqi@0 | 335 | if (os::Solaris::signal_handlers_are_installed) { |
aoqi@0 | 336 | if (t != NULL ){ |
aoqi@0 | 337 | if(t->is_Java_thread()) { |
aoqi@0 | 338 | thread = (JavaThread*)t; |
aoqi@0 | 339 | } |
aoqi@0 | 340 | else if(t->is_VM_thread()){ |
aoqi@0 | 341 | vmthread = (VMThread *)t; |
aoqi@0 | 342 | } |
aoqi@0 | 343 | } |
aoqi@0 | 344 | } |
aoqi@0 | 345 | |
aoqi@0 | 346 | guarantee(sig != os::Solaris::SIGinterrupt(), "Can not chain VM interrupt signal, try -XX:+UseAltSigs"); |
aoqi@0 | 347 | |
aoqi@0 | 348 | if (sig == os::Solaris::SIGasync()) { |
aoqi@0 | 349 | if (thread || vmthread) { |
aoqi@0 | 350 | OSThread::SR_handler(t, uc); |
aoqi@0 | 351 | return true; |
aoqi@0 | 352 | } else if (os::Solaris::chained_handler(sig, info, ucVoid)) { |
aoqi@0 | 353 | return true; |
aoqi@0 | 354 | } else { |
aoqi@0 | 355 | // If os::Solaris::SIGasync not chained, and this is a non-vm and |
aoqi@0 | 356 | // non-java thread |
aoqi@0 | 357 | return true; |
aoqi@0 | 358 | } |
aoqi@0 | 359 | } |
aoqi@0 | 360 | |
aoqi@0 | 361 | if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) { |
aoqi@0 | 362 | // can't decode this kind of signal |
aoqi@0 | 363 | info = NULL; |
aoqi@0 | 364 | } else { |
aoqi@0 | 365 | assert(sig == info->si_signo, "bad siginfo"); |
aoqi@0 | 366 | } |
aoqi@0 | 367 | |
aoqi@0 | 368 | // decide if this trap can be handled by a stub |
aoqi@0 | 369 | address stub = NULL; |
aoqi@0 | 370 | |
aoqi@0 | 371 | address pc = NULL; |
aoqi@0 | 372 | address npc = NULL; |
aoqi@0 | 373 | |
aoqi@0 | 374 | //%note os_trap_1 |
aoqi@0 | 375 | if (info != NULL && uc != NULL && thread != NULL) { |
aoqi@0 | 376 | // factor me: getPCfromContext |
aoqi@0 | 377 | pc = (address) uc->uc_mcontext.gregs[REG_PC]; |
aoqi@0 | 378 | npc = (address) uc->uc_mcontext.gregs[REG_nPC]; |
aoqi@0 | 379 | |
aoqi@0 | 380 | // SafeFetch() support |
aoqi@0 | 381 | if (StubRoutines::is_safefetch_fault(pc)) { |
aoqi@0 | 382 | uc->uc_mcontext.gregs[REG_PC] = intptr_t(StubRoutines::continuation_for_safefetch_fault(pc)); |
aoqi@0 | 383 | uc->uc_mcontext.gregs[REG_nPC] = uc->uc_mcontext.gregs[REG_PC] + 4; |
aoqi@0 | 384 | return 1; |
aoqi@0 | 385 | } |
aoqi@0 | 386 | |
aoqi@0 | 387 | // Handle ALL stack overflow variations here |
aoqi@0 | 388 | if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) { |
aoqi@0 | 389 | address addr = (address) info->si_addr; |
aoqi@0 | 390 | if (thread->in_stack_yellow_zone(addr)) { |
aoqi@0 | 391 | thread->disable_stack_yellow_zone(); |
aoqi@0 | 392 | // Sometimes the register windows are not properly flushed. |
aoqi@0 | 393 | if(uc->uc_mcontext.gwins != NULL) { |
aoqi@0 | 394 | ::handle_unflushed_register_windows(uc->uc_mcontext.gwins); |
aoqi@0 | 395 | } |
aoqi@0 | 396 | if (thread->thread_state() == _thread_in_Java) { |
aoqi@0 | 397 | // Throw a stack overflow exception. Guard pages will be reenabled |
aoqi@0 | 398 | // while unwinding the stack. |
aoqi@0 | 399 | stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW); |
aoqi@0 | 400 | } else { |
aoqi@0 | 401 | // Thread was in the vm or native code. Return and try to finish. |
aoqi@0 | 402 | return true; |
aoqi@0 | 403 | } |
aoqi@0 | 404 | } else if (thread->in_stack_red_zone(addr)) { |
aoqi@0 | 405 | // Fatal red zone violation. Disable the guard pages and fall through |
aoqi@0 | 406 | // to handle_unexpected_exception way down below. |
aoqi@0 | 407 | thread->disable_stack_red_zone(); |
aoqi@0 | 408 | tty->print_raw_cr("An irrecoverable stack overflow has occurred."); |
aoqi@0 | 409 | // Sometimes the register windows are not properly flushed. |
aoqi@0 | 410 | if(uc->uc_mcontext.gwins != NULL) { |
aoqi@0 | 411 | ::handle_unflushed_register_windows(uc->uc_mcontext.gwins); |
aoqi@0 | 412 | } |
aoqi@0 | 413 | } |
aoqi@0 | 414 | } |
aoqi@0 | 415 | |
aoqi@0 | 416 | |
aoqi@0 | 417 | if (thread->thread_state() == _thread_in_vm) { |
aoqi@0 | 418 | if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) { |
aoqi@0 | 419 | stub = StubRoutines::handler_for_unsafe_access(); |
aoqi@0 | 420 | } |
aoqi@0 | 421 | } |
aoqi@0 | 422 | |
aoqi@0 | 423 | else if (thread->thread_state() == _thread_in_Java) { |
aoqi@0 | 424 | // Java thread running in Java code => find exception handler if any |
aoqi@0 | 425 | // a fault inside compiled code, the interpreter, or a stub |
aoqi@0 | 426 | |
aoqi@0 | 427 | // Support Safepoint Polling |
aoqi@0 | 428 | if ( sig == SIGSEGV && (address)info->si_addr == os::get_polling_page() ) { |
aoqi@0 | 429 | stub = SharedRuntime::get_poll_stub(pc); |
aoqi@0 | 430 | } |
aoqi@0 | 431 | |
aoqi@0 | 432 | // Not needed on x86 solaris because verify_oops doesn't generate |
aoqi@0 | 433 | // SEGV/BUS like sparc does. |
aoqi@0 | 434 | if ( (sig == SIGSEGV || sig == SIGBUS) |
aoqi@0 | 435 | && pc >= MacroAssembler::_verify_oop_implicit_branch[0] |
aoqi@0 | 436 | && pc < MacroAssembler::_verify_oop_implicit_branch[1] ) { |
aoqi@0 | 437 | stub = MacroAssembler::_verify_oop_implicit_branch[2]; |
aoqi@0 | 438 | warning("fixed up memory fault in +VerifyOops at address " INTPTR_FORMAT, info->si_addr); |
aoqi@0 | 439 | } |
aoqi@0 | 440 | |
aoqi@0 | 441 | // This is not factored because on x86 solaris the patching for |
aoqi@0 | 442 | // zombies does not generate a SEGV. |
aoqi@0 | 443 | else if (sig == SIGSEGV && nativeInstruction_at(pc)->is_zombie()) { |
aoqi@0 | 444 | // zombie method (ld [%g0],%o7 instruction) |
aoqi@0 | 445 | stub = SharedRuntime::get_handle_wrong_method_stub(); |
aoqi@0 | 446 | |
aoqi@0 | 447 | // At the stub it needs to look like a call from the caller of this |
aoqi@0 | 448 | // method (not a call from the segv site). |
aoqi@0 | 449 | pc = (address)uc->uc_mcontext.gregs[REG_O7]; |
aoqi@0 | 450 | } |
aoqi@0 | 451 | else if (sig == SIGBUS && info->si_code == BUS_OBJERR) { |
aoqi@0 | 452 | // BugId 4454115: A read from a MappedByteBuffer can fault |
aoqi@0 | 453 | // here if the underlying file has been truncated. |
aoqi@0 | 454 | // Do not crash the VM in such a case. |
aoqi@0 | 455 | CodeBlob* cb = CodeCache::find_blob_unsafe(pc); |
aoqi@0 | 456 | nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL; |
aoqi@0 | 457 | if (nm != NULL && nm->has_unsafe_access()) { |
aoqi@0 | 458 | stub = StubRoutines::handler_for_unsafe_access(); |
aoqi@0 | 459 | } |
aoqi@0 | 460 | } |
aoqi@0 | 461 | |
aoqi@0 | 462 | else if (sig == SIGFPE && info->si_code == FPE_INTDIV) { |
aoqi@0 | 463 | // integer divide by zero |
aoqi@0 | 464 | stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO); |
aoqi@0 | 465 | } |
aoqi@0 | 466 | else if (sig == SIGFPE && info->si_code == FPE_FLTDIV) { |
aoqi@0 | 467 | // floating-point divide by zero |
aoqi@0 | 468 | stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO); |
aoqi@0 | 469 | } |
aoqi@0 | 470 | #ifdef COMPILER2 |
aoqi@0 | 471 | else if (sig == SIGILL && nativeInstruction_at(pc)->is_ic_miss_trap()) { |
aoqi@0 | 472 | #ifdef ASSERT |
aoqi@0 | 473 | #ifdef TIERED |
aoqi@0 | 474 | CodeBlob* cb = CodeCache::find_blob_unsafe(pc); |
aoqi@0 | 475 | assert(cb->is_compiled_by_c2(), "Wrong compiler"); |
aoqi@0 | 476 | #endif // TIERED |
aoqi@0 | 477 | #endif // ASSERT |
aoqi@0 | 478 | // Inline cache missed and user trap "Tne G0+ST_RESERVED_FOR_USER_0+2" taken. |
aoqi@0 | 479 | stub = SharedRuntime::get_ic_miss_stub(); |
aoqi@0 | 480 | // At the stub it needs to look like a call from the caller of this |
aoqi@0 | 481 | // method (not a call from the segv site). |
aoqi@0 | 482 | pc = (address)uc->uc_mcontext.gregs[REG_O7]; |
aoqi@0 | 483 | } |
aoqi@0 | 484 | #endif // COMPILER2 |
aoqi@0 | 485 | |
aoqi@0 | 486 | else if (sig == SIGSEGV && info->si_code > 0 && !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) { |
aoqi@0 | 487 | // Determination of interpreter/vtable stub/compiled code null exception |
aoqi@0 | 488 | stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); |
aoqi@0 | 489 | } |
aoqi@0 | 490 | } |
aoqi@0 | 491 | |
aoqi@0 | 492 | // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in |
aoqi@0 | 493 | // and the heap gets shrunk before the field access. |
aoqi@0 | 494 | if ((sig == SIGSEGV) || (sig == SIGBUS)) { |
aoqi@0 | 495 | address addr = JNI_FastGetField::find_slowcase_pc(pc); |
aoqi@0 | 496 | if (addr != (address)-1) { |
aoqi@0 | 497 | stub = addr; |
aoqi@0 | 498 | } |
aoqi@0 | 499 | } |
aoqi@0 | 500 | |
aoqi@0 | 501 | // Check to see if we caught the safepoint code in the |
aoqi@0 | 502 | // process of write protecting the memory serialization page. |
aoqi@0 | 503 | // It write enables the page immediately after protecting it |
aoqi@0 | 504 | // so just return. |
aoqi@0 | 505 | if ((sig == SIGSEGV) && |
aoqi@0 | 506 | os::is_memory_serialize_page(thread, (address)info->si_addr)) { |
aoqi@0 | 507 | // Block current thread until the memory serialize page permission restored. |
aoqi@0 | 508 | os::block_on_serialize_page_trap(); |
aoqi@0 | 509 | return true; |
aoqi@0 | 510 | } |
aoqi@0 | 511 | } |
aoqi@0 | 512 | |
aoqi@0 | 513 | if (stub != NULL) { |
aoqi@0 | 514 | // save all thread context in case we need to restore it |
aoqi@0 | 515 | |
aoqi@0 | 516 | thread->set_saved_exception_pc(pc); |
aoqi@0 | 517 | thread->set_saved_exception_npc(npc); |
aoqi@0 | 518 | |
aoqi@0 | 519 | // simulate a branch to the stub (a "call" in the safepoint stub case) |
aoqi@0 | 520 | // factor me: setPC |
aoqi@0 | 521 | uc->uc_mcontext.gregs[REG_PC ] = (greg_t)stub; |
aoqi@0 | 522 | uc->uc_mcontext.gregs[REG_nPC] = (greg_t)(stub + 4); |
aoqi@0 | 523 | |
aoqi@0 | 524 | #ifndef PRODUCT |
aoqi@0 | 525 | if (TraceJumps) thread->record_jump(stub, NULL, __FILE__, __LINE__); |
aoqi@0 | 526 | #endif /* PRODUCT */ |
aoqi@0 | 527 | |
aoqi@0 | 528 | return true; |
aoqi@0 | 529 | } |
aoqi@0 | 530 | |
aoqi@0 | 531 | // signal-chaining |
aoqi@0 | 532 | if (os::Solaris::chained_handler(sig, info, ucVoid)) { |
aoqi@0 | 533 | return true; |
aoqi@0 | 534 | } |
aoqi@0 | 535 | |
aoqi@0 | 536 | if (!abort_if_unrecognized) { |
aoqi@0 | 537 | // caller wants another chance, so give it to him |
aoqi@0 | 538 | return false; |
aoqi@0 | 539 | } |
aoqi@0 | 540 | |
aoqi@0 | 541 | if (!os::Solaris::libjsig_is_loaded) { |
aoqi@0 | 542 | struct sigaction oldAct; |
aoqi@0 | 543 | sigaction(sig, (struct sigaction *)0, &oldAct); |
aoqi@0 | 544 | if (oldAct.sa_sigaction != signalHandler) { |
aoqi@0 | 545 | void* sighand = oldAct.sa_sigaction ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction) |
aoqi@0 | 546 | : CAST_FROM_FN_PTR(void*, oldAct.sa_handler); |
aoqi@0 | 547 | warning("Unexpected Signal %d occurred under user-defined signal handler " INTPTR_FORMAT, sig, (intptr_t)sighand); |
aoqi@0 | 548 | } |
aoqi@0 | 549 | } |
aoqi@0 | 550 | |
aoqi@0 | 551 | if (pc == NULL && uc != NULL) { |
aoqi@0 | 552 | pc = (address) uc->uc_mcontext.gregs[REG_PC]; |
aoqi@0 | 553 | } |
aoqi@0 | 554 | |
aoqi@0 | 555 | // Sometimes the register windows are not properly flushed. |
aoqi@0 | 556 | if(uc->uc_mcontext.gwins != NULL) { |
aoqi@0 | 557 | ::handle_unflushed_register_windows(uc->uc_mcontext.gwins); |
aoqi@0 | 558 | } |
aoqi@0 | 559 | |
aoqi@0 | 560 | // unmask current signal |
aoqi@0 | 561 | sigset_t newset; |
aoqi@0 | 562 | sigemptyset(&newset); |
aoqi@0 | 563 | sigaddset(&newset, sig); |
aoqi@0 | 564 | sigprocmask(SIG_UNBLOCK, &newset, NULL); |
aoqi@0 | 565 | |
aoqi@0 | 566 | // Determine which sort of error to throw. Out of swap may signal |
aoqi@0 | 567 | // on the thread stack, which could get a mapping error when touched. |
aoqi@0 | 568 | address addr = (address) info->si_addr; |
aoqi@0 | 569 | if (sig == SIGBUS && info->si_code == BUS_OBJERR && info->si_errno == ENOMEM) { |
aoqi@0 | 570 | vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "Out of swap space to map in thread stack."); |
aoqi@0 | 571 | } |
aoqi@0 | 572 | |
aoqi@0 | 573 | VMError err(t, sig, pc, info, ucVoid); |
aoqi@0 | 574 | err.report_and_die(); |
aoqi@0 | 575 | |
aoqi@0 | 576 | ShouldNotReachHere(); |
aoqi@0 | 577 | } |
aoqi@0 | 578 | |
aoqi@0 | 579 | void os::print_context(outputStream *st, void *context) { |
aoqi@0 | 580 | if (context == NULL) return; |
aoqi@0 | 581 | |
aoqi@0 | 582 | ucontext_t *uc = (ucontext_t*)context; |
aoqi@0 | 583 | st->print_cr("Registers:"); |
aoqi@0 | 584 | |
aoqi@0 | 585 | st->print_cr(" G1=" INTPTR_FORMAT " G2=" INTPTR_FORMAT |
aoqi@0 | 586 | " G3=" INTPTR_FORMAT " G4=" INTPTR_FORMAT, |
aoqi@0 | 587 | uc->uc_mcontext.gregs[REG_G1], |
aoqi@0 | 588 | uc->uc_mcontext.gregs[REG_G2], |
aoqi@0 | 589 | uc->uc_mcontext.gregs[REG_G3], |
aoqi@0 | 590 | uc->uc_mcontext.gregs[REG_G4]); |
aoqi@0 | 591 | st->print_cr(" G5=" INTPTR_FORMAT " G6=" INTPTR_FORMAT |
aoqi@0 | 592 | " G7=" INTPTR_FORMAT " Y=" INTPTR_FORMAT, |
aoqi@0 | 593 | uc->uc_mcontext.gregs[REG_G5], |
aoqi@0 | 594 | uc->uc_mcontext.gregs[REG_G6], |
aoqi@0 | 595 | uc->uc_mcontext.gregs[REG_G7], |
aoqi@0 | 596 | uc->uc_mcontext.gregs[REG_Y]); |
aoqi@0 | 597 | st->print_cr(" O0=" INTPTR_FORMAT " O1=" INTPTR_FORMAT |
aoqi@0 | 598 | " O2=" INTPTR_FORMAT " O3=" INTPTR_FORMAT, |
aoqi@0 | 599 | uc->uc_mcontext.gregs[REG_O0], |
aoqi@0 | 600 | uc->uc_mcontext.gregs[REG_O1], |
aoqi@0 | 601 | uc->uc_mcontext.gregs[REG_O2], |
aoqi@0 | 602 | uc->uc_mcontext.gregs[REG_O3]); |
aoqi@0 | 603 | st->print_cr(" O4=" INTPTR_FORMAT " O5=" INTPTR_FORMAT |
aoqi@0 | 604 | " O6=" INTPTR_FORMAT " O7=" INTPTR_FORMAT, |
aoqi@0 | 605 | uc->uc_mcontext.gregs[REG_O4], |
aoqi@0 | 606 | uc->uc_mcontext.gregs[REG_O5], |
aoqi@0 | 607 | uc->uc_mcontext.gregs[REG_O6], |
aoqi@0 | 608 | uc->uc_mcontext.gregs[REG_O7]); |
aoqi@0 | 609 | |
aoqi@0 | 610 | |
aoqi@0 | 611 | intptr_t *sp = (intptr_t *)os::Solaris::ucontext_get_sp(uc); |
aoqi@0 | 612 | st->print_cr(" L0=" INTPTR_FORMAT " L1=" INTPTR_FORMAT |
aoqi@0 | 613 | " L2=" INTPTR_FORMAT " L3=" INTPTR_FORMAT, |
aoqi@0 | 614 | sp[L0->sp_offset_in_saved_window()], |
aoqi@0 | 615 | sp[L1->sp_offset_in_saved_window()], |
aoqi@0 | 616 | sp[L2->sp_offset_in_saved_window()], |
aoqi@0 | 617 | sp[L3->sp_offset_in_saved_window()]); |
aoqi@0 | 618 | st->print_cr(" L4=" INTPTR_FORMAT " L5=" INTPTR_FORMAT |
aoqi@0 | 619 | " L6=" INTPTR_FORMAT " L7=" INTPTR_FORMAT, |
aoqi@0 | 620 | sp[L4->sp_offset_in_saved_window()], |
aoqi@0 | 621 | sp[L5->sp_offset_in_saved_window()], |
aoqi@0 | 622 | sp[L6->sp_offset_in_saved_window()], |
aoqi@0 | 623 | sp[L7->sp_offset_in_saved_window()]); |
aoqi@0 | 624 | st->print_cr(" I0=" INTPTR_FORMAT " I1=" INTPTR_FORMAT |
aoqi@0 | 625 | " I2=" INTPTR_FORMAT " I3=" INTPTR_FORMAT, |
aoqi@0 | 626 | sp[I0->sp_offset_in_saved_window()], |
aoqi@0 | 627 | sp[I1->sp_offset_in_saved_window()], |
aoqi@0 | 628 | sp[I2->sp_offset_in_saved_window()], |
aoqi@0 | 629 | sp[I3->sp_offset_in_saved_window()]); |
aoqi@0 | 630 | st->print_cr(" I4=" INTPTR_FORMAT " I5=" INTPTR_FORMAT |
aoqi@0 | 631 | " I6=" INTPTR_FORMAT " I7=" INTPTR_FORMAT, |
aoqi@0 | 632 | sp[I4->sp_offset_in_saved_window()], |
aoqi@0 | 633 | sp[I5->sp_offset_in_saved_window()], |
aoqi@0 | 634 | sp[I6->sp_offset_in_saved_window()], |
aoqi@0 | 635 | sp[I7->sp_offset_in_saved_window()]); |
aoqi@0 | 636 | |
aoqi@0 | 637 | st->print_cr(" PC=" INTPTR_FORMAT " nPC=" INTPTR_FORMAT, |
aoqi@0 | 638 | uc->uc_mcontext.gregs[REG_PC], |
aoqi@0 | 639 | uc->uc_mcontext.gregs[REG_nPC]); |
aoqi@0 | 640 | st->cr(); |
aoqi@0 | 641 | st->cr(); |
aoqi@0 | 642 | |
aoqi@0 | 643 | st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp); |
aoqi@0 | 644 | print_hex_dump(st, (address)sp, (address)(sp + 32), sizeof(intptr_t)); |
aoqi@0 | 645 | st->cr(); |
aoqi@0 | 646 | |
aoqi@0 | 647 | // Note: it may be unsafe to inspect memory near pc. For example, pc may |
aoqi@0 | 648 | // point to garbage if entry point in an nmethod is corrupted. Leave |
aoqi@0 | 649 | // this at the end, and hope for the best. |
aoqi@0 | 650 | ExtendedPC epc = os::Solaris::ucontext_get_ExtendedPC(uc); |
aoqi@0 | 651 | address pc = epc.pc(); |
aoqi@0 | 652 | st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); |
aoqi@0 | 653 | print_hex_dump(st, pc - 32, pc + 32, sizeof(char)); |
aoqi@0 | 654 | } |
aoqi@0 | 655 | |
aoqi@0 | 656 | void os::print_register_info(outputStream *st, void *context) { |
aoqi@0 | 657 | if (context == NULL) return; |
aoqi@0 | 658 | |
aoqi@0 | 659 | ucontext_t *uc = (ucontext_t*)context; |
aoqi@0 | 660 | intptr_t *sp = (intptr_t *)os::Solaris::ucontext_get_sp(uc); |
aoqi@0 | 661 | |
aoqi@0 | 662 | st->print_cr("Register to memory mapping:"); |
aoqi@0 | 663 | st->cr(); |
aoqi@0 | 664 | |
aoqi@0 | 665 | // this is only for the "general purpose" registers |
aoqi@0 | 666 | st->print("G1="); print_location(st, uc->uc_mcontext.gregs[REG_G1]); |
aoqi@0 | 667 | st->print("G2="); print_location(st, uc->uc_mcontext.gregs[REG_G2]); |
aoqi@0 | 668 | st->print("G3="); print_location(st, uc->uc_mcontext.gregs[REG_G3]); |
aoqi@0 | 669 | st->print("G4="); print_location(st, uc->uc_mcontext.gregs[REG_G4]); |
aoqi@0 | 670 | st->print("G5="); print_location(st, uc->uc_mcontext.gregs[REG_G5]); |
aoqi@0 | 671 | st->print("G6="); print_location(st, uc->uc_mcontext.gregs[REG_G6]); |
aoqi@0 | 672 | st->print("G7="); print_location(st, uc->uc_mcontext.gregs[REG_G7]); |
aoqi@0 | 673 | st->cr(); |
aoqi@0 | 674 | |
aoqi@0 | 675 | st->print("O0="); print_location(st, uc->uc_mcontext.gregs[REG_O0]); |
aoqi@0 | 676 | st->print("O1="); print_location(st, uc->uc_mcontext.gregs[REG_O1]); |
aoqi@0 | 677 | st->print("O2="); print_location(st, uc->uc_mcontext.gregs[REG_O2]); |
aoqi@0 | 678 | st->print("O3="); print_location(st, uc->uc_mcontext.gregs[REG_O3]); |
aoqi@0 | 679 | st->print("O4="); print_location(st, uc->uc_mcontext.gregs[REG_O4]); |
aoqi@0 | 680 | st->print("O5="); print_location(st, uc->uc_mcontext.gregs[REG_O5]); |
aoqi@0 | 681 | st->print("O6="); print_location(st, uc->uc_mcontext.gregs[REG_O6]); |
aoqi@0 | 682 | st->print("O7="); print_location(st, uc->uc_mcontext.gregs[REG_O7]); |
aoqi@0 | 683 | st->cr(); |
aoqi@0 | 684 | |
aoqi@0 | 685 | st->print("L0="); print_location(st, sp[L0->sp_offset_in_saved_window()]); |
aoqi@0 | 686 | st->print("L1="); print_location(st, sp[L1->sp_offset_in_saved_window()]); |
aoqi@0 | 687 | st->print("L2="); print_location(st, sp[L2->sp_offset_in_saved_window()]); |
aoqi@0 | 688 | st->print("L3="); print_location(st, sp[L3->sp_offset_in_saved_window()]); |
aoqi@0 | 689 | st->print("L4="); print_location(st, sp[L4->sp_offset_in_saved_window()]); |
aoqi@0 | 690 | st->print("L5="); print_location(st, sp[L5->sp_offset_in_saved_window()]); |
aoqi@0 | 691 | st->print("L6="); print_location(st, sp[L6->sp_offset_in_saved_window()]); |
aoqi@0 | 692 | st->print("L7="); print_location(st, sp[L7->sp_offset_in_saved_window()]); |
aoqi@0 | 693 | st->cr(); |
aoqi@0 | 694 | |
aoqi@0 | 695 | st->print("I0="); print_location(st, sp[I0->sp_offset_in_saved_window()]); |
aoqi@0 | 696 | st->print("I1="); print_location(st, sp[I1->sp_offset_in_saved_window()]); |
aoqi@0 | 697 | st->print("I2="); print_location(st, sp[I2->sp_offset_in_saved_window()]); |
aoqi@0 | 698 | st->print("I3="); print_location(st, sp[I3->sp_offset_in_saved_window()]); |
aoqi@0 | 699 | st->print("I4="); print_location(st, sp[I4->sp_offset_in_saved_window()]); |
aoqi@0 | 700 | st->print("I5="); print_location(st, sp[I5->sp_offset_in_saved_window()]); |
aoqi@0 | 701 | st->print("I6="); print_location(st, sp[I6->sp_offset_in_saved_window()]); |
aoqi@0 | 702 | st->print("I7="); print_location(st, sp[I7->sp_offset_in_saved_window()]); |
aoqi@0 | 703 | st->cr(); |
aoqi@0 | 704 | } |
aoqi@0 | 705 | |
aoqi@0 | 706 | void os::Solaris::init_thread_fpu_state(void) { |
aoqi@0 | 707 | // Nothing needed on Sparc. |
aoqi@0 | 708 | } |
aoqi@0 | 709 | |
aoqi@0 | 710 | #if !defined(COMPILER2) && !defined(_LP64) |
aoqi@0 | 711 | |
aoqi@0 | 712 | // These routines are the initial value of atomic_xchg_entry(), |
aoqi@0 | 713 | // atomic_cmpxchg_entry(), atomic_add_entry() and fence_entry() |
aoqi@0 | 714 | // until initialization is complete. |
aoqi@0 | 715 | // TODO - remove when the VM drops support for V8. |
aoqi@0 | 716 | |
aoqi@0 | 717 | typedef jint xchg_func_t (jint, volatile jint*); |
aoqi@0 | 718 | typedef jint cmpxchg_func_t (jint, volatile jint*, jint); |
aoqi@0 | 719 | typedef jlong cmpxchg_long_func_t(jlong, volatile jlong*, jlong); |
aoqi@0 | 720 | typedef jint add_func_t (jint, volatile jint*); |
aoqi@0 | 721 | |
aoqi@0 | 722 | jint os::atomic_xchg_bootstrap(jint exchange_value, volatile jint* dest) { |
aoqi@0 | 723 | // try to use the stub: |
aoqi@0 | 724 | xchg_func_t* func = CAST_TO_FN_PTR(xchg_func_t*, StubRoutines::atomic_xchg_entry()); |
aoqi@0 | 725 | |
aoqi@0 | 726 | if (func != NULL) { |
aoqi@0 | 727 | os::atomic_xchg_func = func; |
aoqi@0 | 728 | return (*func)(exchange_value, dest); |
aoqi@0 | 729 | } |
aoqi@0 | 730 | assert(Threads::number_of_threads() == 0, "for bootstrap only"); |
aoqi@0 | 731 | |
aoqi@0 | 732 | jint old_value = *dest; |
aoqi@0 | 733 | *dest = exchange_value; |
aoqi@0 | 734 | return old_value; |
aoqi@0 | 735 | } |
aoqi@0 | 736 | |
aoqi@0 | 737 | jint os::atomic_cmpxchg_bootstrap(jint exchange_value, volatile jint* dest, jint compare_value) { |
aoqi@0 | 738 | // try to use the stub: |
aoqi@0 | 739 | cmpxchg_func_t* func = CAST_TO_FN_PTR(cmpxchg_func_t*, StubRoutines::atomic_cmpxchg_entry()); |
aoqi@0 | 740 | |
aoqi@0 | 741 | if (func != NULL) { |
aoqi@0 | 742 | os::atomic_cmpxchg_func = func; |
aoqi@0 | 743 | return (*func)(exchange_value, dest, compare_value); |
aoqi@0 | 744 | } |
aoqi@0 | 745 | assert(Threads::number_of_threads() == 0, "for bootstrap only"); |
aoqi@0 | 746 | |
aoqi@0 | 747 | jint old_value = *dest; |
aoqi@0 | 748 | if (old_value == compare_value) |
aoqi@0 | 749 | *dest = exchange_value; |
aoqi@0 | 750 | return old_value; |
aoqi@0 | 751 | } |
aoqi@0 | 752 | |
aoqi@0 | 753 | jlong os::atomic_cmpxchg_long_bootstrap(jlong exchange_value, volatile jlong* dest, jlong compare_value) { |
aoqi@0 | 754 | // try to use the stub: |
aoqi@0 | 755 | cmpxchg_long_func_t* func = CAST_TO_FN_PTR(cmpxchg_long_func_t*, StubRoutines::atomic_cmpxchg_long_entry()); |
aoqi@0 | 756 | |
aoqi@0 | 757 | if (func != NULL) { |
aoqi@0 | 758 | os::atomic_cmpxchg_long_func = func; |
aoqi@0 | 759 | return (*func)(exchange_value, dest, compare_value); |
aoqi@0 | 760 | } |
aoqi@0 | 761 | assert(Threads::number_of_threads() == 0, "for bootstrap only"); |
aoqi@0 | 762 | |
aoqi@0 | 763 | jlong old_value = *dest; |
aoqi@0 | 764 | if (old_value == compare_value) |
aoqi@0 | 765 | *dest = exchange_value; |
aoqi@0 | 766 | return old_value; |
aoqi@0 | 767 | } |
aoqi@0 | 768 | |
aoqi@0 | 769 | jint os::atomic_add_bootstrap(jint add_value, volatile jint* dest) { |
aoqi@0 | 770 | // try to use the stub: |
aoqi@0 | 771 | add_func_t* func = CAST_TO_FN_PTR(add_func_t*, StubRoutines::atomic_add_entry()); |
aoqi@0 | 772 | |
aoqi@0 | 773 | if (func != NULL) { |
aoqi@0 | 774 | os::atomic_add_func = func; |
aoqi@0 | 775 | return (*func)(add_value, dest); |
aoqi@0 | 776 | } |
aoqi@0 | 777 | assert(Threads::number_of_threads() == 0, "for bootstrap only"); |
aoqi@0 | 778 | |
aoqi@0 | 779 | return (*dest) += add_value; |
aoqi@0 | 780 | } |
aoqi@0 | 781 | |
aoqi@0 | 782 | xchg_func_t* os::atomic_xchg_func = os::atomic_xchg_bootstrap; |
aoqi@0 | 783 | cmpxchg_func_t* os::atomic_cmpxchg_func = os::atomic_cmpxchg_bootstrap; |
aoqi@0 | 784 | cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap; |
aoqi@0 | 785 | add_func_t* os::atomic_add_func = os::atomic_add_bootstrap; |
aoqi@0 | 786 | |
aoqi@0 | 787 | #endif // !_LP64 && !COMPILER2 |
aoqi@0 | 788 | |
aoqi@0 | 789 | #if defined(__sparc) && defined(COMPILER2) && defined(_GNU_SOURCE) |
aoqi@0 | 790 | // See file build/solaris/makefiles/$compiler.make |
aoqi@0 | 791 | // For compiler1 the architecture is v8 and frps isn't present in v8 |
aoqi@0 | 792 | extern "C" void _mark_fpu_nosave() { |
aoqi@0 | 793 | __asm__ __volatile__ ("wr %%g0, 0, %%fprs \n\t" : : :); |
aoqi@0 | 794 | } |
aoqi@0 | 795 | #endif //defined(__sparc) && defined(COMPILER2) |
aoqi@0 | 796 | |
aoqi@0 | 797 | #ifndef PRODUCT |
aoqi@0 | 798 | void os::verify_stack_alignment() { |
aoqi@0 | 799 | } |
aoqi@0 | 800 | #endif |