diff options
author | duke <none@none> | 2007-12-01 00:00:00 +0000 |
---|---|---|
committer | duke <none@none> | 2007-12-01 00:00:00 +0000 |
commit | fa88c88cef63eb7f9083dccb60548d78635a44b1 (patch) | |
tree | 8376f6e5c41e70162b5867d9e1fea3f17f540473 /src/os_cpu/windows_x86 | |
download | jdk8u_hotspot-fa88c88cef63eb7f9083dccb60548d78635a44b1.tar.gz |
Initial load
Diffstat (limited to 'src/os_cpu/windows_x86')
19 files changed, 2175 insertions, 0 deletions
diff --git a/src/os_cpu/windows_x86/vm/assembler_windows_x86_32.cpp b/src/os_cpu/windows_x86/vm/assembler_windows_x86_32.cpp new file mode 100644 index 000000000..dd90d704f --- /dev/null +++ b/src/os_cpu/windows_x86/vm/assembler_windows_x86_32.cpp @@ -0,0 +1,64 @@ +/* + * Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#include "incls/_precompiled.incl" +#include "incls/_assembler_windows_x86_32.cpp.incl" + + +void MacroAssembler::int3() { + emit_byte(0xCC); +} + +// The current scheme to accelerate access to the thread +// pointer is to store the current thread in the os_exception_wrapper +// and reference the current thread from stubs and compiled code +// via the FS register. FS[0] contains a pointer to the structured +// exception block which is actually a stack address. The first time +// we call the os exception wrapper, we calculate and store the +// offset from this exception block and use that offset here. +// +// The last mechanism we used was problematic in that the +// the offset we had hard coded in the VM kept changing as Microsoft +// evolved the OS. +// +// Warning: This mechanism assumes that we only attempt to get the +// thread when we are nested below a call wrapper. +// +// movl reg, fs:[0] Get exeception pointer +// movl reg, [reg + thread_ptr_offset] Load thread +// +void MacroAssembler::get_thread(Register thread) { + // can't use ExternalAddress because it can't take NULL + AddressLiteral null(0, relocInfo::none); + + prefix(FS_segment); + movptr(thread, null); + assert(ThreadLocalStorage::get_thread_ptr_offset() != 0, + "Thread Pointer Offset has not been initialized"); + movl(thread, Address(thread, ThreadLocalStorage::get_thread_ptr_offset())); +} + +bool MacroAssembler::needs_explicit_null_check(int offset) { + return offset < 0 || (int)os::vm_page_size() <= offset; +} diff --git a/src/os_cpu/windows_x86/vm/assembler_windows_x86_64.cpp b/src/os_cpu/windows_x86/vm/assembler_windows_x86_64.cpp new file mode 100644 index 000000000..c0211d0af --- /dev/null +++ b/src/os_cpu/windows_x86/vm/assembler_windows_x86_64.cpp @@ -0,0 +1,71 @@ +/* + * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#include "incls/_precompiled.incl" +#include "incls/_assembler_windows_x86_64.cpp.incl" + + +void MacroAssembler::int3() { + emit_byte(0xCC); +} + +// call (Thread*)TlsGetValue(thread_index()); +void MacroAssembler::get_thread(Register thread) { + if (thread != rax) { + pushq(rax); + } + pushq(rdi); + pushq(rsi); + pushq(rdx); + pushq(rcx); + pushq(r8); + pushq(r9); + pushq(r10); + // XXX + movq(r10, rsp); + andq(rsp, -16); + pushq(r10); + pushq(r11); + + movl(c_rarg0, ThreadLocalStorage::thread_index()); + call(RuntimeAddress((address)TlsGetValue)); + + popq(r11); + popq(rsp); + popq(r10); + popq(r9); + popq(r8); + popq(rcx); + popq(rdx); + popq(rsi); + popq(rdi); + if (thread != rax) { + movq(thread, rax); + popq(rax); + } +} + +bool MacroAssembler::needs_explicit_null_check(int offset) { + return offset < 0 || (int)os::vm_page_size() <= offset; +} diff --git a/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp b/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp new file mode 100644 index 000000000..cb85f306b --- /dev/null +++ b/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp @@ -0,0 +1,251 @@ +/* + * Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +// The following alternative implementations are needed because +// Windows 95 doesn't support (some of) the corresponding Windows NT +// calls. Furthermore, these versions allow inlining in the caller. +// (More precisely: The documentation for InterlockedExchange says +// it is supported for Windows 95. However, when single-stepping +// through the assembly code we cannot step into the routine and +// when looking at the routine address we see only garbage code. +// Better safe then sorry!). Was bug 7/31/98 (gri). +// +// Performance note: On uniprocessors, the 'lock' prefixes are not +// necessary (and expensive). We should generate separate cases if +// this becomes a performance problem. + +#pragma warning(disable: 4035) // Disables warnings reporting missing return statement + +inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; } +inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; } +inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; } + +inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; } +inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; } + +inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; } +inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; } +inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; } + + +inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; } +inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; } + +// Adding a lock prefix to an instruction on MP machine +// VC++ doesn't like the lock prefix to be on a single line +// so we can't insert a label after the lock prefix. +// By emitting a lock prefix, we can define a label after it. +#define LOCK_IF_MP(mp) __asm cmp mp, 0 \ + __asm je L0 \ + __asm _emit 0xF0 \ + __asm L0: + +#ifdef AMD64 +inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; } +inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; } + +inline jint Atomic::add (jint add_value, volatile jint* dest) { + return (jint)(*os::atomic_add_func)(add_value, dest); +} + +inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { + return (intptr_t)(*os::atomic_add_ptr_func)(add_value, dest); +} + +inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) { + return (void*)(*os::atomic_add_ptr_func)(add_value, (volatile intptr_t*)dest); +} + +inline void Atomic::inc (volatile jint* dest) { + (void)add (1, dest); +} + +inline void Atomic::inc_ptr(volatile intptr_t* dest) { + (void)add_ptr(1, dest); +} + +inline void Atomic::inc_ptr(volatile void* dest) { + (void)add_ptr(1, dest); +} + +inline void Atomic::dec (volatile jint* dest) { + (void)add (-1, dest); +} + +inline void Atomic::dec_ptr(volatile intptr_t* dest) { + (void)add_ptr(-1, dest); +} + +inline void Atomic::dec_ptr(volatile void* dest) { + (void)add_ptr(-1, dest); +} + +inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) { + return (jint)(*os::atomic_xchg_func)(exchange_value, dest); +} + +inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) { + return (intptr_t)(os::atomic_xchg_ptr_func)(exchange_value, dest); +} + +inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) { + return (void *)(os::atomic_xchg_ptr_func)((intptr_t)exchange_value, (volatile intptr_t*)dest); +} + +inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { + return (*os::atomic_cmpxchg_func)(exchange_value, dest, compare_value); +} + +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { + return (*os::atomic_cmpxchg_long_func)(exchange_value, dest, compare_value); +} + +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { + return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +} + +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { + return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +} + +#else // !AMD64 + +//inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; } +//inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; } +inline jint Atomic::add (jint add_value, volatile jint* dest) { + int mp = os::is_MP(); + __asm { + mov edx, dest; + mov eax, add_value; + mov ecx, eax; + LOCK_IF_MP(mp) + xadd dword ptr [edx], eax; + add eax, ecx; + } +} + +inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { + return (intptr_t)add((jint)add_value, (volatile jint*)dest); +} + +inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) { + return (void*)add((jint)add_value, (volatile jint*)dest); +} + +inline void Atomic::inc (volatile jint* dest) { + // alternative for InterlockedIncrement + int mp = os::is_MP(); + __asm { + mov edx, dest; + LOCK_IF_MP(mp) + add dword ptr [edx], 1; + } +} + +inline void Atomic::inc_ptr(volatile intptr_t* dest) { + inc((volatile jint*)dest); +} + +inline void Atomic::inc_ptr(volatile void* dest) { + inc((volatile jint*)dest); +} + +inline void Atomic::dec (volatile jint* dest) { + // alternative for InterlockedDecrement + int mp = os::is_MP(); + __asm { + mov edx, dest; + LOCK_IF_MP(mp) + sub dword ptr [edx], 1; + } +} + +inline void Atomic::dec_ptr(volatile intptr_t* dest) { + dec((volatile jint*)dest); +} + +inline void Atomic::dec_ptr(volatile void* dest) { + dec((volatile jint*)dest); +} + +inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) { + // alternative for InterlockedExchange + __asm { + mov eax, exchange_value; + mov ecx, dest; + xchg eax, dword ptr [ecx]; + } +} + +inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) { + return (intptr_t)xchg((jint)exchange_value, (volatile jint*)dest); +} + +inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) { + return (void*)xchg((jint)exchange_value, (volatile jint*)dest); +} + +inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { + // alternative for InterlockedCompareExchange + int mp = os::is_MP(); + __asm { + mov edx, dest + mov ecx, exchange_value + mov eax, compare_value + LOCK_IF_MP(mp) + cmpxchg dword ptr [edx], ecx + } +} + +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { + int mp = os::is_MP(); + jint ex_lo = (jint)exchange_value; + jint ex_hi = *( ((jint*)&exchange_value) + 1 ); + jint cmp_lo = (jint)compare_value; + jint cmp_hi = *( ((jint*)&compare_value) + 1 ); + __asm { + push ebx + push edi + mov eax, cmp_lo + mov edx, cmp_hi + mov edi, dest + mov ebx, ex_lo + mov ecx, ex_hi + LOCK_IF_MP(mp) + cmpxchg8b qword ptr [edi] + pop edi + pop ebx + } +} + +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { + return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); +} + +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { + return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); +} +#endif // AMD64 + +#pragma warning(default: 4035) // Enables warnings reporting missing return statement diff --git a/src/os_cpu/windows_x86/vm/bytes_windows_x86.inline.hpp b/src/os_cpu/windows_x86/vm/bytes_windows_x86.inline.hpp new file mode 100644 index 000000000..345bfbd38 --- /dev/null +++ b/src/os_cpu/windows_x86/vm/bytes_windows_x86.inline.hpp @@ -0,0 +1,82 @@ +/* + * Copyright 1998 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#pragma warning(disable: 4035) // Disable warning 4035: no return value + +// Efficient swapping of data bytes from Java byte +// ordering to native byte ordering and vice versa. +inline u2 Bytes::swap_u2(u2 x) { +#ifdef AMD64 + address p = (address) &x; + return ( (u2(p[0]) << 8 ) | ( u2(p[1])) ); +#else + __asm { + mov ax, x + xchg al, ah + } + // no return statement needed, result is already in ax + // compiler warning C4035 disabled via warning pragma +#endif // AMD64 +} + +inline u4 Bytes::swap_u4(u4 x) { +#ifdef AMD64 + address p = (address) &x; + return ( (u4(p[0]) << 24) | (u4(p[1]) << 16) | (u4(p[2]) << 8) | u4(p[3])) ; +#else + __asm { + mov eax, x + bswap eax + } + // no return statement needed, result is already in eax + // compiler warning C4035 disabled via warning pragma +#endif // AMD64 +} + +#ifdef AMD64 +inline u8 Bytes::swap_u8(u8 x) { + address p = (address) &x; + return ( (u8(p[0]) << 56) | (u8(p[1]) << 48) | (u8(p[2]) << 40) | (u8(p[3]) << 32) | + (u8(p[4]) << 24) | (u8(p[5]) << 16) | (u8(p[6]) << 8) | u8(p[7])) ; +} + +#else +// Helper function for swap_u8 +inline u8 Bytes::swap_u8_base(u4 x, u4 y) { + __asm { + mov eax, y + mov edx, x + bswap eax + bswap edx + } + // no return statement needed, result is already in edx:eax + // compiler warning C4035 disabled via warning pragma +} + +inline u8 Bytes::swap_u8(u8 x) { + return swap_u8_base(*(u4*)&x, *(((u4*)&x)+1)); +} +#endif // AMD64 + +#pragma warning(default: 4035) // Enable warning 4035: no return value diff --git a/src/os_cpu/windows_x86/vm/copy_windows_x86.inline.hpp b/src/os_cpu/windows_x86/vm/copy_windows_x86.inline.hpp new file mode 100644 index 000000000..2d6c05195 --- /dev/null +++ b/src/os_cpu/windows_x86/vm/copy_windows_x86.inline.hpp @@ -0,0 +1,166 @@ +/* + * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) { + (void)memmove(to, from, count * HeapWordSize); +} + +static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) { +#ifdef AMD64 + switch (count) { + case 8: to[7] = from[7]; + case 7: to[6] = from[6]; + case 6: to[5] = from[5]; + case 5: to[4] = from[4]; + case 4: to[3] = from[3]; + case 3: to[2] = from[2]; + case 2: to[1] = from[1]; + case 1: to[0] = from[0]; + case 0: break; + default: + (void)memcpy(to, from, count * HeapWordSize); + break; + } +#else + (void)memcpy(to, from, count * HeapWordSize); +#endif // AMD64 +} + +static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) { + switch (count) { + case 8: to[7] = from[7]; + case 7: to[6] = from[6]; + case 6: to[5] = from[5]; + case 5: to[4] = from[4]; + case 4: to[3] = from[3]; + case 3: to[2] = from[2]; + case 2: to[1] = from[1]; + case 1: to[0] = from[0]; + case 0: break; + default: while (count-- > 0) { + *to++ = *from++; + } + break; + } +} + +static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) { + (void)memmove(to, from, count * HeapWordSize); +} + +static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) { + pd_disjoint_words(from, to, count); +} + +static void pd_conjoint_bytes(void* from, void* to, size_t count) { + (void)memmove(to, from, count); +} + +static void pd_conjoint_bytes_atomic(void* from, void* to, size_t count) { + pd_conjoint_bytes(from, to, count); +} + +static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) { + // FIXME + (void)memmove(to, from, count << LogBytesPerShort); +} + +static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) { + // FIXME + (void)memmove(to, from, count << LogBytesPerInt); +} + +static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) { +#ifdef AMD64 + assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); + pd_conjoint_oops_atomic((oop*)from, (oop*)to, count); +#else + // Guarantee use of fild/fistp or xmm regs via some asm code, because compilers won't. + __asm { + mov eax, from; + mov edx, to; + mov ecx, count; + cmp eax, edx; + jbe downtest; + jmp uptest; + up: + fild qword ptr [eax]; + fistp qword ptr [edx]; + add eax, 8; + add edx, 8; + uptest: + sub ecx, 1; + jge up; + jmp done; + down: + fild qword ptr [eax][ecx*8]; + fistp qword ptr [edx][ecx*8]; + downtest: + sub ecx, 1; + jge down; + done:; + } +#endif // AMD64 +} + +static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) { + // Do better than this: inline memmove body NEEDS CLEANUP + if (from > to) { + while (count-- > 0) { + // Copy forwards + *to++ = *from++; + } + } else { + from += count - 1; + to += count - 1; + while (count-- > 0) { + // Copy backwards + *to-- = *from--; + } + } +} + +static void pd_arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) { +#ifdef AMD64 + pd_conjoint_bytes_atomic(from, to, count); +#else + pd_conjoint_bytes(from, to, count); +#endif // AMD64 +} + +static void pd_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) { + pd_conjoint_jshorts_atomic((jshort*)from, (jshort*)to, count); +} + +static void pd_arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) { + pd_conjoint_jints_atomic((jint*)from, (jint*)to, count); +} + +static void pd_arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) { + pd_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count); +} + +static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) { + pd_conjoint_oops_atomic((oop*)from, (oop*)to, count); +} diff --git a/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp b/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp new file mode 100644 index 000000000..7c578df70 --- /dev/null +++ b/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +// +// Sets the default values for platform dependent flags used by the runtime system. +// (see globals.hpp) +// +define_pd_global(bool, DontYieldALot, false); + +// Default stack size on Windows is determined by the executable (java.exe +// has a default value of 320K/1MB [32bit/64bit]). Depending on Windows version, changing +// ThreadStackSize to non-zero may have significant impact on memory usage. +// See comments in os_windows.cpp. +define_pd_global(intx, ThreadStackSize, 0); // 0 => use system default +define_pd_global(intx, VMThreadStackSize, 0); // 0 => use system default + +define_pd_global(intx, SurvivorRatio, 8); + +#ifdef ASSERT +define_pd_global(intx, CompilerThreadStackSize, 1024); +#else +define_pd_global(intx, CompilerThreadStackSize, 0); +#endif + +define_pd_global(uintx, JVMInvokeMethodSlack, 8192); + +// Only used on 64 bit Windows platforms +define_pd_global(bool, UseVectoredExceptions, false); diff --git a/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp b/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp new file mode 100644 index 000000000..b0a98bb0b --- /dev/null +++ b/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp @@ -0,0 +1,210 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#pragma warning(disable: 4035) // Disables warnings reporting missing return statement + +// Implementation of class OrderAccess. + +inline void OrderAccess::loadload() { acquire(); } +inline void OrderAccess::storestore() { release(); } +inline void OrderAccess::loadstore() { acquire(); } +inline void OrderAccess::storeload() { fence(); } + +inline void OrderAccess::acquire() { +#ifndef AMD64 + __asm { + mov eax, dword ptr [esp]; + } +#endif // !AMD64 +} + +inline void OrderAccess::release() { + // A volatile store has release semantics. + dummy = 0; +} + +inline void OrderAccess::fence() { +#ifdef AMD64 + (*os::fence_func)(); +#else + if (os::is_MP()) { + __asm { + lock add dword ptr [esp], 0; + } + } +#endif // AMD64 +} + +inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } +inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } +inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } +inline jlong OrderAccess::load_acquire(volatile jlong* p) { return *p; } +inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } +inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } +inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } +inline julong OrderAccess::load_acquire(volatile julong* p) { return *p; } +inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } +inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; } + +inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; } +inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; } +inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; } + +inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } +inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } +inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } +inline void OrderAccess::release_store(volatile jlong* p, jlong v) { *p = v; } +inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } +inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } +inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } +inline void OrderAccess::release_store(volatile julong* p, julong v) { *p = v; } +inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } +inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; } + +inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; } +inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; } + +inline void OrderAccess::store_fence(jbyte* p, jbyte v) { +#ifdef AMD64 + *p = v; fence(); +#else + __asm { + mov edx, p; + mov al, v; + xchg al, byte ptr [edx]; + } +#endif // AMD64 +} + +inline void OrderAccess::store_fence(jshort* p, jshort v) { +#ifdef AMD64 + *p = v; fence(); +#else + __asm { + mov edx, p; + mov ax, v; + xchg ax, word ptr [edx]; + } +#endif // AMD64 +} + +inline void OrderAccess::store_fence(jint* p, jint v) { +#ifdef AMD64 + *p = v; fence(); +#else + __asm { + mov edx, p; + mov eax, v; + xchg eax, dword ptr [edx]; + } +#endif // AMD64 +} + +inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jubyte* p, jubyte v) { store_fence((jbyte*)p, (jbyte)v); } +inline void OrderAccess::store_fence(jushort* p, jushort v) { store_fence((jshort*)p, (jshort)v); } +inline void OrderAccess::store_fence(juint* p, juint v) { store_fence((jint*)p, (jint)v); } +inline void OrderAccess::store_fence(julong* p, julong v) { store_fence((jlong*)p, (jlong)v); } +inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); } + +inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { +#ifdef AMD64 + *p = v; fence(); +#else + store_fence((jint*)p, (jint)v); +#endif // AMD64 +} + +inline void OrderAccess::store_ptr_fence(void** p, void* v) { +#ifdef AMD64 + *p = v; fence(); +#else + store_fence((jint*)p, (jint)v); +#endif // AMD64 +} + +// Must duplicate definitions instead of calling store_fence because we don't want to cast away volatile. +inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { +#ifdef AMD64 + *p = v; fence(); +#else + __asm { + mov edx, p; + mov al, v; + xchg al, byte ptr [edx]; + } +#endif // AMD64 +} + +inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { +#ifdef AMD64 + *p = v; fence(); +#else + __asm { + mov edx, p; + mov ax, v; + xchg ax, word ptr [edx]; + } +#endif // AMD64 +} + +inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { +#ifdef AMD64 + *p = v; fence(); +#else + __asm { + mov edx, p; + mov eax, v; + xchg eax, dword ptr [edx]; + } +#endif // AMD64 +} + +inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { *p = v; fence(); } + +inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store_fence((volatile jbyte*)p, (jbyte)v); } +inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store_fence((volatile jshort*)p, (jshort)v); } +inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store_fence((volatile jint*)p, (jint)v); } +inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store_fence((volatile jlong*)p, (jlong)v); } +inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } +inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); } + +inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { +#ifdef AMD64 + *p = v; fence(); +#else + release_store_fence((volatile jint*)p, (jint)v); +#endif // AMD64 +} + +inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { +#ifdef AMD64 + *(void* volatile *)p = v; fence(); +#else + release_store_fence((volatile jint*)p, (jint)v); +#endif // AMD64 +} + +#pragma warning(default: 4035) // Enables warnings reporting missing return statement diff --git a/src/os_cpu/windows_x86/vm/os_windows_x86.cpp b/src/os_cpu/windows_x86/vm/os_windows_x86.cpp new file mode 100644 index 000000000..a25040459 --- /dev/null +++ b/src/os_cpu/windows_x86/vm/os_windows_x86.cpp @@ -0,0 +1,478 @@ +/* + * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +// do not include precompiled header file +# include "incls/_os_windows_x86.cpp.incl" +# include "unwind_windows_x86.hpp" +#undef REG_SP +#undef REG_FP +#undef REG_PC +#ifdef AMD64 +#define REG_SP Rsp +#define REG_FP Rbp +#define REG_PC Rip +#else +#define REG_SP Esp +#define REG_FP Ebp +#define REG_PC Eip +#endif // AMD64 + +extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* ); + +// Install a win32 structured exception handler around thread. +void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) { + __try { + +#ifndef AMD64 + // We store the current thread in this wrapperthread location + // and determine how far away this address is from the structured + // execption pointer that FS:[0] points to. This get_thread + // code can then get the thread pointer via FS. + // + // Warning: This routine must NEVER be inlined since we'd end up with + // multiple offsets. + // + volatile Thread* wrapperthread = thread; + + if ( ThreadLocalStorage::get_thread_ptr_offset() == 0 ) { + int thread_ptr_offset; + __asm { + lea eax, dword ptr wrapperthread; + sub eax, dword ptr FS:[0H]; + mov thread_ptr_offset, eax + }; + ThreadLocalStorage::set_thread_ptr_offset(thread_ptr_offset); + } +#ifdef ASSERT + // Verify that the offset hasn't changed since we initally captured + // it. This might happen if we accidentally ended up with an + // inlined version of this routine. + else { + int test_thread_ptr_offset; + __asm { + lea eax, dword ptr wrapperthread; + sub eax, dword ptr FS:[0H]; + mov test_thread_ptr_offset, eax + }; + assert(test_thread_ptr_offset == ThreadLocalStorage::get_thread_ptr_offset(), + "thread pointer offset from SEH changed"); + } +#endif // ASSERT +#endif // !AMD64 + + f(value, method, args, thread); + } __except(topLevelExceptionFilter((_EXCEPTION_POINTERS*)_exception_info())) { + // Nothing to do. + } +} + +#ifdef AMD64 + +// This is the language specific handler for exceptions +// originating from dynamically generated code. +// We call the standard structured exception handler +// We only expect Continued Execution since we cannot unwind +// from generated code. +LONG HandleExceptionFromCodeCache( + IN PEXCEPTION_RECORD ExceptionRecord, + IN ULONG64 EstablisherFrame, + IN OUT PCONTEXT ContextRecord, + IN OUT PDISPATCHER_CONTEXT DispatcherContext) { + EXCEPTION_POINTERS ep; + LONG result; + + ep.ExceptionRecord = ExceptionRecord; + ep.ContextRecord = ContextRecord; + + result = topLevelExceptionFilter(&ep); + + // We better only get a CONTINUE_EXECUTION from our handler + // since we don't have unwind information registered. + + guarantee( result == EXCEPTION_CONTINUE_EXECUTION, + "Unexpected result from topLevelExceptionFilter"); + + return(ExceptionContinueExecution); +} + + +// Structure containing the Windows Data Structures required +// to register our Code Cache exception handler. +// We put these in the CodeCache since the API requires +// all addresses in these structures are relative to the Code +// area registered with RtlAddFunctionTable. +typedef struct { + char ExceptionHandlerInstr[16]; // jmp HandleExceptionFromCodeCache + RUNTIME_FUNCTION rt; + UNWIND_INFO_EH_ONLY unw; +} DynamicCodeData, *pDynamicCodeData; + +#endif // AMD64 +// +// Register our CodeCache area with the OS so it will dispatch exceptions +// to our topLevelExceptionFilter when we take an exception in our +// dynamically generated code. +// +// Arguments: low and high are the address of the full reserved +// codeCache area +// +bool os::register_code_area(char *low, char *high) { +#ifdef AMD64 + + ResourceMark rm; + + pDynamicCodeData pDCD; + PRUNTIME_FUNCTION prt; + PUNWIND_INFO_EH_ONLY punwind; + + // If we are using Vectored Exceptions we don't need this registration + if (UseVectoredExceptions) return true; + + BufferBlob* b = BufferBlob::create("CodeCache Exception Handler", sizeof (DynamicCodeData)); + CodeBuffer cb(b->instructions_begin(), b->instructions_size()); + MacroAssembler* masm = new MacroAssembler(&cb); + pDCD = (pDynamicCodeData) masm->pc(); + + masm->jump(ExternalAddress((address)&HandleExceptionFromCodeCache)); + masm->flush(); + + // Create an Unwind Structure specifying no unwind info + // other than an Exception Handler + punwind = &pDCD->unw; + punwind->Version = 1; + punwind->Flags = UNW_FLAG_EHANDLER; + punwind->SizeOfProlog = 0; + punwind->CountOfCodes = 0; + punwind->FrameRegister = 0; + punwind->FrameOffset = 0; + punwind->ExceptionHandler = (char *)(&(pDCD->ExceptionHandlerInstr[0])) - + (char*)low; + punwind->ExceptionData[0] = 0; + + // This structure describes the covered dynamic code area. + // Addresses are relative to the beginning on the code cache area + prt = &pDCD->rt; + prt->BeginAddress = 0; + prt->EndAddress = (ULONG)(high - low); + prt->UnwindData = ((char *)punwind - low); + + guarantee(RtlAddFunctionTable(prt, 1, (ULONGLONG)low), + "Failed to register Dynamic Code Exception Handler with RtlAddFunctionTable"); + +#endif // AMD64 + return true; +} + +void os::initialize_thread() { +// Nothing to do. +} + +// Atomics and Stub Functions + +typedef jint xchg_func_t (jint, volatile jint*); +typedef intptr_t xchg_ptr_func_t (intptr_t, volatile intptr_t*); +typedef jint cmpxchg_func_t (jint, volatile jint*, jint); +typedef jlong cmpxchg_long_func_t (jlong, volatile jlong*, jlong); +typedef jint add_func_t (jint, volatile jint*); +typedef intptr_t add_ptr_func_t (intptr_t, volatile intptr_t*); +typedef void fence_func_t (); + +#ifdef AMD64 + +jint os::atomic_xchg_bootstrap(jint exchange_value, volatile jint* dest) { + // try to use the stub: + xchg_func_t* func = CAST_TO_FN_PTR(xchg_func_t*, StubRoutines::atomic_xchg_entry()); + + if (func != NULL) { + os::atomic_xchg_func = func; + return (*func)(exchange_value, dest); + } + assert(Threads::number_of_threads() == 0, "for bootstrap only"); + + jint old_value = *dest; + *dest = exchange_value; + return old_value; +} + +intptr_t os::atomic_xchg_ptr_bootstrap(intptr_t exchange_value, volatile intptr_t* dest) { + // try to use the stub: + xchg_ptr_func_t* func = CAST_TO_FN_PTR(xchg_ptr_func_t*, StubRoutines::atomic_xchg_ptr_entry()); + + if (func != NULL) { + os::atomic_xchg_ptr_func = func; + return (*func)(exchange_value, dest); + } + assert(Threads::number_of_threads() == 0, "for bootstrap only"); + + intptr_t old_value = *dest; + *dest = exchange_value; + return old_value; +} + + +jint os::atomic_cmpxchg_bootstrap(jint exchange_value, volatile jint* dest, jint compare_value) { + // try to use the stub: + cmpxchg_func_t* func = CAST_TO_FN_PTR(cmpxchg_func_t*, StubRoutines::atomic_cmpxchg_entry()); + + if (func != NULL) { + os::atomic_cmpxchg_func = func; + return (*func)(exchange_value, dest, compare_value); + } + assert(Threads::number_of_threads() == 0, "for bootstrap only"); + + jint old_value = *dest; + if (old_value == compare_value) + *dest = exchange_value; + return old_value; +} +#endif // AMD64 + +jlong os::atomic_cmpxchg_long_bootstrap(jlong exchange_value, volatile jlong* dest, jlong compare_value) { + // try to use the stub: + cmpxchg_long_func_t* func = CAST_TO_FN_PTR(cmpxchg_long_func_t*, StubRoutines::atomic_cmpxchg_long_entry()); + + if (func != NULL) { + os::atomic_cmpxchg_long_func = func; + return (*func)(exchange_value, dest, compare_value); + } + assert(Threads::number_of_threads() == 0, "for bootstrap only"); + + jlong old_value = *dest; + if (old_value == compare_value) + *dest = exchange_value; + return old_value; +} + +#ifdef AMD64 + +jint os::atomic_add_bootstrap(jint add_value, volatile jint* dest) { + // try to use the stub: + add_func_t* func = CAST_TO_FN_PTR(add_func_t*, StubRoutines::atomic_add_entry()); + + if (func != NULL) { + os::atomic_add_func = func; + return (*func)(add_value, dest); + } + assert(Threads::number_of_threads() == 0, "for bootstrap only"); + + return (*dest) += add_value; +} + +intptr_t os::atomic_add_ptr_bootstrap(intptr_t add_value, volatile intptr_t* dest) { + // try to use the stub: + add_ptr_func_t* func = CAST_TO_FN_PTR(add_ptr_func_t*, StubRoutines::atomic_add_ptr_entry()); + + if (func != NULL) { + os::atomic_add_ptr_func = func; + return (*func)(add_value, dest); + } + assert(Threads::number_of_threads() == 0, "for bootstrap only"); + + return (*dest) += add_value; +} + +void os::fence_bootstrap() { + // try to use the stub: + fence_func_t* func = CAST_TO_FN_PTR(fence_func_t*, StubRoutines::fence_entry()); + + if (func != NULL) { + os::fence_func = func; + (*func)(); + return; + } + assert(Threads::number_of_threads() == 0, "for bootstrap only"); + + // don't have to do anything for a single thread +} + + +xchg_func_t* os::atomic_xchg_func = os::atomic_xchg_bootstrap; +xchg_ptr_func_t* os::atomic_xchg_ptr_func = os::atomic_xchg_ptr_bootstrap; +cmpxchg_func_t* os::atomic_cmpxchg_func = os::atomic_cmpxchg_bootstrap; +add_func_t* os::atomic_add_func = os::atomic_add_bootstrap; +add_ptr_func_t* os::atomic_add_ptr_func = os::atomic_add_ptr_bootstrap; +fence_func_t* os::fence_func = os::fence_bootstrap; + +#endif // AMD64 + +cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap; + +ExtendedPC os::fetch_frame_from_context(void* ucVoid, + intptr_t** ret_sp, intptr_t** ret_fp) { + + ExtendedPC epc; + CONTEXT* uc = (CONTEXT*)ucVoid; + + if (uc != NULL) { + epc = ExtendedPC((address)uc->REG_PC); + if (ret_sp) *ret_sp = (intptr_t*)uc->REG_SP; + if (ret_fp) *ret_fp = (intptr_t*)uc->REG_FP; + } else { + // construct empty ExtendedPC for return value checking + epc = ExtendedPC(NULL); + if (ret_sp) *ret_sp = (intptr_t *)NULL; + if (ret_fp) *ret_fp = (intptr_t *)NULL; + } + + return epc; +} + +frame os::fetch_frame_from_context(void* ucVoid) { + intptr_t* sp; + intptr_t* fp; + ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); + return frame(sp, fp, epc.pc()); +} + +// VC++ does not save frame pointer on stack in optimized build. It +// can be turned off by /Oy-. If we really want to walk C frames, +// we can use the StackWalk() API. +frame os::get_sender_for_C_frame(frame* fr) { + return frame(fr->sender_sp(), fr->link(), fr->sender_pc()); +} + + +#ifndef AMD64 +intptr_t* _get_previous_fp() { + intptr_t **frameptr; + __asm { + mov frameptr, ebp + }; + return *frameptr; +} +#endif // !AMD64 + +frame os::current_frame() { + +#ifdef AMD64 + // apparently _asm not supported on windows amd64 + typedef intptr_t* get_fp_func (); + get_fp_func* func = CAST_TO_FN_PTR(get_fp_func*, + StubRoutines::amd64::get_previous_fp_entry()); + if (func == NULL) return frame(NULL, NULL, NULL); + intptr_t* fp = (*func)(); +#else + intptr_t* fp = _get_previous_fp(); +#endif // AMD64 + + frame myframe((intptr_t*)os::current_stack_pointer(), + (intptr_t*)fp, + CAST_FROM_FN_PTR(address, os::current_frame)); + if (os::is_first_C_frame(&myframe)) { + // stack is not walkable + return frame(NULL, NULL, NULL); + } else { + return os::get_sender_for_C_frame(&myframe); + } +} + +void os::print_context(outputStream *st, void *context) { + if (context == NULL) return; + + CONTEXT* uc = (CONTEXT*)context; + + st->print_cr("Registers:"); +#ifdef AMD64 + st->print( "EAX=" INTPTR_FORMAT, uc->Rax); + st->print(", EBX=" INTPTR_FORMAT, uc->Rbx); + st->print(", ECX=" INTPTR_FORMAT, uc->Rcx); + st->print(", EDX=" INTPTR_FORMAT, uc->Rdx); + st->cr(); + st->print( "ESP=" INTPTR_FORMAT, uc->Rsp); + st->print(", EBP=" INTPTR_FORMAT, uc->Rbp); + st->print(", ESI=" INTPTR_FORMAT, uc->Rsi); + st->print(", EDI=" INTPTR_FORMAT, uc->Rdi); + st->cr(); + st->print( "EIP=" INTPTR_FORMAT, uc->Rip); + st->print(", EFLAGS=" INTPTR_FORMAT, uc->EFlags); +#else + st->print( "EAX=" INTPTR_FORMAT, uc->Eax); + st->print(", EBX=" INTPTR_FORMAT, uc->Ebx); + st->print(", ECX=" INTPTR_FORMAT, uc->Ecx); + st->print(", EDX=" INTPTR_FORMAT, uc->Edx); + st->cr(); + st->print( "ESP=" INTPTR_FORMAT, uc->Esp); + st->print(", EBP=" INTPTR_FORMAT, uc->Ebp); + st->print(", ESI=" INTPTR_FORMAT, uc->Esi); + st->print(", EDI=" INTPTR_FORMAT, uc->Edi); + st->cr(); + st->print( "EIP=" INTPTR_FORMAT, uc->Eip); + st->print(", EFLAGS=" INTPTR_FORMAT, uc->EFlags); +#endif // AMD64 + st->cr(); + st->cr(); + + intptr_t *sp = (intptr_t *)uc->REG_SP; + st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp); + print_hex_dump(st, (address)sp, (address)(sp + 32), sizeof(intptr_t)); + st->cr(); + + // Note: it may be unsafe to inspect memory near pc. For example, pc may + // point to garbage if entry point in an nmethod is corrupted. Leave + // this at the end, and hope for the best. + address pc = (address)uc->REG_PC; + st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); + print_hex_dump(st, pc - 16, pc + 16, sizeof(char)); + st->cr(); +} + +extern "C" int SafeFetch32 (int * adr, int Err) { + int rv = Err ; + _try { + rv = *((volatile int *) adr) ; + } __except(EXCEPTION_EXECUTE_HANDLER) { + } + return rv ; +} + +extern "C" intptr_t SafeFetchN (intptr_t * adr, intptr_t Err) { + intptr_t rv = Err ; + _try { + rv = *((volatile intptr_t *) adr) ; + } __except(EXCEPTION_EXECUTE_HANDLER) { + } + return rv ; +} + +extern "C" int SpinPause () { +#ifdef AMD64 + return 0 ; +#else + // pause == rep:nop + // On systems that don't support pause a rep:nop + // is executed as a nop. The rep: prefix is ignored. + _asm { + pause ; + }; + return 1 ; +#endif // AMD64 +} + + +void os::setup_fpu() { +#ifndef AMD64 + int fpu_cntrl_word = StubRoutines::fpu_cntrl_wrd_std(); + __asm fldcw fpu_cntrl_word; +#endif // !AMD64 +} diff --git a/src/os_cpu/windows_x86/vm/os_windows_x86.hpp b/src/os_cpu/windows_x86/vm/os_windows_x86.hpp new file mode 100644 index 000000000..d75781016 --- /dev/null +++ b/src/os_cpu/windows_x86/vm/os_windows_x86.hpp @@ -0,0 +1,63 @@ +/* + * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + + // + // NOTE: we are back in class os here, not win32 + // +#ifdef AMD64 + static jint (*atomic_xchg_func) (jint, volatile jint*); + static intptr_t (*atomic_xchg_ptr_func) (intptr_t, volatile intptr_t*); + + static jint (*atomic_cmpxchg_func) (jint, volatile jint*, jint); + static jlong (*atomic_cmpxchg_long_func) (jlong, volatile jlong*, jlong); + + static jint (*atomic_add_func) (jint, volatile jint*); + static intptr_t (*atomic_add_ptr_func) (intptr_t, volatile intptr_t*); + + static void (*fence_func) (); + + + static jint atomic_xchg_bootstrap (jint, volatile jint*); + static intptr_t atomic_xchg_ptr_bootstrap (intptr_t, volatile intptr_t*); + + static jint atomic_cmpxchg_bootstrap (jint, volatile jint*, jint); +#else + + static jlong (*atomic_cmpxchg_long_func) (jlong, volatile jlong*, jlong); + +#endif // AMD64 + + static jlong atomic_cmpxchg_long_bootstrap(jlong, volatile jlong*, jlong); + +#ifdef AMD64 + static jint atomic_add_bootstrap (jint, volatile jint*); + static intptr_t atomic_add_ptr_bootstrap (intptr_t, volatile intptr_t*); + + static void fence_bootstrap (); +#endif // AMD64 + + static void setup_fpu(); + static bool supports_sse() { return true; } + + static bool register_code_area(char *low, char *high); diff --git a/src/os_cpu/windows_x86/vm/prefetch_windows_x86.inline.hpp b/src/os_cpu/windows_x86/vm/prefetch_windows_x86.inline.hpp new file mode 100644 index 000000000..d40d3418a --- /dev/null +++ b/src/os_cpu/windows_x86/vm/prefetch_windows_x86.inline.hpp @@ -0,0 +1,26 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +inline void Prefetch::read (void *loc, intx interval) {} +inline void Prefetch::write(void *loc, intx interval) {} diff --git a/src/os_cpu/windows_x86/vm/threadLS_windows_x86.cpp b/src/os_cpu/windows_x86/vm/threadLS_windows_x86.cpp new file mode 100644 index 000000000..c46f115d3 --- /dev/null +++ b/src/os_cpu/windows_x86/vm/threadLS_windows_x86.cpp @@ -0,0 +1,48 @@ +/* + * Copyright 1998-2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +// Provides an entry point we can link against and +// a buffer we can emit code into. The buffer is +// filled by ThreadLocalStorage::generate_code_for_get_thread +// and called from ThreadLocalStorage::thread() + +#include "incls/_precompiled.incl" +#include "incls/_threadLS_windows_x86.cpp.incl" + +int ThreadLocalStorage::_thread_ptr_offset = 0; + +static void call_wrapper_dummy() {} + +// We need to call the os_exception_wrapper once so that it sets +// up the offset from FS of the thread pointer. +void ThreadLocalStorage::generate_code_for_get_thread() { + os::os_exception_wrapper( (java_call_t)call_wrapper_dummy, + NULL, NULL, NULL, NULL); +} + +void ThreadLocalStorage::pd_init() { } + +void ThreadLocalStorage::pd_set_thread(Thread* thread) { + os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); +} diff --git a/src/os_cpu/windows_x86/vm/threadLS_windows_x86.hpp b/src/os_cpu/windows_x86/vm/threadLS_windows_x86.hpp new file mode 100644 index 000000000..e295abe22 --- /dev/null +++ b/src/os_cpu/windows_x86/vm/threadLS_windows_x86.hpp @@ -0,0 +1,44 @@ +/* + * Copyright 1998-2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +// Processor dependent parts of ThreadLocalStorage + +protected: + + static int _thread_ptr_offset; + +public: + + // Java Thread + static inline Thread* thread() { + return (Thread*)TlsGetValue(thread_index()); + } + + static inline Thread* get_thread() { + return (Thread*)TlsGetValue(thread_index()); + } + + static inline void set_thread_ptr_offset( int offset ) { _thread_ptr_offset = offset; } + + static inline int get_thread_ptr_offset() { return _thread_ptr_offset; } diff --git a/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp b/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp new file mode 100644 index 000000000..a11a746af --- /dev/null +++ b/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp @@ -0,0 +1,86 @@ +/* + * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#include "incls/_precompiled.incl" +#include "incls/_thread_windows_x86.cpp.incl" + +// For Forte Analyzer AsyncGetCallTrace profiling support - thread is +// currently interrupted by SIGPROF +bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, + void* ucontext, bool isInJava) { + + assert(Thread::current() == this, "caller must be current thread"); + assert(this->is_Java_thread(), "must be JavaThread"); + + JavaThread* jt = (JavaThread *)this; + + // If we have a last_Java_frame, then we should use it even if + // isInJava == true. It should be more reliable than CONTEXT info. + if (jt->has_last_Java_frame()) { + *fr_addr = jt->pd_last_frame(); + return true; + } + + // At this point, we don't have a last_Java_frame, so + // we try to glean some information out of the CONTEXT + // if we were running Java code when SIGPROF came in. + if (isInJava) { + CONTEXT* uc = (CONTEXT*)ucontext; + +#ifdef AMD64 + intptr_t* ret_fp = (intptr_t*) uc->Rbp; + intptr_t* ret_sp = (intptr_t*) uc->Rsp; + ExtendedPC addr = ExtendedPC((address)uc->Rip); +#else + intptr_t* ret_fp = (intptr_t*) uc->Ebp; + intptr_t* ret_sp = (intptr_t*) uc->Esp; + ExtendedPC addr = ExtendedPC((address)uc->Eip); +#endif // AMD64 + if (addr.pc() == NULL || ret_sp == NULL ) { + // CONTEXT wasn't useful + return false; + } + + frame ret_frame(ret_sp, ret_fp, addr.pc()); + if (!ret_frame.safe_for_sender(jt)) { +#ifdef COMPILER2 + // C2 uses ebp as a general register see if NULL fp helps + frame ret_frame2(ret_sp, NULL, addr.pc()); + if (!ret_frame2.safe_for_sender(jt)) { + // nothing else to try if the frame isn't good + return false; + } + ret_frame = ret_frame2; +#else + // nothing else to try if the frame isn't good + return false; +#endif /* COMPILER2 */ + } + *fr_addr = ret_frame; + return true; + } + + // nothing else to try + return false; +} diff --git a/src/os_cpu/windows_x86/vm/thread_windows_x86.hpp b/src/os_cpu/windows_x86/vm/thread_windows_x86.hpp new file mode 100644 index 000000000..8e61fdd92 --- /dev/null +++ b/src/os_cpu/windows_x86/vm/thread_windows_x86.hpp @@ -0,0 +1,62 @@ +/* + * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + + private: + void pd_initialize() { + _anchor.clear(); + } + + frame pd_last_frame() { + assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); + if (_anchor.last_Java_pc() != NULL) { + return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); + } else { + // This will pick up pc from sp + return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp()); + } + } + + public: + // Mutators are highly dangerous.... + intptr_t* last_Java_fp() { return _anchor.last_Java_fp(); } + void set_last_Java_fp(intptr_t* fp) { _anchor.set_last_Java_fp(fp); } + + void set_base_of_stack_pointer(intptr_t* base_sp) {} + + + static ByteSize last_Java_fp_offset() { + return byte_offset_of(JavaThread, _anchor) + JavaFrameAnchor::last_Java_fp_offset(); + } + + intptr_t* base_of_stack_pointer() { return NULL; } + void record_base_of_stack_pointer() {} + + bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, + bool isInJava); + + // These routines are only used on cpu architectures that + // have separate register stacks (Itanium). + static bool register_stack_overflow() { return false; } + static void enable_register_stack_guard() {} + static void disable_register_stack_guard() {} diff --git a/src/os_cpu/windows_x86/vm/unwind_windows_x86.hpp b/src/os_cpu/windows_x86/vm/unwind_windows_x86.hpp new file mode 100644 index 000000000..1e8ed078d --- /dev/null +++ b/src/os_cpu/windows_x86/vm/unwind_windows_x86.hpp @@ -0,0 +1,78 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + + +#ifdef AMD64 +typedef unsigned char UBYTE; + +#define UNW_FLAG_EHANDLER 0x01 +#define UNW_FLAG_UHANDLER 0x02 +#define UNW_FLAG_CHAININFO 0x04 + +// This structure is used to define an UNWIND_INFO that +// only has an ExceptionHandler. There are no UnwindCodes +// declared. +typedef struct _UNWIND_INFO_EH_ONLY { + UBYTE Version : 3; + UBYTE Flags : 5; + UBYTE SizeOfProlog; + UBYTE CountOfCodes; + UBYTE FrameRegister : 4; + UBYTE FrameOffset : 4; + union { + OPTIONAL ULONG ExceptionHandler; + OPTIONAL ULONG FunctionEntry; + }; + OPTIONAL ULONG ExceptionData[1]; +} UNWIND_INFO_EH_ONLY, *PUNWIND_INFO_EH_ONLY; + + +/* +typedef struct _RUNTIME_FUNCTION { + ULONG BeginAddress; + ULONG EndAddress; + ULONG UnwindData; +} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION; +*/ + +typedef struct _DISPATCHER_CONTEXT { + ULONG64 ControlPc; + ULONG64 ImageBase; + PRUNTIME_FUNCTION FunctionEntry; + ULONG64 EstablisherFrame; + ULONG64 TargetIp; + PCONTEXT ContextRecord; +// PEXCEPTION_ROUTINE LanguageHandler; + char * LanguageHandler; // double dependency problem + PVOID HandlerData; +} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; + +typedef EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE) ( + IN PEXCEPTION_RECORD ExceptionRecord, + IN ULONG64 EstablisherFrame, + IN OUT PCONTEXT ContextRecord, + IN OUT PDISPATCHER_CONTEXT DispatcherContext +); + +#endif // AMD64 diff --git a/src/os_cpu/windows_x86/vm/vmStructs_windows_x86.hpp b/src/os_cpu/windows_x86/vm/vmStructs_windows_x86.hpp new file mode 100644 index 000000000..bf2c029b4 --- /dev/null +++ b/src/os_cpu/windows_x86/vm/vmStructs_windows_x86.hpp @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +// These are the OS and CPU-specific fields, types and integer +// constants required by the Serviceability Agent. This file is +// referenced by vmStructs.cpp. + +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ + \ + /******************************/ \ + /* Threads (NOTE: incomplete) */ \ + /******************************/ \ + \ + nonstatic_field(OSThread, _thread_id, unsigned long) \ + unchecked_nonstatic_field(OSThread, _thread_handle, sizeof(HANDLE)) /* NOTE: no type */ \ + \ + /* This must be the last entry, and must be present */ \ + last_entry() + +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ + \ + /* This must be the last entry, and must be present */ \ + last_entry() + +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ + \ + /* This must be the last entry, and must be present */ \ + last_entry() + +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ + \ + /* This must be the last entry, and must be present */ \ + last_entry() diff --git a/src/os_cpu/windows_x86/vm/vm_version_windows_x86.cpp b/src/os_cpu/windows_x86/vm/vm_version_windows_x86.cpp new file mode 100644 index 000000000..c3abce485 --- /dev/null +++ b/src/os_cpu/windows_x86/vm/vm_version_windows_x86.cpp @@ -0,0 +1,26 @@ +/* + * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +# include "incls/_precompiled.incl" +# include "incls/_vm_version_windows_x86.cpp.incl" diff --git a/src/os_cpu/windows_x86/vm/windows_x86_32.ad b/src/os_cpu/windows_x86/vm/windows_x86_32.ad new file mode 100644 index 000000000..83a5421c1 --- /dev/null +++ b/src/os_cpu/windows_x86/vm/windows_x86_32.ad @@ -0,0 +1,158 @@ +// +// Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +// CA 95054 USA or visit www.sun.com if you need additional information or +// have any questions. +// +// + +// X86 Win32 Architecture Description File + +//----------OS-DEPENDENT ENCODING BLOCK----------------------------------------------------- +// This block specifies the encoding classes used by the compiler to output +// byte streams. Encoding classes generate functions which are called by +// Machine Instruction Nodes in order to generate the bit encoding of the +// instruction. Operands specify their base encoding interface with the +// interface keyword. There are currently supported four interfaces, +// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an +// operand to generate a function which returns its register number when +// queried. CONST_INTER causes an operand to generate a function which +// returns the value of the constant when queried. MEMORY_INTER causes an +// operand to generate four functions which return the Base Register, the +// Index Register, the Scale Value, and the Offset Value of the operand when +// queried. COND_INTER causes an operand to generate six functions which +// return the encoding code (ie - encoding bits for the instruction) +// associated with each basic boolean condition for a conditional instruction. +// Instructions specify two basic values for encoding. They use the +// ins_encode keyword to specify their encoding class (which must be one of +// the class names specified in the encoding block), and they use the +// opcode keyword to specify, in order, their primary, secondary, and +// tertiary opcode. Only the opcode sections which a particular instruction +// needs for encoding need to be specified. +encode %{ + // Build emit functions for each basic byte or larger field in the intel + // encoding scheme (opcode, rm, sib, immediate), and call them from C++ + // code in the enc_class source block. Emit functions will live in the + // main source block for now. In future, we can generalize this by + // adding a syntax that specifies the sizes of fields in an order, + // so that the adlc can build the emit functions automagically + + enc_class tlsencode (eRegP dst, eRegP src) %{ + emit_rm(cbuf, 0x2, $dst$$reg, $src$$reg); + emit_d32(cbuf, ThreadLocalStorage::get_thread_ptr_offset() ); + %} + + enc_class call_epilog %{ + if( VerifyStackAtCalls ) { + // Check that stack depth is unchanged: find majik cookie on stack + int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP,-3*VMRegImpl::slots_per_word)); + if(framesize >= 128) { + emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood + emit_d8(cbuf,0xBC); + emit_d8(cbuf,0x24); + emit_d32(cbuf,framesize); // Find majik cookie from ESP + emit_d32(cbuf, 0xbadb100d); + } + else { + emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood + emit_d8(cbuf,0x7C); + emit_d8(cbuf,0x24); + emit_d8(cbuf,framesize); // Find majik cookie from ESP + emit_d32(cbuf, 0xbadb100d); + } + // jmp EQ around INT3 + emit_opcode(cbuf,0x74); + emit_d8(cbuf,1); + // Die if stack mismatch + emit_opcode(cbuf,0xCC); + } + %} + +%} + +// INSTRUCTIONS -- Platform dependent + + +//----------OS and Locking Instructions---------------------------------------- + +// The prefix of this name is KNOWN by the ADLC and cannot be changed. +instruct tlsLoadP_prefixLoadP(eRegP t1) %{ + effect(DEF t1); + + format %{ "MOV $t1,FS:[0x00] "%} + opcode(0x8B, 0x64); + ins_encode(OpcS, OpcP, conmemref(t1)); + ins_pipe( ialu_reg_fat ); +%} + +// This name is KNOWN by the ADLC and cannot be changed. +// The ADLC forces a 'TypeRawPtr::BOTTOM' output type +// for this guy. +// %%% Should do this with a clause like: bottom_type(TypeRawPtr::BOTTOM); +instruct tlsLoadP(eRegP dst, eRegP t1) %{ + effect(DEF dst, USE t1); + + format %{ "MOV $dst,[$t1 + TLS::thread_ptr_offset()]" %} + opcode(0x8B); + ins_encode(OpcP, tlsencode(dst, t1)); + ins_pipe( ialu_reg_reg_fat ); +%} + +instruct TLS(eRegP dst) %{ + match(Set dst (ThreadLocal)); + expand %{ + eRegP t1; + tlsLoadP_prefixLoadP(t1); + tlsLoadP(dst, t1); + %} +%} + +// Die now +instruct ShouldNotReachHere( ) +%{ + match(Halt); + // Use the following format syntax + format %{ "INT3 ; ShouldNotReachHere" %} + opcode(0xCC); + ins_encode(OpcP); + ins_pipe( pipe_slow ); +%} + +// +// Platform dependent source +// +source %{ + +// emit an interrupt that is caught by the debugger +void emit_break(CodeBuffer &cbuf) { + *(cbuf.code_end()) = (unsigned char)(0xcc); + cbuf.set_code_end(cbuf.code_end() + 1); +} + +void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + emit_break(cbuf); +} + + +uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { + return 1; +} + + +%} diff --git a/src/os_cpu/windows_x86/vm/windows_x86_64.ad b/src/os_cpu/windows_x86/vm/windows_x86_64.ad new file mode 100644 index 000000000..0ef5a15bf --- /dev/null +++ b/src/os_cpu/windows_x86/vm/windows_x86_64.ad @@ -0,0 +1,159 @@ +// +// Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +// CA 95054 USA or visit www.sun.com if you need additional information or +// have any questions. +// +// + +// AMD64 Win32 Architecture Description File + +//----------OS-DEPENDENT ENCODING BLOCK----------------------------------------------------- +// This block specifies the encoding classes used by the compiler to output +// byte streams. Encoding classes generate functions which are called by +// Machine Instruction Nodes in order to generate the bit encoding of the +// instruction. Operands specify their base encoding interface with the +// interface keyword. There are currently supported four interfaces, +// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an +// operand to generate a function which returns its register number when +// queried. CONST_INTER causes an operand to generate a function which +// returns the value of the constant when queried. MEMORY_INTER causes an +// operand to generate four functions which return the Base Register, the +// Index Register, the Scale Value, and the Offset Value of the operand when +// queried. COND_INTER causes an operand to generate six functions which +// return the encoding code (ie - encoding bits for the instruction) +// associated with each basic boolean condition for a conditional instruction. +// Instructions specify two basic values for encoding. They use the +// ins_encode keyword to specify their encoding class (which must be one of +// the class names specified in the encoding block), and they use the +// opcode keyword to specify, in order, their primary, secondary, and +// tertiary opcode. Only the opcode sections which a particular instruction +// needs for encoding need to be specified. +encode %{ + // Build emit functions for each basic byte or larger field in the intel + // encoding scheme (opcode, rm, sib, immediate), and call them from C++ + // code in the enc_class source block. Emit functions will live in the + // main source block for now. In future, we can generalize this by + // adding a syntax that specifies the sizes of fields in an order, + // so that the adlc can build the emit functions automagically + + enc_class Java_To_Runtime (method meth) %{ // CALL Java_To_Runtime + // No relocation needed + + // movq r10, <meth> + emit_opcode(cbuf, Assembler::REX_WB); + emit_opcode(cbuf, 0xB8 | (R10_enc - 8)); + emit_d64(cbuf, (int64_t) $meth$$method); + + // call (r10) + emit_opcode(cbuf, Assembler::REX_B); + emit_opcode(cbuf, 0xFF); + emit_opcode(cbuf, 0xD0 | (R10_enc - 8)); + %} + + enc_class call_epilog %{ + if (VerifyStackAtCalls) { + // Check that stack depth is unchanged: find majik cookie on stack + int framesize = + ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3*VMRegImpl::slots_per_word)); + if (framesize) { + if (framesize < 0x80) { + emit_opcode(cbuf, Assembler::REX_W); + emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood + emit_d8(cbuf, 0x7C); + emit_d8(cbuf, 0x24); + emit_d8(cbuf, framesize); // Find majik cookie from ESP + emit_d32(cbuf, 0xbadb100d); + } else { + emit_opcode(cbuf, Assembler::REX_W); + emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood + emit_d8(cbuf, 0xBC); + emit_d8(cbuf, 0x24); + emit_d32(cbuf, framesize); // Find majik cookie from ESP + emit_d32(cbuf, 0xbadb100d); + } + } + // jmp EQ around INT3 + // QQQ TODO + const int jump_around = 5; // size of call to breakpoint, 1 for CC + emit_opcode(cbuf, 0x74); + emit_d8(cbuf, jump_around); + // QQQ temporary + emit_break(cbuf); + // Die if stack mismatch + // emit_opcode(cbuf,0xCC); + } + %} +%} + +// INSTRUCTIONS -- Platform dependent + + +//----------OS and Locking Instructions---------------------------------------- + +// This name is KNOWN by the ADLC and cannot be changed. +// The ADLC forces a 'TypeRawPtr::BOTTOM' output type +// for this guy. +instruct tlsLoadP(r15_RegP dst) +%{ + match(Set dst (ThreadLocal)); + effect(DEF dst); + + size(0); + format %{ "# TLS is in R15" %} + ins_encode( /*empty encoding*/ ); + ins_pipe(ialu_reg_reg); +%} + +// Die now +instruct ShouldNotReachHere( ) +%{ + match(Halt); + // Use the following format syntax + format %{ "INT3 ; ShouldNotReachHere" %} + opcode(0xCC); + ins_encode(OpcP); + ins_pipe( pipe_slow ); +%} + +// +// Platform dependent source +// +source %{ + +int MachCallRuntimeNode::ret_addr_offset() +{ + return 13; // movq r10,#addr; callq (r10) +} + +// emit an interrupt that is caught by the debugger +void emit_break(CodeBuffer &cbuf) { + *(cbuf.code_end()) = (unsigned char)(0xcc); + cbuf.set_code_end(cbuf.code_end() + 1); +} + +void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + emit_break(cbuf); +} + +uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { + return 1; +} + +%} |