summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2022-04-16 16:23:23 +0000
committerMoonchild <moonchild@palemoon.org>2022-04-16 16:23:23 +0000
commit08842d77aef11d7d9690feba8e8707315a511f88 (patch)
tree8dc33a4d3fd940f6f0c042de1db4c5d284e0e877 /js
parent1191c9e371ba878ccd53f9a8ca44b6a3f348a439 (diff)
parentf5c363c01db0ece0ce58e47ca2e63f677f07ff1c (diff)
downloaduxp-08842d77aef11d7d9690feba8e8707315a511f88.tar.gz
Merge pull request 'Issue #1818 Cleanup some old GCC hacks' (#1865) from trav90/UXP-contrib:compiler-hacks-cleanup into master
Reviewed-on: https://repo.palemoon.org/MoonchildProductions/UXP/pulls/1865
Diffstat (limited to 'js')
-rw-r--r--js/src/gc/Heap.h4
-rw-r--r--js/src/jit/Safepoints.cpp6
-rw-r--r--js/src/jit/arm/Architecture-arm.h3
-rw-r--r--js/src/jit/arm/AtomicOperations-arm.h76
-rw-r--r--js/src/jit/arm/Simulator-arm.cpp2
-rw-r--r--js/src/jit/arm64/vixl/Assembler-vixl.h4
-rw-r--r--js/src/jit/arm64/vixl/MozAssembler-vixl.cpp2
-rw-r--r--js/src/jit/mips-shared/AtomicOperations-mips-shared.h76
-rw-r--r--js/src/jit/none/AtomicOperations-ppc.h76
-rw-r--r--js/src/jit/none/AtomicOperations-sparc.h76
-rw-r--r--js/src/jit/x86-shared/AtomicOperations-x86-shared.h108
-rw-r--r--js/src/old-configure.in13
-rw-r--r--js/src/wasm/WasmBaselineCompile.cpp4
13 files changed, 7 insertions, 443 deletions
diff --git a/js/src/gc/Heap.h b/js/src/gc/Heap.h
index 2f27702601..2a10420943 100644
--- a/js/src/gc/Heap.h
+++ b/js/src/gc/Heap.h
@@ -80,9 +80,7 @@ enum InitialHeap {
};
/* The GC allocation kinds. */
-// FIXME: uint8_t would make more sense for the underlying type, but causes
-// miscompilations in GCC (fixed in 4.8.5 and 4.9.3). See also bug 1143966.
-enum class AllocKind {
+enum class AllocKind : uint8_t {
FIRST,
OBJECT_FIRST = FIRST,
FUNCTION = FIRST,
diff --git a/js/src/jit/Safepoints.cpp b/js/src/jit/Safepoints.cpp
index 9446861a0b..27cb642542 100644
--- a/js/src/jit/Safepoints.cpp
+++ b/js/src/jit/Safepoints.cpp
@@ -264,11 +264,7 @@ AllocationToPartKind(const LAllocation& a)
return Part_Arg;
}
-// gcc 4.5 doesn't actually inline CanEncodeInfoInHeader when only
-// using the "inline" keyword, and miscompiles the function as well
-// when doing block reordering with branch prediction information.
-// See bug 799295 comment 71.
-static MOZ_ALWAYS_INLINE bool
+static inline bool
CanEncodeInfoInHeader(const LAllocation& a, uint32_t* out)
{
if (a.isGeneralReg()) {
diff --git a/js/src/jit/arm/Architecture-arm.h b/js/src/jit/arm/Architecture-arm.h
index d2c634798b..5dbc68a599 100644
--- a/js/src/jit/arm/Architecture-arm.h
+++ b/js/src/jit/arm/Architecture-arm.h
@@ -13,8 +13,7 @@
#include "js/Utility.h"
-// GCC versions 4.6 and above define __ARM_PCS_VFP to denote a hard-float
-// ABI target.
+// GCC defines __ARM_PCS_VFP to denote a hard-float ABI target.
#if defined(__ARM_PCS_VFP)
#define JS_CODEGEN_ARM_HARDFP
#endif
diff --git a/js/src/jit/arm/AtomicOperations-arm.h b/js/src/jit/arm/AtomicOperations-arm.h
index e10b348c0a..f9ca690c07 100644
--- a/js/src/jit/arm/AtomicOperations-arm.h
+++ b/js/src/jit/arm/AtomicOperations-arm.h
@@ -12,18 +12,6 @@
#if defined(__clang__) || defined(__GNUC__)
-// The default implementation tactic for gcc/clang is to use the newer
-// __atomic intrinsics added for use in C++11 <atomic>. Where that
-// isn't available, we use GCC's older __sync functions instead.
-//
-// ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS is kept as a backward
-// compatible option for older compilers: enable this to use GCC's old
-// __sync functions instead of the newer __atomic functions. This
-// will be required for GCC 4.6.x and earlier, and probably for Clang
-// 3.1, should we need to use those versions.
-
-//#define ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
-
inline bool
js::jit::AtomicOperations::isLockfree8()
{
@@ -37,24 +25,16 @@ js::jit::AtomicOperations::isLockfree8()
//
// For now, make the JIT defer to the C++ compiler when we know what
// the C++ compiler will do, otherwise assume a lock is needed.
-# ifndef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int8_t), 0));
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int16_t), 0));
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int32_t), 0));
return HasLDSTREXBHD() && __atomic_always_lock_free(sizeof(int64_t), 0);
-# else
- return false;
-# endif
}
inline void
js::jit::AtomicOperations::fenceSeqCst()
{
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_synchronize();
-# else
__atomic_thread_fence(__ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -62,14 +42,8 @@ inline T
js::jit::AtomicOperations::loadSeqCst(T* addr)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_synchronize();
- T v = *addr;
- __sync_synchronize();
-# else
T v;
__atomic_load(addr, &v, __ATOMIC_SEQ_CST);
-# endif
return v;
}
@@ -78,13 +52,7 @@ inline void
js::jit::AtomicOperations::storeSeqCst(T* addr, T val)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_synchronize();
- *addr = val;
- __sync_synchronize();
-# else
__atomic_store(addr, &val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -92,18 +60,9 @@ inline T
js::jit::AtomicOperations::exchangeSeqCst(T* addr, T val)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- T v;
- __sync_synchronize();
- do {
- v = *addr;
- } while (__sync_val_compare_and_swap(addr, v, val) != v);
- return v;
-# else
T v;
__atomic_exchange(addr, &val, &v, __ATOMIC_SEQ_CST);
return v;
-# endif
}
template<typename T>
@@ -111,12 +70,8 @@ inline T
js::jit::AtomicOperations::compareExchangeSeqCst(T* addr, T oldval, T newval)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_val_compare_and_swap(addr, oldval, newval);
-# else
__atomic_compare_exchange(addr, &oldval, &newval, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return oldval;
-# endif
}
template<typename T>
@@ -124,11 +79,7 @@ inline T
js::jit::AtomicOperations::fetchAddSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_add(addr, val);
-# else
return __atomic_fetch_add(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -136,11 +87,7 @@ inline T
js::jit::AtomicOperations::fetchSubSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_sub(addr, val);
-# else
return __atomic_fetch_sub(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -148,11 +95,7 @@ inline T
js::jit::AtomicOperations::fetchAndSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_and(addr, val);
-# else
return __atomic_fetch_and(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -160,11 +103,7 @@ inline T
js::jit::AtomicOperations::fetchOrSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_or(addr, val);
-# else
return __atomic_fetch_or(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -172,11 +111,7 @@ inline T
js::jit::AtomicOperations::fetchXorSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_xor(addr, val);
-# else
return __atomic_fetch_xor(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -209,17 +144,12 @@ template<size_t nbytes>
inline void
js::jit::RegionLock::acquire(void* addr)
{
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- while (!__sync_bool_compare_and_swap(&spinlock, 0, 1))
- ;
-# else
uint32_t zero = 0;
uint32_t one = 1;
while (!__atomic_compare_exchange(&spinlock, &zero, &one, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) {
zero = 0;
continue;
}
-# endif
}
template<size_t nbytes>
@@ -227,16 +157,10 @@ inline void
js::jit::RegionLock::release(void* addr)
{
MOZ_ASSERT(AtomicOperations::loadSeqCst(&spinlock) == 1, "releasing unlocked region lock");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_sub_and_fetch(&spinlock, 1);
-# else
uint32_t zero = 0;
__atomic_store(&spinlock, &zero, __ATOMIC_SEQ_CST);
-# endif
}
-# undef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
-
#elif defined(ENABLE_SHARED_ARRAY_BUFFER)
# error "Either disable JS shared memory at compile time, use GCC or Clang, or add code here"
diff --git a/js/src/jit/arm/Simulator-arm.cpp b/js/src/jit/arm/Simulator-arm.cpp
index 2b295212a5..5dfdb939a0 100644
--- a/js/src/jit/arm/Simulator-arm.cpp
+++ b/js/src/jit/arm/Simulator-arm.cpp
@@ -1289,8 +1289,6 @@ int32_t
Simulator::get_register(int reg) const
{
MOZ_ASSERT(reg >= 0 && reg < num_registers);
- // Work around GCC bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
- if (reg >= num_registers) return 0;
return registers_[reg] + ((reg == pc) ? SimInstruction::kPCReadOffset : 0);
}
diff --git a/js/src/jit/arm64/vixl/Assembler-vixl.h b/js/src/jit/arm64/vixl/Assembler-vixl.h
index d209f8b570..175349bf56 100644
--- a/js/src/jit/arm64/vixl/Assembler-vixl.h
+++ b/js/src/jit/arm64/vixl/Assembler-vixl.h
@@ -4016,11 +4016,9 @@ class Assembler : public MozBaseAssembler {
const MemOperand& addr,
LoadStoreScalingOption option = PreferScaledOffset);
- // TODO(all): The third parameter should be passed by reference but gcc 4.8.2
- // reports a bogus uninitialised warning then.
BufferOffset Logical(const Register& rd,
const Register& rn,
- const Operand operand,
+ const Operand& operand,
LogicalOp op);
BufferOffset LogicalImmediate(const Register& rd,
const Register& rn,
diff --git a/js/src/jit/arm64/vixl/MozAssembler-vixl.cpp b/js/src/jit/arm64/vixl/MozAssembler-vixl.cpp
index 3b2e0a8bc6..a9bb8a18d9 100644
--- a/js/src/jit/arm64/vixl/MozAssembler-vixl.cpp
+++ b/js/src/jit/arm64/vixl/MozAssembler-vixl.cpp
@@ -400,7 +400,7 @@ void Assembler::nop(Instruction* at) {
BufferOffset Assembler::Logical(const Register& rd, const Register& rn,
- const Operand operand, LogicalOp op)
+ const Operand& operand, LogicalOp op)
{
VIXL_ASSERT(rd.size() == rn.size());
if (operand.IsImmediate()) {
diff --git a/js/src/jit/mips-shared/AtomicOperations-mips-shared.h b/js/src/jit/mips-shared/AtomicOperations-mips-shared.h
index dee9302300..7441a27e87 100644
--- a/js/src/jit/mips-shared/AtomicOperations-mips-shared.h
+++ b/js/src/jit/mips-shared/AtomicOperations-mips-shared.h
@@ -13,22 +13,9 @@
#if defined(__clang__) || defined(__GNUC__)
-// The default implementation tactic for gcc/clang is to use the newer
-// __atomic intrinsics added for use in C++11 <atomic>. Where that
-// isn't available, we use GCC's older __sync functions instead.
-//
-// ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS is kept as a backward
-// compatible option for older compilers: enable this to use GCC's old
-// __sync functions instead of the newer __atomic functions. This
-// will be required for GCC 4.6.x and earlier, and probably for Clang
-// 3.1, should we need to use those versions.
-
-//#define ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
-
inline bool
js::jit::AtomicOperations::isLockfree8()
{
-# ifndef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int8_t), 0));
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int16_t), 0));
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int32_t), 0));
@@ -36,19 +23,12 @@ js::jit::AtomicOperations::isLockfree8()
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int64_t), 0));
# endif
return true;
-# else
- return false;
-# endif
}
inline void
js::jit::AtomicOperations::fenceSeqCst()
{
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_synchronize();
-# else
__atomic_thread_fence(__ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -56,14 +36,8 @@ inline T
js::jit::AtomicOperations::loadSeqCst(T* addr)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_synchronize();
- T v = *addr;
- __sync_synchronize();
-# else
T v;
__atomic_load(addr, &v, __ATOMIC_SEQ_CST);
-# endif
return v;
}
@@ -72,13 +46,7 @@ inline void
js::jit::AtomicOperations::storeSeqCst(T* addr, T val)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_synchronize();
- *addr = val;
- __sync_synchronize();
-# else
__atomic_store(addr, &val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -86,12 +54,8 @@ inline T
js::jit::AtomicOperations::compareExchangeSeqCst(T* addr, T oldval, T newval)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_val_compare_and_swap(addr, oldval, newval);
-# else
__atomic_compare_exchange(addr, &oldval, &newval, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return oldval;
-# endif
}
template<typename T>
@@ -99,11 +63,7 @@ inline T
js::jit::AtomicOperations::fetchAddSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_add(addr, val);
-# else
return __atomic_fetch_add(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -111,11 +71,7 @@ inline T
js::jit::AtomicOperations::fetchSubSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_sub(addr, val);
-# else
return __atomic_fetch_sub(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -123,11 +79,7 @@ inline T
js::jit::AtomicOperations::fetchAndSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_and(addr, val);
-# else
return __atomic_fetch_and(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -135,11 +87,7 @@ inline T
js::jit::AtomicOperations::fetchOrSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_or(addr, val);
-# else
return __atomic_fetch_or(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -147,11 +95,7 @@ inline T
js::jit::AtomicOperations::fetchXorSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_xor(addr, val);
-# else
return __atomic_fetch_xor(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -185,35 +129,21 @@ inline T
js::jit::AtomicOperations::exchangeSeqCst(T* addr, T val)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- T v;
- __sync_synchronize();
- do {
- v = *addr;
- } while (__sync_val_compare_and_swap(addr, v, val) != v);
- return v;
-# else
T v;
__atomic_exchange(addr, &val, &v, __ATOMIC_SEQ_CST);
return v;
-# endif
}
template<size_t nbytes>
inline void
js::jit::RegionLock::acquire(void* addr)
{
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- while (!__sync_bool_compare_and_swap(&spinlock, 0, 1))
- ;
-# else
uint32_t zero = 0;
uint32_t one = 1;
while (!__atomic_compare_exchange(&spinlock, &zero, &one, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) {
zero = 0;
continue;
}
-# endif
}
template<size_t nbytes>
@@ -221,16 +151,10 @@ inline void
js::jit::RegionLock::release(void* addr)
{
MOZ_ASSERT(AtomicOperations::loadSeqCst(&spinlock) == 1, "releasing unlocked region lock");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_sub_and_fetch(&spinlock, 1);
-# else
uint32_t zero = 0;
__atomic_store(&spinlock, &zero, __ATOMIC_SEQ_CST);
-# endif
}
-# undef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
-
#elif defined(ENABLE_SHARED_ARRAY_BUFFER)
# error "Either disable JS shared memory at compile time, use GCC or Clang, or add code here"
diff --git a/js/src/jit/none/AtomicOperations-ppc.h b/js/src/jit/none/AtomicOperations-ppc.h
index 182de9f8ac..465c0cf41b 100644
--- a/js/src/jit/none/AtomicOperations-ppc.h
+++ b/js/src/jit/none/AtomicOperations-ppc.h
@@ -13,22 +13,9 @@
#if defined(__clang__) || defined(__GNUC__)
-// The default implementation tactic for gcc/clang is to use the newer
-// __atomic intrinsics added for use in C++11 <atomic>. Where that
-// isn't available, we use GCC's older __sync functions instead.
-//
-// ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS is kept as a backward
-// compatible option for older compilers: enable this to use GCC's old
-// __sync functions instead of the newer __atomic functions. This
-// will be required for GCC 4.6.x and earlier, and probably for Clang
-// 3.1, should we need to use those versions.
-
-//#define ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
-
inline bool
js::jit::AtomicOperations::isLockfree8()
{
-# ifndef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int8_t), 0));
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int16_t), 0));
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int32_t), 0));
@@ -37,19 +24,12 @@ js::jit::AtomicOperations::isLockfree8()
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int64_t), 0));
# endif
return true;
-# else
- return false;
-# endif
}
inline void
js::jit::AtomicOperations::fenceSeqCst()
{
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_synchronize();
-# else
__atomic_thread_fence(__ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -57,14 +37,8 @@ inline T
js::jit::AtomicOperations::loadSeqCst(T* addr)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_synchronize();
- T v = *addr;
- __sync_synchronize();
-# else
T v;
__atomic_load(addr, &v, __ATOMIC_SEQ_CST);
-# endif
return v;
}
@@ -73,13 +47,7 @@ inline void
js::jit::AtomicOperations::storeSeqCst(T* addr, T val)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_synchronize();
- *addr = val;
- __sync_synchronize();
-# else
__atomic_store(addr, &val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -87,12 +55,8 @@ inline T
js::jit::AtomicOperations::compareExchangeSeqCst(T* addr, T oldval, T newval)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_val_compare_and_swap(addr, oldval, newval);
-# else
__atomic_compare_exchange(addr, &oldval, &newval, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return oldval;
-# endif
}
template<typename T>
@@ -100,11 +64,7 @@ inline T
js::jit::AtomicOperations::fetchAddSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_add(addr, val);
-# else
return __atomic_fetch_add(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -112,11 +72,7 @@ inline T
js::jit::AtomicOperations::fetchSubSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_sub(addr, val);
-# else
return __atomic_fetch_sub(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -124,11 +80,7 @@ inline T
js::jit::AtomicOperations::fetchAndSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_and(addr, val);
-# else
return __atomic_fetch_and(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -136,11 +88,7 @@ inline T
js::jit::AtomicOperations::fetchOrSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_or(addr, val);
-# else
return __atomic_fetch_or(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -148,11 +96,7 @@ inline T
js::jit::AtomicOperations::fetchXorSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_xor(addr, val);
-# else
return __atomic_fetch_xor(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -186,35 +130,21 @@ inline T
js::jit::AtomicOperations::exchangeSeqCst(T* addr, T val)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- T v;
- __sync_synchronize();
- do {
- v = *addr;
- } while (__sync_val_compare_and_swap(addr, v, val) != v);
- return v;
-# else
T v;
__atomic_exchange(addr, &val, &v, __ATOMIC_SEQ_CST);
return v;
-# endif
}
template<size_t nbytes>
inline void
js::jit::RegionLock::acquire(void* addr)
{
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- while (!__sync_bool_compare_and_swap(&spinlock, 0, 1))
- ;
-# else
uint32_t zero = 0;
uint32_t one = 1;
while (!__atomic_compare_exchange(&spinlock, &zero, &one, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) {
zero = 0;
continue;
}
-# endif
}
template<size_t nbytes>
@@ -222,16 +152,10 @@ inline void
js::jit::RegionLock::release(void* addr)
{
MOZ_ASSERT(AtomicOperations::loadSeqCst(&spinlock) == 1, "releasing unlocked region lock");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_sub_and_fetch(&spinlock, 1);
-# else
uint32_t zero = 0;
__atomic_store(&spinlock, &zero, __ATOMIC_SEQ_CST);
-# endif
}
-# undef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
-
#elif defined(ENABLE_SHARED_ARRAY_BUFFER)
# error "Either disable JS shared memory, use GCC or Clang, or add code here"
diff --git a/js/src/jit/none/AtomicOperations-sparc.h b/js/src/jit/none/AtomicOperations-sparc.h
index ca689da7e2..c962a524e7 100644
--- a/js/src/jit/none/AtomicOperations-sparc.h
+++ b/js/src/jit/none/AtomicOperations-sparc.h
@@ -13,22 +13,9 @@
#if defined(__clang__) || defined(__GNUC__)
-// The default implementation tactic for gcc/clang is to use the newer
-// __atomic intrinsics added for use in C++11 <atomic>. Where that
-// isn't available, we use GCC's older __sync functions instead.
-//
-// ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS is kept as a backward
-// compatible option for older compilers: enable this to use GCC's old
-// __sync functions instead of the newer __atomic functions. This
-// will be required for GCC 4.6.x and earlier, and probably for Clang
-// 3.1, should we need to use those versions.
-
-//#define ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
-
inline bool
js::jit::AtomicOperations::isLockfree8()
{
-# ifndef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int8_t), 0));
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int16_t), 0));
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int32_t), 0));
@@ -36,19 +23,12 @@ js::jit::AtomicOperations::isLockfree8()
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int64_t), 0));
# endif
return true;
-# else
- return false;
-# endif
}
inline void
js::jit::AtomicOperations::fenceSeqCst()
{
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_synchronize();
-# else
__atomic_thread_fence(__ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -56,14 +36,8 @@ inline T
js::jit::AtomicOperations::loadSeqCst(T* addr)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_synchronize();
- T v = *addr;
- __sync_synchronize();
-# else
T v;
__atomic_load(addr, &v, __ATOMIC_SEQ_CST);
-# endif
return v;
}
@@ -72,13 +46,7 @@ inline void
js::jit::AtomicOperations::storeSeqCst(T* addr, T val)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_synchronize();
- *addr = val;
- __sync_synchronize();
-# else
__atomic_store(addr, &val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -86,12 +54,8 @@ inline T
js::jit::AtomicOperations::compareExchangeSeqCst(T* addr, T oldval, T newval)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_val_compare_and_swap(addr, oldval, newval);
-# else
__atomic_compare_exchange(addr, &oldval, &newval, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return oldval;
-# endif
}
template<typename T>
@@ -101,11 +65,7 @@ js::jit::AtomicOperations::fetchAddSeqCst(T* addr, T val)
#if !defined( __LP64__)
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
#endif
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_add(addr, val);
-# else
return __atomic_fetch_add(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -115,11 +75,7 @@ js::jit::AtomicOperations::fetchSubSeqCst(T* addr, T val)
#if !defined( __LP64__)
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
#endif
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_sub(addr, val);
-# else
return __atomic_fetch_sub(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -129,11 +85,7 @@ js::jit::AtomicOperations::fetchAndSeqCst(T* addr, T val)
#if !defined( __LP64__)
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
#endif
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_and(addr, val);
-# else
return __atomic_fetch_and(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -143,11 +95,7 @@ js::jit::AtomicOperations::fetchOrSeqCst(T* addr, T val)
#if !defined( __LP64__)
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
#endif
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_or(addr, val);
-# else
return __atomic_fetch_or(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -157,11 +105,7 @@ js::jit::AtomicOperations::fetchXorSeqCst(T* addr, T val)
#if !defined( __LP64__)
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
#endif
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_xor(addr, val);
-# else
return __atomic_fetch_xor(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -195,35 +139,21 @@ inline T
js::jit::AtomicOperations::exchangeSeqCst(T* addr, T val)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- T v;
- __sync_synchronize();
- do {
- v = *addr;
- } while (__sync_val_compare_and_swap(addr, v, val) != v);
- return v;
-# else
T v;
__atomic_exchange(addr, &val, &v, __ATOMIC_SEQ_CST);
return v;
-# endif
}
template<size_t nbytes>
inline void
js::jit::RegionLock::acquire(void* addr)
{
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- while (!__sync_bool_compare_and_swap(&spinlock, 0, 1))
- ;
-# else
uint32_t zero = 0;
uint32_t one = 1;
while (!__atomic_compare_exchange(&spinlock, &zero, &one, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) {
zero = 0;
continue;
}
-# endif
}
template<size_t nbytes>
@@ -231,16 +161,10 @@ inline void
js::jit::RegionLock::release(void* addr)
{
MOZ_ASSERT(AtomicOperations::loadSeqCst(&spinlock) == 1, "releasing unlocked region lock");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_sub_and_fetch(&spinlock, 1);
-# else
uint32_t zero = 0;
__atomic_store(&spinlock, &zero, __ATOMIC_SEQ_CST);
-# endif
}
-# undef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
-
#elif defined(ENABLE_SHARED_ARRAY_BUFFER)
# error "Either disable JS shared memory, use GCC or Clang, or add code here"
diff --git a/js/src/jit/x86-shared/AtomicOperations-x86-shared.h b/js/src/jit/x86-shared/AtomicOperations-x86-shared.h
index 1230c7febd..4eee00a3de 100644
--- a/js/src/jit/x86-shared/AtomicOperations-x86-shared.h
+++ b/js/src/jit/x86-shared/AtomicOperations-x86-shared.h
@@ -45,18 +45,6 @@
#if defined(__clang__) || defined(__GNUC__)
-// The default implementation tactic for gcc/clang is to use the newer
-// __atomic intrinsics added for use in C++11 <atomic>. Where that
-// isn't available, we use GCC's older __sync functions instead.
-//
-// ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS is kept as a backward
-// compatible option for older compilers: enable this to use GCC's old
-// __sync functions instead of the newer __atomic functions. This
-// will be required for GCC 4.6.x and earlier, and probably for Clang
-// 3.1, should we need to use those versions.
-
-// #define ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
-
// Lock-free 8-byte atomics are assumed on x86 but must be disabled in
// corner cases, see comments below and in isLockfree8().
@@ -77,15 +65,11 @@
inline bool
js::jit::AtomicOperations::isLockfree8()
{
-# ifndef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int8_t), 0));
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int16_t), 0));
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int32_t), 0));
-# endif
# ifdef LOCKFREE8
-# ifndef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
MOZ_ASSERT(__atomic_always_lock_free(sizeof(int64_t), 0));
-# endif
return true;
# else
return false;
@@ -95,11 +79,7 @@ js::jit::AtomicOperations::isLockfree8()
inline void
js::jit::AtomicOperations::fenceSeqCst()
{
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_synchronize();
-# else
__atomic_thread_fence(__ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -107,16 +87,8 @@ inline T
js::jit::AtomicOperations::loadSeqCst(T* addr)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- // Inhibit compiler reordering with a volatile load. The x86 does
- // not reorder loads with respect to subsequent loads or stores
- // and no ordering barrier is required here. See more elaborate
- // comments in storeSeqCst.
- T v = *static_cast<T volatile*>(addr);
-# else
T v;
__atomic_load(addr, &v, __ATOMIC_SEQ_CST);
-# endif
return v;
}
@@ -141,43 +113,7 @@ inline void
js::jit::AtomicOperations::storeSeqCst(T* addr, T val)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- // Inhibit compiler reordering with a volatile store. The x86 may
- // reorder a store with respect to a subsequent load from a
- // different location, hence there is an ordering barrier here to
- // prevent that.
- //
- // By way of background, look to eg
- // http://bartoszmilewski.com/2008/11/05/who-ordered-memory-fences-on-an-x86/
- //
- // Consider:
- //
- // uint8_t x = 0, y = 0; // to start
- //
- // thread1:
- // sx: AtomicOperations::store(&x, 1);
- // gy: uint8_t obs1 = AtomicOperations::loadSeqCst(&y);
- //
- // thread2:
- // sy: AtomicOperations::store(&y, 1);
- // gx: uint8_t obs2 = AtomicOperations::loadSeqCst(&x);
- //
- // Sequential consistency requires a total global ordering of
- // operations: sx-gy-sy-gx, sx-sy-gx-gy, sx-sy-gy-gx, sy-gx-sx-gy,
- // sy-sx-gy-gx, or sy-sx-gx-gy. In every ordering at least one of
- // sx-before-gx or sy-before-gy happens, so *at least one* of
- // obs1/obs2 is 1.
- //
- // If AtomicOperations::{load,store}SeqCst were just volatile
- // {load,store}, x86 could reorder gx/gy before each thread's
- // prior load. That would permit gx-gy-sx-sy: both loads would be
- // 0! Thus after a volatile store we must synchronize to ensure
- // the store happens before the load.
- *static_cast<T volatile*>(addr) = val;
- __sync_synchronize();
-# else
__atomic_store(addr, &val, __ATOMIC_SEQ_CST);
-# endif
}
# ifndef LOCKFREE8
@@ -201,19 +137,9 @@ inline T
js::jit::AtomicOperations::exchangeSeqCst(T* addr, T val)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- T v;
- do {
- // Here I assume the compiler will not hoist the load. It
- // shouldn't, because the CAS could affect* addr.
- v = *addr;
- } while (!__sync_bool_compare_and_swap(addr, v, val));
- return v;
-# else
T v;
__atomic_exchange(addr, &val, &v, __ATOMIC_SEQ_CST);
return v;
-# endif
}
# ifndef LOCKFREE8
@@ -237,12 +163,8 @@ inline T
js::jit::AtomicOperations::compareExchangeSeqCst(T* addr, T oldval, T newval)
{
MOZ_ASSERT(sizeof(T) < 8 || isLockfree8());
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_val_compare_and_swap(addr, oldval, newval);
-# else
__atomic_compare_exchange(addr, &oldval, &newval, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return oldval;
-# endif
}
# ifndef LOCKFREE8
@@ -266,11 +188,7 @@ inline T
js::jit::AtomicOperations::fetchAddSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_add(addr, val);
-# else
return __atomic_fetch_add(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -278,11 +196,7 @@ inline T
js::jit::AtomicOperations::fetchSubSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_sub(addr, val);
-# else
return __atomic_fetch_sub(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -290,11 +204,7 @@ inline T
js::jit::AtomicOperations::fetchAndSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_and(addr, val);
-# else
return __atomic_fetch_and(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -302,11 +212,7 @@ inline T
js::jit::AtomicOperations::fetchOrSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_or(addr, val);
-# else
return __atomic_fetch_or(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -314,11 +220,7 @@ inline T
js::jit::AtomicOperations::fetchXorSeqCst(T* addr, T val)
{
static_assert(sizeof(T) <= 4, "not available for 8-byte values yet");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- return __sync_fetch_and_xor(addr, val);
-# else
return __atomic_fetch_xor(addr, val, __ATOMIC_SEQ_CST);
-# endif
}
template<typename T>
@@ -351,17 +253,12 @@ template<size_t nbytes>
inline void
js::jit::RegionLock::acquire(void* addr)
{
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- while (!__sync_bool_compare_and_swap(&spinlock, 0, 1))
- continue;
-# else
uint32_t zero = 0;
uint32_t one = 1;
while (!__atomic_compare_exchange(&spinlock, &zero, &one, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) {
zero = 0;
continue;
}
-# endif
}
template<size_t nbytes>
@@ -369,15 +266,10 @@ inline void
js::jit::RegionLock::release(void* addr)
{
MOZ_ASSERT(AtomicOperations::loadSeqCst(&spinlock) == 1, "releasing unlocked region lock");
-# ifdef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
- __sync_sub_and_fetch(&spinlock, 1); // Should turn into LOCK XADD
-# else
uint32_t zero = 0;
__atomic_store(&spinlock, &zero, __ATOMIC_SEQ_CST);
-# endif
}
-# undef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
# undef LOCKFREE8
#elif defined(_MSC_VER)
diff --git a/js/src/old-configure.in b/js/src/old-configure.in
index 355409352c..ec599b676d 100644
--- a/js/src/old-configure.in
+++ b/js/src/old-configure.in
@@ -1903,19 +1903,6 @@ dnl ========================================================
MOZ_ARG_HEADER(Compiler Options)
dnl ========================================================
-dnl Check for gcc -pipe support
-dnl ========================================================
-AC_MSG_CHECKING([for -pipe support])
-if test -n "$GNU_CC" -a -n "$GNU_CXX"; then
- dnl Any gcc that supports firefox supports -pipe.
- CFLAGS="$CFLAGS -pipe"
- CXXFLAGS="$CXXFLAGS -pipe"
- AC_MSG_RESULT([yes])
-else
- AC_MSG_RESULT([no])
-fi
-
-dnl ========================================================
dnl Profile guided optimization (gcc checks)
dnl ========================================================
dnl Test for profiling options
diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp
index d4849f3d1d..7a905ecbea 100644
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -387,9 +387,9 @@ class BaseCompiler
#endif
case NONE:
MOZ_CRASH("AnyReg::any() on NONE");
+ default:
+ return AnyRegister();
}
- // Work around GCC 5 analysis/warning bug.
- MOZ_CRASH("AnyReg::any(): impossible case");
}
union {