src/os_cpu/windows_x86/vm/os_windows_x86.cpp

Wed, 12 Nov 2014 13:12:35 -0500

author
jiangli
date
Wed, 12 Nov 2014 13:12:35 -0500
changeset 7362
10842d23f20a
parent 6198
55fb97c4c58d
child 7535
7ae4e26cb1e0
child 9349
e25662a88116
permissions
-rw-r--r--

8054008: Using -XX:-LazyBootClassLoader crashes with ACCESS_VIOLATION on Win 64bit.
Summary: Only enable the assert for current_stack_pointer after stub routines become available.
Reviewed-by: dholmes, roland, lfoltan

duke@435 1 /*
mikael@6198 2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
stefank@2314 25 // no precompiled headers
twisti@4318 26 #include "asm/macroAssembler.hpp"
stefank@2314 27 #include "classfile/classLoader.hpp"
stefank@2314 28 #include "classfile/systemDictionary.hpp"
stefank@2314 29 #include "classfile/vmSymbols.hpp"
stefank@2314 30 #include "code/icBuffer.hpp"
stefank@2314 31 #include "code/vtableStubs.hpp"
iklam@5667 32 #include "decoder_windows.hpp"
stefank@2314 33 #include "interpreter/interpreter.hpp"
stefank@2314 34 #include "jvm_windows.h"
stefank@2314 35 #include "memory/allocation.inline.hpp"
stefank@2314 36 #include "mutex_windows.inline.hpp"
stefank@2314 37 #include "nativeInst_x86.hpp"
stefank@2314 38 #include "os_share_windows.hpp"
stefank@2314 39 #include "prims/jniFastGetField.hpp"
stefank@2314 40 #include "prims/jvm.h"
stefank@2314 41 #include "prims/jvm_misc.hpp"
stefank@2314 42 #include "runtime/arguments.hpp"
stefank@2314 43 #include "runtime/extendedPC.hpp"
stefank@2314 44 #include "runtime/frame.inline.hpp"
stefank@2314 45 #include "runtime/interfaceSupport.hpp"
stefank@2314 46 #include "runtime/java.hpp"
stefank@2314 47 #include "runtime/javaCalls.hpp"
stefank@2314 48 #include "runtime/mutexLocker.hpp"
stefank@2314 49 #include "runtime/osThread.hpp"
stefank@2314 50 #include "runtime/sharedRuntime.hpp"
stefank@2314 51 #include "runtime/stubRoutines.hpp"
stefank@4299 52 #include "runtime/thread.inline.hpp"
stefank@2314 53 #include "runtime/timer.hpp"
stefank@2314 54 #include "utilities/events.hpp"
stefank@2314 55 #include "utilities/vmError.hpp"
stefank@2314 56
duke@435 57 # include "unwind_windows_x86.hpp"
duke@435 58 #undef REG_SP
duke@435 59 #undef REG_FP
duke@435 60 #undef REG_PC
duke@435 61 #ifdef AMD64
duke@435 62 #define REG_SP Rsp
duke@435 63 #define REG_FP Rbp
duke@435 64 #define REG_PC Rip
duke@435 65 #else
duke@435 66 #define REG_SP Esp
duke@435 67 #define REG_FP Ebp
duke@435 68 #define REG_PC Eip
duke@435 69 #endif // AMD64
duke@435 70
duke@435 71 extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* );
duke@435 72
duke@435 73 // Install a win32 structured exception handler around thread.
duke@435 74 void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) {
duke@435 75 __try {
duke@435 76
duke@435 77 #ifndef AMD64
duke@435 78 // We store the current thread in this wrapperthread location
duke@435 79 // and determine how far away this address is from the structured
duke@435 80 // execption pointer that FS:[0] points to. This get_thread
duke@435 81 // code can then get the thread pointer via FS.
duke@435 82 //
duke@435 83 // Warning: This routine must NEVER be inlined since we'd end up with
duke@435 84 // multiple offsets.
duke@435 85 //
duke@435 86 volatile Thread* wrapperthread = thread;
duke@435 87
duke@435 88 if ( ThreadLocalStorage::get_thread_ptr_offset() == 0 ) {
duke@435 89 int thread_ptr_offset;
duke@435 90 __asm {
duke@435 91 lea eax, dword ptr wrapperthread;
duke@435 92 sub eax, dword ptr FS:[0H];
duke@435 93 mov thread_ptr_offset, eax
duke@435 94 };
duke@435 95 ThreadLocalStorage::set_thread_ptr_offset(thread_ptr_offset);
duke@435 96 }
duke@435 97 #ifdef ASSERT
duke@435 98 // Verify that the offset hasn't changed since we initally captured
duke@435 99 // it. This might happen if we accidentally ended up with an
duke@435 100 // inlined version of this routine.
duke@435 101 else {
duke@435 102 int test_thread_ptr_offset;
duke@435 103 __asm {
duke@435 104 lea eax, dword ptr wrapperthread;
duke@435 105 sub eax, dword ptr FS:[0H];
duke@435 106 mov test_thread_ptr_offset, eax
duke@435 107 };
duke@435 108 assert(test_thread_ptr_offset == ThreadLocalStorage::get_thread_ptr_offset(),
duke@435 109 "thread pointer offset from SEH changed");
duke@435 110 }
duke@435 111 #endif // ASSERT
duke@435 112 #endif // !AMD64
duke@435 113
duke@435 114 f(value, method, args, thread);
duke@435 115 } __except(topLevelExceptionFilter((_EXCEPTION_POINTERS*)_exception_info())) {
duke@435 116 // Nothing to do.
duke@435 117 }
duke@435 118 }
duke@435 119
duke@435 120 #ifdef AMD64
duke@435 121
duke@435 122 // This is the language specific handler for exceptions
duke@435 123 // originating from dynamically generated code.
duke@435 124 // We call the standard structured exception handler
duke@435 125 // We only expect Continued Execution since we cannot unwind
duke@435 126 // from generated code.
duke@435 127 LONG HandleExceptionFromCodeCache(
duke@435 128 IN PEXCEPTION_RECORD ExceptionRecord,
duke@435 129 IN ULONG64 EstablisherFrame,
duke@435 130 IN OUT PCONTEXT ContextRecord,
duke@435 131 IN OUT PDISPATCHER_CONTEXT DispatcherContext) {
duke@435 132 EXCEPTION_POINTERS ep;
duke@435 133 LONG result;
duke@435 134
duke@435 135 ep.ExceptionRecord = ExceptionRecord;
duke@435 136 ep.ContextRecord = ContextRecord;
duke@435 137
duke@435 138 result = topLevelExceptionFilter(&ep);
duke@435 139
duke@435 140 // We better only get a CONTINUE_EXECUTION from our handler
duke@435 141 // since we don't have unwind information registered.
duke@435 142
duke@435 143 guarantee( result == EXCEPTION_CONTINUE_EXECUTION,
duke@435 144 "Unexpected result from topLevelExceptionFilter");
duke@435 145
duke@435 146 return(ExceptionContinueExecution);
duke@435 147 }
duke@435 148
duke@435 149
duke@435 150 // Structure containing the Windows Data Structures required
duke@435 151 // to register our Code Cache exception handler.
duke@435 152 // We put these in the CodeCache since the API requires
duke@435 153 // all addresses in these structures are relative to the Code
duke@435 154 // area registered with RtlAddFunctionTable.
duke@435 155 typedef struct {
duke@435 156 char ExceptionHandlerInstr[16]; // jmp HandleExceptionFromCodeCache
duke@435 157 RUNTIME_FUNCTION rt;
duke@435 158 UNWIND_INFO_EH_ONLY unw;
duke@435 159 } DynamicCodeData, *pDynamicCodeData;
duke@435 160
duke@435 161 #endif // AMD64
duke@435 162 //
duke@435 163 // Register our CodeCache area with the OS so it will dispatch exceptions
duke@435 164 // to our topLevelExceptionFilter when we take an exception in our
duke@435 165 // dynamically generated code.
duke@435 166 //
duke@435 167 // Arguments: low and high are the address of the full reserved
duke@435 168 // codeCache area
duke@435 169 //
duke@435 170 bool os::register_code_area(char *low, char *high) {
duke@435 171 #ifdef AMD64
duke@435 172
duke@435 173 ResourceMark rm;
duke@435 174
duke@435 175 pDynamicCodeData pDCD;
duke@435 176 PRUNTIME_FUNCTION prt;
duke@435 177 PUNWIND_INFO_EH_ONLY punwind;
duke@435 178
twisti@2103 179 BufferBlob* blob = BufferBlob::create("CodeCache Exception Handler", sizeof(DynamicCodeData));
twisti@2103 180 CodeBuffer cb(blob);
duke@435 181 MacroAssembler* masm = new MacroAssembler(&cb);
duke@435 182 pDCD = (pDynamicCodeData) masm->pc();
duke@435 183
duke@435 184 masm->jump(ExternalAddress((address)&HandleExceptionFromCodeCache));
duke@435 185 masm->flush();
duke@435 186
duke@435 187 // Create an Unwind Structure specifying no unwind info
duke@435 188 // other than an Exception Handler
duke@435 189 punwind = &pDCD->unw;
duke@435 190 punwind->Version = 1;
duke@435 191 punwind->Flags = UNW_FLAG_EHANDLER;
duke@435 192 punwind->SizeOfProlog = 0;
duke@435 193 punwind->CountOfCodes = 0;
duke@435 194 punwind->FrameRegister = 0;
duke@435 195 punwind->FrameOffset = 0;
duke@435 196 punwind->ExceptionHandler = (char *)(&(pDCD->ExceptionHandlerInstr[0])) -
duke@435 197 (char*)low;
duke@435 198 punwind->ExceptionData[0] = 0;
duke@435 199
duke@435 200 // This structure describes the covered dynamic code area.
duke@435 201 // Addresses are relative to the beginning on the code cache area
duke@435 202 prt = &pDCD->rt;
duke@435 203 prt->BeginAddress = 0;
duke@435 204 prt->EndAddress = (ULONG)(high - low);
duke@435 205 prt->UnwindData = ((char *)punwind - low);
duke@435 206
duke@435 207 guarantee(RtlAddFunctionTable(prt, 1, (ULONGLONG)low),
duke@435 208 "Failed to register Dynamic Code Exception Handler with RtlAddFunctionTable");
duke@435 209
duke@435 210 #endif // AMD64
duke@435 211 return true;
duke@435 212 }
duke@435 213
zgu@4079 214 void os::initialize_thread(Thread* thr) {
duke@435 215 // Nothing to do.
duke@435 216 }
duke@435 217
duke@435 218 // Atomics and Stub Functions
duke@435 219
duke@435 220 typedef jint xchg_func_t (jint, volatile jint*);
duke@435 221 typedef intptr_t xchg_ptr_func_t (intptr_t, volatile intptr_t*);
duke@435 222 typedef jint cmpxchg_func_t (jint, volatile jint*, jint);
duke@435 223 typedef jlong cmpxchg_long_func_t (jlong, volatile jlong*, jlong);
duke@435 224 typedef jint add_func_t (jint, volatile jint*);
duke@435 225 typedef intptr_t add_ptr_func_t (intptr_t, volatile intptr_t*);
duke@435 226
duke@435 227 #ifdef AMD64
duke@435 228
duke@435 229 jint os::atomic_xchg_bootstrap(jint exchange_value, volatile jint* dest) {
duke@435 230 // try to use the stub:
duke@435 231 xchg_func_t* func = CAST_TO_FN_PTR(xchg_func_t*, StubRoutines::atomic_xchg_entry());
duke@435 232
duke@435 233 if (func != NULL) {
duke@435 234 os::atomic_xchg_func = func;
duke@435 235 return (*func)(exchange_value, dest);
duke@435 236 }
duke@435 237 assert(Threads::number_of_threads() == 0, "for bootstrap only");
duke@435 238
duke@435 239 jint old_value = *dest;
duke@435 240 *dest = exchange_value;
duke@435 241 return old_value;
duke@435 242 }
duke@435 243
duke@435 244 intptr_t os::atomic_xchg_ptr_bootstrap(intptr_t exchange_value, volatile intptr_t* dest) {
duke@435 245 // try to use the stub:
duke@435 246 xchg_ptr_func_t* func = CAST_TO_FN_PTR(xchg_ptr_func_t*, StubRoutines::atomic_xchg_ptr_entry());
duke@435 247
duke@435 248 if (func != NULL) {
duke@435 249 os::atomic_xchg_ptr_func = func;
duke@435 250 return (*func)(exchange_value, dest);
duke@435 251 }
duke@435 252 assert(Threads::number_of_threads() == 0, "for bootstrap only");
duke@435 253
duke@435 254 intptr_t old_value = *dest;
duke@435 255 *dest = exchange_value;
duke@435 256 return old_value;
duke@435 257 }
duke@435 258
duke@435 259
duke@435 260 jint os::atomic_cmpxchg_bootstrap(jint exchange_value, volatile jint* dest, jint compare_value) {
duke@435 261 // try to use the stub:
duke@435 262 cmpxchg_func_t* func = CAST_TO_FN_PTR(cmpxchg_func_t*, StubRoutines::atomic_cmpxchg_entry());
duke@435 263
duke@435 264 if (func != NULL) {
duke@435 265 os::atomic_cmpxchg_func = func;
duke@435 266 return (*func)(exchange_value, dest, compare_value);
duke@435 267 }
duke@435 268 assert(Threads::number_of_threads() == 0, "for bootstrap only");
duke@435 269
duke@435 270 jint old_value = *dest;
duke@435 271 if (old_value == compare_value)
duke@435 272 *dest = exchange_value;
duke@435 273 return old_value;
duke@435 274 }
duke@435 275 #endif // AMD64
duke@435 276
duke@435 277 jlong os::atomic_cmpxchg_long_bootstrap(jlong exchange_value, volatile jlong* dest, jlong compare_value) {
duke@435 278 // try to use the stub:
duke@435 279 cmpxchg_long_func_t* func = CAST_TO_FN_PTR(cmpxchg_long_func_t*, StubRoutines::atomic_cmpxchg_long_entry());
duke@435 280
duke@435 281 if (func != NULL) {
duke@435 282 os::atomic_cmpxchg_long_func = func;
duke@435 283 return (*func)(exchange_value, dest, compare_value);
duke@435 284 }
duke@435 285 assert(Threads::number_of_threads() == 0, "for bootstrap only");
duke@435 286
duke@435 287 jlong old_value = *dest;
duke@435 288 if (old_value == compare_value)
duke@435 289 *dest = exchange_value;
duke@435 290 return old_value;
duke@435 291 }
duke@435 292
duke@435 293 #ifdef AMD64
duke@435 294
duke@435 295 jint os::atomic_add_bootstrap(jint add_value, volatile jint* dest) {
duke@435 296 // try to use the stub:
duke@435 297 add_func_t* func = CAST_TO_FN_PTR(add_func_t*, StubRoutines::atomic_add_entry());
duke@435 298
duke@435 299 if (func != NULL) {
duke@435 300 os::atomic_add_func = func;
duke@435 301 return (*func)(add_value, dest);
duke@435 302 }
duke@435 303 assert(Threads::number_of_threads() == 0, "for bootstrap only");
duke@435 304
duke@435 305 return (*dest) += add_value;
duke@435 306 }
duke@435 307
duke@435 308 intptr_t os::atomic_add_ptr_bootstrap(intptr_t add_value, volatile intptr_t* dest) {
duke@435 309 // try to use the stub:
duke@435 310 add_ptr_func_t* func = CAST_TO_FN_PTR(add_ptr_func_t*, StubRoutines::atomic_add_ptr_entry());
duke@435 311
duke@435 312 if (func != NULL) {
duke@435 313 os::atomic_add_ptr_func = func;
duke@435 314 return (*func)(add_value, dest);
duke@435 315 }
duke@435 316 assert(Threads::number_of_threads() == 0, "for bootstrap only");
duke@435 317
duke@435 318 return (*dest) += add_value;
duke@435 319 }
duke@435 320
duke@435 321 xchg_func_t* os::atomic_xchg_func = os::atomic_xchg_bootstrap;
duke@435 322 xchg_ptr_func_t* os::atomic_xchg_ptr_func = os::atomic_xchg_ptr_bootstrap;
duke@435 323 cmpxchg_func_t* os::atomic_cmpxchg_func = os::atomic_cmpxchg_bootstrap;
duke@435 324 add_func_t* os::atomic_add_func = os::atomic_add_bootstrap;
duke@435 325 add_ptr_func_t* os::atomic_add_ptr_func = os::atomic_add_ptr_bootstrap;
duke@435 326
duke@435 327 #endif // AMD64
duke@435 328
duke@435 329 cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap;
duke@435 330
iklam@5667 331 #ifdef AMD64
iklam@5667 332 /*
iklam@5667 333 * Windows/x64 does not use stack frames the way expected by Java:
iklam@5667 334 * [1] in most cases, there is no frame pointer. All locals are addressed via RSP
iklam@5667 335 * [2] in rare cases, when alloca() is used, a frame pointer is used, but this may
iklam@5667 336 * not be RBP.
iklam@5667 337 * See http://msdn.microsoft.com/en-us/library/ew5tede7.aspx
iklam@5667 338 *
iklam@5667 339 * So it's not possible to print the native stack using the
iklam@5667 340 * while (...) {... fr = os::get_sender_for_C_frame(&fr); }
iklam@5667 341 * loop in vmError.cpp. We need to roll our own loop.
iklam@5667 342 */
iklam@5667 343 bool os::platform_print_native_stack(outputStream* st, void* context,
iklam@5667 344 char *buf, int buf_size)
iklam@5667 345 {
iklam@5667 346 CONTEXT ctx;
iklam@5667 347 if (context != NULL) {
iklam@5667 348 memcpy(&ctx, context, sizeof(ctx));
iklam@5667 349 } else {
iklam@5667 350 RtlCaptureContext(&ctx);
iklam@5667 351 }
iklam@5667 352
iklam@5667 353 st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");
iklam@5667 354
iklam@5667 355 STACKFRAME stk;
iklam@5667 356 memset(&stk, 0, sizeof(stk));
iklam@5667 357 stk.AddrStack.Offset = ctx.Rsp;
iklam@5667 358 stk.AddrStack.Mode = AddrModeFlat;
iklam@5667 359 stk.AddrFrame.Offset = ctx.Rbp;
iklam@5667 360 stk.AddrFrame.Mode = AddrModeFlat;
iklam@5667 361 stk.AddrPC.Offset = ctx.Rip;
iklam@5667 362 stk.AddrPC.Mode = AddrModeFlat;
iklam@5667 363
iklam@5667 364 int count = 0;
iklam@5667 365 address lastpc = 0;
iklam@5667 366 while (count++ < StackPrintLimit) {
iklam@5667 367 intptr_t* sp = (intptr_t*)stk.AddrStack.Offset;
iklam@5667 368 intptr_t* fp = (intptr_t*)stk.AddrFrame.Offset; // NOT necessarily the same as ctx.Rbp!
iklam@5667 369 address pc = (address)stk.AddrPC.Offset;
iklam@5667 370
iklam@5667 371 if (pc != NULL && sp != NULL && fp != NULL) {
iklam@5667 372 if (count == 2 && lastpc == pc) {
iklam@5667 373 // Skip it -- StackWalk64() may return the same PC
iklam@5667 374 // (but different SP) on the first try.
iklam@5667 375 } else {
iklam@5667 376 // Don't try to create a frame(sp, fp, pc) -- on WinX64, stk.AddrFrame
iklam@5667 377 // may not contain what Java expects, and may cause the frame() constructor
iklam@5667 378 // to crash. Let's just print out the symbolic address.
iklam@5667 379 frame::print_C_frame(st, buf, buf_size, pc);
iklam@5667 380 st->cr();
iklam@5667 381 }
iklam@5667 382 lastpc = pc;
iklam@5667 383 } else {
iklam@5667 384 break;
iklam@5667 385 }
iklam@5667 386
iklam@5667 387 PVOID p = WindowsDbgHelp::SymFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset);
iklam@5667 388 if (!p) {
iklam@5667 389 // StackWalk64() can't handle this PC. Calling StackWalk64 again may cause crash.
iklam@5667 390 break;
iklam@5667 391 }
iklam@5667 392
iklam@5667 393 BOOL result = WindowsDbgHelp::StackWalk64(
iklam@5667 394 IMAGE_FILE_MACHINE_AMD64, // __in DWORD MachineType,
iklam@5667 395 GetCurrentProcess(), // __in HANDLE hProcess,
iklam@5667 396 GetCurrentThread(), // __in HANDLE hThread,
iklam@5667 397 &stk, // __inout LP STACKFRAME64 StackFrame,
iklam@5667 398 &ctx, // __inout PVOID ContextRecord,
iklam@5667 399 NULL, // __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
iklam@5667 400 WindowsDbgHelp::pfnSymFunctionTableAccess64(),
iklam@5667 401 // __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
iklam@5667 402 WindowsDbgHelp::pfnSymGetModuleBase64(),
iklam@5667 403 // __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
iklam@5667 404 NULL); // __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
iklam@5667 405
iklam@5667 406 if (!result) {
iklam@5667 407 break;
iklam@5667 408 }
iklam@5667 409 }
iklam@5667 410 if (count > StackPrintLimit) {
iklam@5667 411 st->print_cr("...<more frames>...");
iklam@5667 412 }
iklam@5667 413 st->cr();
iklam@5667 414
iklam@5667 415 return true;
iklam@5667 416 }
iklam@5667 417 #endif // AMD64
iklam@5667 418
duke@435 419 ExtendedPC os::fetch_frame_from_context(void* ucVoid,
duke@435 420 intptr_t** ret_sp, intptr_t** ret_fp) {
duke@435 421
duke@435 422 ExtendedPC epc;
duke@435 423 CONTEXT* uc = (CONTEXT*)ucVoid;
duke@435 424
duke@435 425 if (uc != NULL) {
duke@435 426 epc = ExtendedPC((address)uc->REG_PC);
duke@435 427 if (ret_sp) *ret_sp = (intptr_t*)uc->REG_SP;
duke@435 428 if (ret_fp) *ret_fp = (intptr_t*)uc->REG_FP;
duke@435 429 } else {
duke@435 430 // construct empty ExtendedPC for return value checking
duke@435 431 epc = ExtendedPC(NULL);
duke@435 432 if (ret_sp) *ret_sp = (intptr_t *)NULL;
duke@435 433 if (ret_fp) *ret_fp = (intptr_t *)NULL;
duke@435 434 }
duke@435 435
duke@435 436 return epc;
duke@435 437 }
duke@435 438
duke@435 439 frame os::fetch_frame_from_context(void* ucVoid) {
duke@435 440 intptr_t* sp;
duke@435 441 intptr_t* fp;
duke@435 442 ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
duke@435 443 return frame(sp, fp, epc.pc());
duke@435 444 }
duke@435 445
duke@435 446 // VC++ does not save frame pointer on stack in optimized build. It
duke@435 447 // can be turned off by /Oy-. If we really want to walk C frames,
duke@435 448 // we can use the StackWalk() API.
duke@435 449 frame os::get_sender_for_C_frame(frame* fr) {
duke@435 450 return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
duke@435 451 }
duke@435 452
roland@3606 453 #ifndef AMD64
roland@3606 454 // Returns an estimate of the current stack pointer. Result must be guaranteed
roland@3606 455 // to point into the calling threads stack, and be no lower than the current
roland@3606 456 // stack pointer.
roland@3606 457 address os::current_stack_pointer() {
roland@3606 458 int dummy;
roland@3606 459 address sp = (address)&dummy;
roland@3606 460 return sp;
roland@3606 461 }
roland@3606 462 #else
roland@3606 463 // Returns the current stack pointer. Accurate value needed for
roland@3606 464 // os::verify_stack_alignment().
roland@3606 465 address os::current_stack_pointer() {
roland@3606 466 typedef address get_sp_func();
roland@3606 467 get_sp_func* func = CAST_TO_FN_PTR(get_sp_func*,
roland@3606 468 StubRoutines::x86::get_previous_sp_entry());
roland@3606 469 return (*func)();
roland@3606 470 }
roland@3606 471 #endif
roland@3606 472
duke@435 473
duke@435 474 #ifndef AMD64
duke@435 475 intptr_t* _get_previous_fp() {
duke@435 476 intptr_t **frameptr;
duke@435 477 __asm {
duke@435 478 mov frameptr, ebp
duke@435 479 };
duke@435 480 return *frameptr;
duke@435 481 }
duke@435 482 #endif // !AMD64
duke@435 483
duke@435 484 frame os::current_frame() {
duke@435 485
duke@435 486 #ifdef AMD64
duke@435 487 // apparently _asm not supported on windows amd64
duke@435 488 typedef intptr_t* get_fp_func ();
duke@435 489 get_fp_func* func = CAST_TO_FN_PTR(get_fp_func*,
never@739 490 StubRoutines::x86::get_previous_fp_entry());
dholmes@4528 491 if (func == NULL) return frame();
duke@435 492 intptr_t* fp = (*func)();
iklam@5667 493 if (fp == NULL) {
iklam@5667 494 return frame();
iklam@5667 495 }
duke@435 496 #else
duke@435 497 intptr_t* fp = _get_previous_fp();
duke@435 498 #endif // AMD64
duke@435 499
duke@435 500 frame myframe((intptr_t*)os::current_stack_pointer(),
duke@435 501 (intptr_t*)fp,
duke@435 502 CAST_FROM_FN_PTR(address, os::current_frame));
duke@435 503 if (os::is_first_C_frame(&myframe)) {
duke@435 504 // stack is not walkable
dholmes@4528 505 return frame();
duke@435 506 } else {
duke@435 507 return os::get_sender_for_C_frame(&myframe);
duke@435 508 }
duke@435 509 }
duke@435 510
duke@435 511 void os::print_context(outputStream *st, void *context) {
duke@435 512 if (context == NULL) return;
duke@435 513
duke@435 514 CONTEXT* uc = (CONTEXT*)context;
duke@435 515
duke@435 516 st->print_cr("Registers:");
duke@435 517 #ifdef AMD64
bobv@2036 518 st->print( "RAX=" INTPTR_FORMAT, uc->Rax);
bobv@2036 519 st->print(", RBX=" INTPTR_FORMAT, uc->Rbx);
bobv@2036 520 st->print(", RCX=" INTPTR_FORMAT, uc->Rcx);
bobv@2036 521 st->print(", RDX=" INTPTR_FORMAT, uc->Rdx);
duke@435 522 st->cr();
bobv@2036 523 st->print( "RSP=" INTPTR_FORMAT, uc->Rsp);
bobv@2036 524 st->print(", RBP=" INTPTR_FORMAT, uc->Rbp);
bobv@2036 525 st->print(", RSI=" INTPTR_FORMAT, uc->Rsi);
bobv@2036 526 st->print(", RDI=" INTPTR_FORMAT, uc->Rdi);
duke@435 527 st->cr();
never@2262 528 st->print( "R8 =" INTPTR_FORMAT, uc->R8);
never@2262 529 st->print(", R9 =" INTPTR_FORMAT, uc->R9);
bobv@2036 530 st->print(", R10=" INTPTR_FORMAT, uc->R10);
bobv@2036 531 st->print(", R11=" INTPTR_FORMAT, uc->R11);
bobv@2036 532 st->cr();
bobv@2036 533 st->print( "R12=" INTPTR_FORMAT, uc->R12);
bobv@2036 534 st->print(", R13=" INTPTR_FORMAT, uc->R13);
bobv@2036 535 st->print(", R14=" INTPTR_FORMAT, uc->R14);
bobv@2036 536 st->print(", R15=" INTPTR_FORMAT, uc->R15);
bobv@2036 537 st->cr();
bobv@2036 538 st->print( "RIP=" INTPTR_FORMAT, uc->Rip);
duke@435 539 st->print(", EFLAGS=" INTPTR_FORMAT, uc->EFlags);
duke@435 540 #else
duke@435 541 st->print( "EAX=" INTPTR_FORMAT, uc->Eax);
duke@435 542 st->print(", EBX=" INTPTR_FORMAT, uc->Ebx);
duke@435 543 st->print(", ECX=" INTPTR_FORMAT, uc->Ecx);
duke@435 544 st->print(", EDX=" INTPTR_FORMAT, uc->Edx);
duke@435 545 st->cr();
duke@435 546 st->print( "ESP=" INTPTR_FORMAT, uc->Esp);
duke@435 547 st->print(", EBP=" INTPTR_FORMAT, uc->Ebp);
duke@435 548 st->print(", ESI=" INTPTR_FORMAT, uc->Esi);
duke@435 549 st->print(", EDI=" INTPTR_FORMAT, uc->Edi);
duke@435 550 st->cr();
duke@435 551 st->print( "EIP=" INTPTR_FORMAT, uc->Eip);
duke@435 552 st->print(", EFLAGS=" INTPTR_FORMAT, uc->EFlags);
duke@435 553 #endif // AMD64
duke@435 554 st->cr();
duke@435 555 st->cr();
duke@435 556
duke@435 557 intptr_t *sp = (intptr_t *)uc->REG_SP;
duke@435 558 st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp);
duke@435 559 print_hex_dump(st, (address)sp, (address)(sp + 32), sizeof(intptr_t));
duke@435 560 st->cr();
duke@435 561
duke@435 562 // Note: it may be unsafe to inspect memory near pc. For example, pc may
duke@435 563 // point to garbage if entry point in an nmethod is corrupted. Leave
duke@435 564 // this at the end, and hope for the best.
duke@435 565 address pc = (address)uc->REG_PC;
duke@435 566 st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc);
never@2262 567 print_hex_dump(st, pc - 32, pc + 32, sizeof(char));
never@2262 568 st->cr();
never@2262 569 }
never@2262 570
never@2262 571
never@2262 572 void os::print_register_info(outputStream *st, void *context) {
never@2262 573 if (context == NULL) return;
never@2262 574
never@2262 575 CONTEXT* uc = (CONTEXT*)context;
never@2262 576
never@2262 577 st->print_cr("Register to memory mapping:");
never@2262 578 st->cr();
never@2262 579
never@2262 580 // this is only for the "general purpose" registers
never@2262 581
never@2262 582 #ifdef AMD64
never@2262 583 st->print("RAX="); print_location(st, uc->Rax);
never@2262 584 st->print("RBX="); print_location(st, uc->Rbx);
never@2262 585 st->print("RCX="); print_location(st, uc->Rcx);
never@2262 586 st->print("RDX="); print_location(st, uc->Rdx);
never@2262 587 st->print("RSP="); print_location(st, uc->Rsp);
never@2262 588 st->print("RBP="); print_location(st, uc->Rbp);
never@2262 589 st->print("RSI="); print_location(st, uc->Rsi);
never@2262 590 st->print("RDI="); print_location(st, uc->Rdi);
never@2262 591 st->print("R8 ="); print_location(st, uc->R8);
never@2262 592 st->print("R9 ="); print_location(st, uc->R9);
never@2262 593 st->print("R10="); print_location(st, uc->R10);
never@2262 594 st->print("R11="); print_location(st, uc->R11);
never@2262 595 st->print("R12="); print_location(st, uc->R12);
never@2262 596 st->print("R13="); print_location(st, uc->R13);
never@2262 597 st->print("R14="); print_location(st, uc->R14);
never@2262 598 st->print("R15="); print_location(st, uc->R15);
never@2262 599 #else
never@2262 600 st->print("EAX="); print_location(st, uc->Eax);
never@2262 601 st->print("EBX="); print_location(st, uc->Ebx);
never@2262 602 st->print("ECX="); print_location(st, uc->Ecx);
never@2262 603 st->print("EDX="); print_location(st, uc->Edx);
never@2262 604 st->print("ESP="); print_location(st, uc->Esp);
never@2262 605 st->print("EBP="); print_location(st, uc->Ebp);
never@2262 606 st->print("ESI="); print_location(st, uc->Esi);
never@2262 607 st->print("EDI="); print_location(st, uc->Edi);
never@2262 608 #endif
never@2262 609
duke@435 610 st->cr();
duke@435 611 }
duke@435 612
duke@435 613 extern "C" int SpinPause () {
duke@435 614 #ifdef AMD64
duke@435 615 return 0 ;
duke@435 616 #else
duke@435 617 // pause == rep:nop
duke@435 618 // On systems that don't support pause a rep:nop
duke@435 619 // is executed as a nop. The rep: prefix is ignored.
duke@435 620 _asm {
duke@435 621 pause ;
duke@435 622 };
duke@435 623 return 1 ;
duke@435 624 #endif // AMD64
duke@435 625 }
duke@435 626
duke@435 627
duke@435 628 void os::setup_fpu() {
duke@435 629 #ifndef AMD64
duke@435 630 int fpu_cntrl_word = StubRoutines::fpu_cntrl_wrd_std();
duke@435 631 __asm fldcw fpu_cntrl_word;
duke@435 632 #endif // !AMD64
duke@435 633 }
roland@3606 634
roland@3606 635 #ifndef PRODUCT
roland@3606 636 void os::verify_stack_alignment() {
roland@3606 637 #ifdef AMD64
jiangli@7362 638 // The current_stack_pointer() calls generated get_previous_sp stub routine.
jiangli@7362 639 // Only enable the assert after the routine becomes available.
jiangli@7362 640 if (StubRoutines::code1() != NULL) {
jiangli@7362 641 assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
jiangli@7362 642 }
roland@3606 643 #endif
roland@3606 644 }
roland@3606 645 #endif

mercurial