1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* -*- tab-width: 4 -*- */
4 /* ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is [Open Source Virtual Machine.].
19 * The Initial Developer of the Original Code is
20 * Adobe System Incorporated.
21 * Portions created by the Initial Developer are Copyright (C) 1993-2006
22 * the Initial Developer. All Rights Reserved.
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
41 #ifndef __avmplus_win32_platform__
42 #define __avmplus_win32_platform__
47 * We have avmplus.vcproj compiled with the /W4 warning level
48 * which is quite picky. Disable warnings we don't care about.
51 #pragma warning(disable:4946) // reinterpret_cast used between related classes (bugzilla 615964)
52 #pragma warning(disable:4127) // conditional expression is constant - appears to be compiler noise primarily
53 #pragma warning(disable:4201) // nonstandard extension used : nameless struct/union
54 #pragma warning(disable:4251) // X needs to have dll-interface to be used by clients of class Y
55 #pragma warning(disable:4310) // cast truncates constant value
56 #pragma warning(disable:4511) // can't generate copy ctor
57 #pragma warning(disable:4512) // assignment operator could not be generated
58 #pragma warning(disable:4611) // interaction between '_setjmp' and C++ object destruction is non-portable
59 #pragma warning(disable:4725) // instruction may be inaccurate on some Pentiums
61 // enable some that are off even in /W4 mode, but are still handy
62 #pragma warning(default:4242) // 'identifier' : conversion from 'type1' to 'type2', possible loss of data
63 #pragma warning(default:4263) // 'function' : member function does not override any base class virtual member function
64 #pragma warning(default:4264) // 'virtual_function' : no override available for virtual member function from base 'class'; function is hidden
65 #pragma warning(default:4265) // 'class' : class has virtual functions, but destructor is not virtual
66 #pragma warning(default:4266) // 'function' : no override available for virtual member function from base 'type'; function is hidden
67 #pragma warning(default:4296) // expression is always true (false) (Generally, an unsigned variable was used in a comparison operation with zero.)
68 #pragma warning(default:4905) // wide string literal cast to 'LPSTR'
69 #pragma warning(default:4906) // string literal cast to 'LPWSTR'
71 // some that might be useful to turn on someday, but would require too much twiddly code tweaking right now
72 // #pragma warning(error:4820) // 'bytes' bytes padding added after construct 'member_name' (MSFT system headers generate zillions of these, sadly)
75 * Disable PREfast analysis warnings that complain about legitimate usage.
78 // These are triggered by the use of named constants for configuration purposes.
79 // There is nothing wrong with using these in preference to preprocessor conditionalization.
80 #pragma warning(disable:6237) // (<zero> && <expression>) is always zero
81 #pragma warning(disable:6239) // (<non-zero constant> && <expression>) always evaluates to the result of <expression>
83 // This needs to be fixed, but reflects our generally cavalier treatment of stack overflow
84 #pragma warning(disable:6255) // _alloca indicates failure by raising a stack overflow exception
88 #define VMPI_memcpy ::memcpy
89 #define VMPI_memset ::memset
90 #define VMPI_memcmp ::memcmp
91 #define VMPI_memmove ::memmove
92 #define VMPI_memchr ::memchr
93 #define VMPI_strcmp ::strcmp
94 #define VMPI_strcat ::strcat
95 #define VMPI_strchr ::strchr
96 #define VMPI_strrchr ::strrchr
97 #define VMPI_strcpy ::strcpy
98 #define VMPI_strlen ::strlen
99 #define VMPI_strncat ::strncat
100 #define VMPI_strncmp ::strncmp
101 #define VMPI_strncpy ::strncpy
102 #define VMPI_strtol ::strtol
103 #define VMPI_strstr ::strstr
105 #define VMPI_sprintf ::sprintf
106 #define VMPI_sscanf ::sscanf
108 // Print rest args into s according to format. The size of s is n. A NUL
109 // terminator is always written. Returns the number of characters written,
110 // not including the NUL. (Hence the return value is always 0..n-1.)
112 int VMPI_snprintf(char *s
, size_t n
, const char *format
, ...);
114 // As for VMPI_snprintf but with an argument list instead of rest args.
116 int VMPI_vsnprintf(char *s
, size_t n
, const char *format
, va_list args
);
118 #define VMPI_atoi ::atoi
119 // these aren't prefixed b/c off winmo/pcre problems with ? : expressions
120 #define VMPI_tolower tolower
121 #define VMPI_islower islower
122 #define VMPI_toupper toupper
123 #define VMPI_isupper isupper
124 #define VMPI_isdigit isdigit
125 #define VMPI_isalnum isalnum
126 #define VMPI_isxdigit isxdigit
127 #define VMPI_isspace isspace
128 #define VMPI_isgraph isgraph
129 #define VMPI_isprint isprint
130 #define VMPI_ispunct ispunct
131 #define VMPI_iscntrl iscntrl
132 #define VMPI_isalpha isalpha
134 #define VMPI_abort() ::TerminateProcess(GetCurrentProcess(), 0)
136 #define VMPI_abort ::abort
139 #define VMPI_exit ::exit
155 #if defined(UNDER_CE)
156 // winmo complains if we try to include <new> and it complains if someone else includes new before us so...
157 #ifndef __PLACEMENT_NEW_INLINE
158 #define __PLACEMENT_NEW_INLINE
159 inline void* operator new(size_t, void* p
) { return p
; }
162 // others want the system new
167 // Windows Mobile doesn't provide intptr_t or uintptr_t
168 typedef __int32
intptr_t;
169 typedef unsigned __int32
uintptr_t;
172 typedef void *maddr_ptr
;
174 // Set up a jmp_buf suitable for VMPI_longjmpNoUnwind.
175 //#define VMPI_setjmpNoUnwind ::setjmp
177 // Jump to an active jmp_buf that was set up by VMPI_setjmpNoUnwind.
178 // Under no circumstances may C++ destructors be unwound during the
179 // jump (MSVC likes to do this by default).
180 //#define VMPI_longjmpNoUnwind ::longjmp
183 #include <setjmpex.h>
186 _int64 __cdecl
longjmp64(jmp_buf jmpbuf
, _int64 arg
);
188 #define VMPI_setjmpNoUnwind ::setjmp
189 #define VMPI_longjmpNoUnwind ::longjmp64
192 #define VMPI_setjmpNoUnwind ::setjmp
193 #define VMPI_longjmpNoUnwind ::longjmp
197 // Newer versions of the Windows SDK set up the intrinsics slightly differently
198 // than VC8. Only include intrin.h if the SDK doesn't declare it.
199 #ifndef InterlockedBitTestAndSet
202 #include <emmintrin.h>
205 #include "JITProfiling.h"
209 // Windows doesn't support inttypes.h or most C99 types directly
210 typedef __int8
int8_t;
211 typedef __int16
int16_t;
212 typedef __int32
int32_t;
213 typedef __int64
int64_t;
214 typedef unsigned __int8
uint8_t;
215 typedef unsigned __int16
uint16_t;
216 typedef unsigned __int32
uint32_t;
217 typedef unsigned __int64
uint64_t;
219 // This must come after all the include files
220 #if defined _MSC_VER && !defined DEBUG
221 #pragma intrinsic(memcmp)
222 #pragma intrinsic(memcpy)
223 #pragma intrinsic(memset)
224 #pragma intrinsic(strlen)
225 #pragma intrinsic(strcpy)
226 #pragma intrinsic(strcat)
230 #define REALLY_INLINE __forceinline
231 #define FASTCALL __fastcall
233 #define FASTCALL __attribute__((fastcall))
238 #if defined(_MSC_VER)
239 #define AVMPLUS_ALIGN8(type) __declspec(align(8)) type
240 #define AVMPLUS_ALIGN16(type) __declspec(align(16)) type
241 #elif defined(__GNUC__)
242 #define AVMPLUS_ALIGN8(type) type __attribute__ ((aligned (8)))
243 #define AVMPLUS_ALIGN16(type) type __attribute__ ((aligned (16)))
245 #error "Unrecognized compiler"
248 #if defined(_MSC_VER) && _MSC_VER < 1400 && defined(VMCFG_NANOJIT)
249 #define NJ_NO_VARIADIC_MACROS
253 * Type defintion for an opaque data type representing platform-defined spin lock
254 * @see VMPI_lockInit(), VMPI_lockAcquire()
256 struct vmpi_spin_lock_t
261 REALLY_INLINE
void VMPI_lockInit(vmpi_spin_lock_t
* lock
)
266 REALLY_INLINE
void VMPI_lockDestroy(vmpi_spin_lock_t
* lock
)
271 REALLY_INLINE
bool VMPI_lockAcquire(vmpi_spin_lock_t
*lock
)
274 while (::InterlockedCompareExchange((LPLONG
)&lock
->lock
, 1, 0) != 0)
277 // We used to reset to zero if we got to 100. This resets to 0 at 64 instead, with no branch.
279 // if tries == 0, we just rolled over 64, so we Sleep(1) to give other threads a chance to run... otherwise we Sleep(0)
285 REALLY_INLINE
bool VMPI_lockRelease(vmpi_spin_lock_t
*lock
)
287 ::InterlockedExchange((LPLONG
)&lock
->lock
, 0);
291 REALLY_INLINE
bool VMPI_lockTestAndAcquire(vmpi_spin_lock_t
*lock
)
293 return ::InterlockedCompareExchange((LPLONG
)&lock
->lock
, 1, 0) == 0;
296 REALLY_INLINE
int32_t VMPI_atomicIncAndGet32WithBarrier(volatile int32_t* value
)
299 return InterlockedIncrement(const_cast<LONG
*>((volatile LONG
*)value
)); // Barrier semantics are not actually documented
301 return InterlockedIncrement((volatile LONG
*)value
);
305 REALLY_INLINE
int32_t VMPI_atomicIncAndGet32(volatile int32_t* value
)
307 // No barrier-less version is available
308 return VMPI_atomicIncAndGet32WithBarrier(value
);
311 REALLY_INLINE
int32_t VMPI_atomicDecAndGet32WithBarrier(volatile int32_t* value
)
314 return InterlockedDecrement(const_cast<LONG
*>((volatile LONG
*)value
)); // Barrier semantics are not actually documented
316 return InterlockedDecrement((volatile LONG
*)value
);
320 REALLY_INLINE
int32_t VMPI_atomicDecAndGet32(volatile int32_t* value
)
322 // No barrier-less version is available
323 return VMPI_atomicDecAndGet32WithBarrier(value
);
326 REALLY_INLINE
bool VMPI_compareAndSwap32WithBarrier(int32_t oldValue
, int32_t newValue
, volatile int32_t* address
)
329 return InterlockedCompareExchange(const_cast<LONG
*>((volatile LONG
*)address
), newValue
, oldValue
) == oldValue
; // Barrier semantics are not actually documented
331 return InterlockedCompareExchange((volatile LONG
*)address
, newValue
, oldValue
) == oldValue
;
335 REALLY_INLINE
bool VMPI_compareAndSwap32(int32_t oldValue
, int32_t newValue
, volatile int32_t* address
)
337 return VMPI_compareAndSwap32WithBarrier(oldValue
, newValue
, address
);
340 REALLY_INLINE
void VMPI_memoryBarrier()
342 // FIXME: bug 609820 Memory barrier (fence) for win32
344 // void MemoryBarrier(void) is only available >= Vista
345 // This is a temp solution until we have a x86 asm version.
346 volatile int32_t dummy
;
347 VMPI_atomicIncAndGet32WithBarrier(&dummy
);
351 * Threads waiting on a conditional variable are recorded in a list
352 * of WaitingThread structs.
354 struct WaitingThread
{
361 * A condition variable is implemented as a linked list of waiting threads.
362 * The variable itself needs to record only the head and the tail of the list.
364 struct vmpi_condvar_t
{
369 typedef DWORD vmpi_thread_t
;
370 typedef CRITICAL_SECTION vmpi_mutex_t
;
371 typedef LPVOID vmpi_thread_arg_t
; // Argument type for thread start function
372 typedef DWORD vmpi_thread_rtn_t
; // Return type for thread start function
373 typedef LPTHREAD_START_ROUTINE vmpi_thread_start_t
;
375 struct vmpi_thread_attr_t
{
381 #define VMPI_THREAD_START_CC WINAPI
383 REALLY_INLINE
bool VMPI_recursiveMutexInit(vmpi_mutex_t
* mutex
)
385 InitializeCriticalSection(mutex
);
389 REALLY_INLINE
bool VMPI_recursiveMutexDestroy(vmpi_mutex_t
* mutex
)
391 DeleteCriticalSection(mutex
);
395 REALLY_INLINE
bool VMPI_recursiveMutexTryLock(vmpi_mutex_t
* mutex
)
397 return TryEnterCriticalSection(mutex
) != 0;
400 REALLY_INLINE
void VMPI_recursiveMutexLock(vmpi_mutex_t
* mutex
)
402 EnterCriticalSection(mutex
);
405 REALLY_INLINE
void VMPI_recursiveMutexUnlock(vmpi_mutex_t
* mutex
)
407 LeaveCriticalSection(mutex
);
410 REALLY_INLINE
bool VMPI_condVarInit(vmpi_condvar_t
* condvar
)
412 condvar
->head
= NULL
;
413 condvar
->tail
= NULL
;
417 REALLY_INLINE
bool VMPI_condVarDestroy(vmpi_condvar_t
* condvar
)
423 REALLY_INLINE vmpi_thread_t
VMPI_currentThread()
425 return (vmpi_thread_t
) (uintptr_t)GetCurrentThreadId();
428 REALLY_INLINE
bool VMPI_tlsSetValue(uintptr_t tlsId
, void* value
)
430 return TlsSetValue((DWORD
)tlsId
, value
) == TRUE
;
433 REALLY_INLINE
void* VMPI_tlsGetValue(uintptr_t tlsId
)
435 return TlsGetValue((DWORD
)tlsId
);
438 REALLY_INLINE
void VMPI_threadYield()
447 #endif // __avmplus_win32_platform__