STATIC_ASSERT(kSeqStringTag == 0);
__ tst(r0, Operand(kStringRepresentationMask));
// The underlying external string is never a short external string.
- STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength);
- STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength);
+ STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
+ STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
__ b(ne, &external_string); // Go to (7).
// (5) Sequential string. Load regexp code according to encoding.
// Handle external string.
// Rule out short external strings.
- STATIC_CHECK(kShortExternalStringTag != 0);
+ STATIC_ASSERT(kShortExternalStringTag != 0);
__ tst(r1, Operand(kShortExternalStringTag));
__ b(ne, &runtime);
__ ldr(r5, FieldMemOperand(r5, ExternalString::kResourceDataOffset));
__ Assert(eq, kExternalStringExpectedButNotFound);
}
// Rule out short external strings.
- STATIC_CHECK(kShortExternalStringTag != 0);
+ STATIC_ASSERT(kShortExternalStringTag != 0);
__ tst(result, Operand(kShortExternalStringMask));
__ b(ne, call_runtime);
__ ldr(string, FieldMemOperand(string, ExternalString::kResourceDataOffset));
__ Ldrb(string_type, FieldMemOperand(x10, Map::kInstanceTypeOffset));
STATIC_ASSERT(kSeqStringTag == 0);
// The underlying external string is never a short external string.
- STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength);
- STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength);
+ STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
+ STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
__ TestAndBranchIfAnySet(string_type.X(),
kStringRepresentationMask,
&external_string); // Go to (7).
__ Assert(eq, kExternalStringExpectedButNotFound);
}
// Rule out short external strings.
- STATIC_CHECK(kShortExternalStringTag != 0);
+ STATIC_ASSERT(kShortExternalStringTag != 0);
// TestAndBranchIfAnySet can emit Tbnz. Do not use it because call_runtime
// can be bound far away in deferred code.
__ Tst(result, kShortExternalStringMask);
// Use C++11 static_assert if possible, which gives error
// messages that are easier to understand on first sight.
#if V8_HAS_CXX11_STATIC_ASSERT
-#define STATIC_CHECK(test) static_assert(test, #test)
+#define STATIC_ASSERT(test) static_assert(test, #test)
#else
// This is inspired by the static assertion facility in boost. This
// is pretty magical. If it causes you trouble on a platform you may
// actually causes each use to introduce a new defined type with a
// name depending on the source line.
template <int> class StaticAssertionHelper { };
-#define STATIC_CHECK(test) \
+#define STATIC_ASSERT(test) \
typedef \
StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>((test))>)> \
SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__) V8_UNUSED
#define ASSERT_LT(v1, v2) ((void) 0)
#define ASSERT_LE(v1, v2) ((void) 0)
#endif
-// Static asserts has no impact on runtime performance, so they can be
-// safely enabled in release mode. Moreover, the ((void) 0) expression
-// obeys different syntax rules than typedef's, e.g. it can't appear
-// inside class declaration, this leads to inconsistency between debug
-// and release compilation modes behavior.
-#define STATIC_ASSERT(test) STATIC_CHECK(test)
#define ASSERT_NOT_NULL(p) ASSERT_NE(NULL, p)
static bool IsBootstrappingOrGlobalObject(Isolate* isolate, Object* object);
#endif
- STATIC_CHECK(kHeaderSize == Internals::kContextHeaderSize);
- STATIC_CHECK(EMBEDDER_DATA_INDEX == Internals::kContextEmbedderDataIndex);
+ STATIC_ASSERT(kHeaderSize == Internals::kContextHeaderSize);
+ STATIC_ASSERT(EMBEDDER_DATA_INDEX == Internals::kContextEmbedderDataIndex);
};
} } // namespace v8::internal
void HeapEntry::Print(
const char* prefix, const char* edge_name, int max_depth, int indent) {
- STATIC_CHECK(sizeof(unsigned) == sizeof(id()));
+ STATIC_ASSERT(sizeof(unsigned) == sizeof(id()));
OS::Print("%6" V8PRIuPTR " @%6u %*c %s%s: ",
self_size(), id(), indent, ' ', prefix, edge_name);
if (type() != kString) {
gc_roots_index_(HeapEntry::kNoEntry),
natives_root_index_(HeapEntry::kNoEntry),
max_snapshot_js_object_id_(0) {
- STATIC_CHECK(
+ STATIC_ASSERT(
sizeof(HeapGraphEdge) ==
SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize);
- STATIC_CHECK(
+ STATIC_ASSERT(
sizeof(HeapEntry) ==
SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize);
USE(SnapshotSizeConstants<4>::kExpectedHeapGraphEdgeSize);
SetWeakReference(js_fun, entry,
"next_function_link", js_fun->next_function_link(),
JSFunction::kNextFunctionLinkOffset);
- STATIC_CHECK(JSFunction::kNextFunctionLinkOffset
+ STATIC_ASSERT(JSFunction::kNextFunctionLinkOffset
== JSFunction::kNonWeakFieldsEndOffset);
- STATIC_CHECK(JSFunction::kNextFunctionLinkOffset + kPointerSize
+ STATIC_ASSERT(JSFunction::kNextFunctionLinkOffset + kPointerSize
== JSFunction::kSize);
} else if (obj->IsGlobalObject()) {
GlobalObject* global_obj = GlobalObject::cast(obj);
SetInternalReference(global_obj, entry,
"global_receiver", global_obj->global_receiver(),
GlobalObject::kGlobalReceiverOffset);
- STATIC_CHECK(GlobalObject::kHeaderSize - JSObject::kHeaderSize ==
+ STATIC_ASSERT(GlobalObject::kHeaderSize - JSObject::kHeaderSize ==
4 * kPointerSize);
} else if (obj->IsJSArrayBufferView()) {
JSArrayBufferView* view = JSArrayBufferView::cast(obj);
EXTRACT_CONTEXT_FIELD(DEOPTIMIZED_CODE_LIST, unused, deoptimized_code_list);
EXTRACT_CONTEXT_FIELD(NEXT_CONTEXT_LINK, unused, next_context_link);
#undef EXTRACT_CONTEXT_FIELD
- STATIC_CHECK(Context::OPTIMIZED_FUNCTIONS_LIST == Context::FIRST_WEAK_SLOT);
- STATIC_CHECK(Context::NEXT_CONTEXT_LINK + 1
- == Context::NATIVE_CONTEXT_SLOTS);
- STATIC_CHECK(Context::FIRST_WEAK_SLOT + 5 == Context::NATIVE_CONTEXT_SLOTS);
+ STATIC_ASSERT(Context::OPTIMIZED_FUNCTIONS_LIST ==
+ Context::FIRST_WEAK_SLOT);
+ STATIC_ASSERT(Context::NEXT_CONTEXT_LINK + 1 ==
+ Context::NATIVE_CONTEXT_SLOTS);
+ STATIC_ASSERT(Context::FIRST_WEAK_SLOT + 5 ==
+ Context::NATIVE_CONTEXT_SLOTS);
}
}
AllocationSite::kDependentCodeOffset);
// Do not visit weak_next as it is not visited by the StaticVisitor,
// and we're not very interested in weak_next field here.
- STATIC_CHECK(AllocationSite::kWeakNextOffset >=
+ STATIC_ASSERT(AllocationSite::kWeakNextOffset >=
AllocationSite::BodyDescriptor::kEndOffset);
}
template<typename T>
static int utoa_impl(T value, const Vector<char>& buffer, int buffer_pos) {
- STATIC_CHECK(static_cast<T>(-1) > 0); // Check that T is unsigned
+ STATIC_ASSERT(static_cast<T>(-1) > 0); // Check that T is unsigned
int number_of_digits = 0;
T t = value;
do {
template<typename T>
static int utoa(T value, const Vector<char>& buffer, int buffer_pos) {
typename ToUnsigned<sizeof(value)>::Type unsigned_value = value;
- STATIC_CHECK(sizeof(value) == sizeof(unsigned_value));
+ STATIC_ASSERT(sizeof(value) == sizeof(unsigned_value));
return utoa_impl(unsigned_value, buffer, buffer_pos);
}
kSmiRootsStart = kStringTableRootIndex + 1
};
- STATIC_CHECK(kUndefinedValueRootIndex == Internals::kUndefinedValueRootIndex);
- STATIC_CHECK(kNullValueRootIndex == Internals::kNullValueRootIndex);
- STATIC_CHECK(kTrueValueRootIndex == Internals::kTrueValueRootIndex);
- STATIC_CHECK(kFalseValueRootIndex == Internals::kFalseValueRootIndex);
- STATIC_CHECK(kempty_stringRootIndex == Internals::kEmptyStringRootIndex);
+ STATIC_ASSERT(kUndefinedValueRootIndex ==
+ Internals::kUndefinedValueRootIndex);
+ STATIC_ASSERT(kNullValueRootIndex == Internals::kNullValueRootIndex);
+ STATIC_ASSERT(kTrueValueRootIndex == Internals::kTrueValueRootIndex);
+ STATIC_ASSERT(kFalseValueRootIndex == Internals::kFalseValueRootIndex);
+ STATIC_ASSERT(kempty_stringRootIndex == Internals::kEmptyStringRootIndex);
// Generated code can embed direct references to non-writable roots if
// they are in new space.
// (5b) Is subject external? If yes, go to (8).
__ test_b(ebx, kStringRepresentationMask);
// The underlying external string is never a short external string.
- STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength);
- STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength);
+ STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
+ STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
__ j(not_zero, &external_string); // Go to (8).
// eax: sequential subject string (or look-alike, external string)
// Handle external string.
// Rule out short external strings.
- STATIC_CHECK(kShortExternalStringTag != 0);
+ STATIC_ASSERT(kShortExternalStringTag != 0);
__ test_b(ebx, kShortExternalStringMask);
__ j(not_zero, &runtime);
__ mov(edi, FieldOperand(edi, ExternalString::kResourceDataOffset));
__ Assert(zero, kExternalStringExpectedButNotFound);
}
// Rule out short external strings.
- STATIC_CHECK(kShortExternalStringTag != 0);
+ STATIC_ASSERT(kShortExternalStringTag != 0);
__ test_b(result, kShortExternalStringMask);
__ j(not_zero, call_runtime);
// Check encoding.
STATIC_ASSERT(kSeqStringTag == 0);
__ And(at, a0, Operand(kStringRepresentationMask));
// The underlying external string is never a short external string.
- STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength);
- STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength);
+ STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
+ STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
__ Branch(&external_string, ne, at, Operand(zero_reg)); // Go to (7).
// (5) Sequential string. Load regexp code according to encoding.
// Handle external string.
// Rule out short external strings.
- STATIC_CHECK(kShortExternalStringTag != 0);
+ STATIC_ASSERT(kShortExternalStringTag != 0);
__ And(t0, a1, Operand(kShortExternalStringTag));
__ Branch(&runtime, ne, t0, Operand(zero_reg));
__ lw(t1, FieldMemOperand(t1, ExternalString::kResourceDataOffset));
at, Operand(zero_reg));
}
// Rule out short external strings.
- STATIC_CHECK(kShortExternalStringTag != 0);
+ STATIC_ASSERT(kShortExternalStringTag != 0);
__ And(at, result, Operand(kShortExternalStringMask));
__ Branch(call_runtime, ne, at, Operand(zero_reg));
__ lw(string, FieldMemOperand(string, ExternalString::kResourceDataOffset));
}
-STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
+STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) ==
Internals::kFullStringRepresentationMask);
-STATIC_CHECK(static_cast<uint32_t>(kStringEncodingMask) ==
+STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) ==
Internals::kStringEncodingMask);
}
-STATIC_CHECK((kExternalStringTag | kOneByteStringTag) ==
+STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) ==
Internals::kExternalAsciiRepresentationTag);
-STATIC_CHECK(v8::String::ASCII_ENCODING == kOneByteStringTag);
+STATIC_ASSERT(v8::String::ASCII_ENCODING == kOneByteStringTag);
bool StringShape::IsExternalTwoByte() {
}
-STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
+STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) ==
Internals::kExternalTwoByteRepresentationTag);
-STATIC_CHECK(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
+STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
uc32 FlatStringReader::Get(int index) {
ASSERT(0 <= index && index <= length_);
const int kExternalArrayTypeCount =
LAST_EXTERNAL_ARRAY_TYPE - FIRST_EXTERNAL_ARRAY_TYPE + 1;
-STATIC_CHECK(JS_OBJECT_TYPE == Internals::kJSObjectType);
-STATIC_CHECK(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
-STATIC_CHECK(ODDBALL_TYPE == Internals::kOddballType);
-STATIC_CHECK(FOREIGN_TYPE == Internals::kForeignType);
+STATIC_ASSERT(JS_OBJECT_TYPE == Internals::kJSObjectType);
+STATIC_ASSERT(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
+STATIC_ASSERT(ODDBALL_TYPE == Internals::kOddballType);
+STATIC_ASSERT(FOREIGN_TYPE == Internals::kForeignType);
#define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \
static const int kMapOffset = Object::kHeaderSize;
static const int kHeaderSize = kMapOffset + kPointerSize;
- STATIC_CHECK(kMapOffset == Internals::kHeapObjectMapOffset);
+ STATIC_ASSERT(kMapOffset == Internals::kHeapObjectMapOffset);
protected:
// helpers for calling an ObjectVisitor to iterate over pointers in the
static const int kElementsOffset = kPropertiesOffset + kPointerSize;
static const int kHeaderSize = kElementsOffset + kPointerSize;
- STATIC_CHECK(kHeaderSize == Internals::kJSObjectHeaderSize);
+ STATIC_ASSERT(kHeaderSize == Internals::kJSObjectHeaderSize);
class BodyDescriptor : public FlexibleBodyDescriptor<kPropertiesOffset> {
public:
Object* value);
private:
- STATIC_CHECK(kHeaderSize == Internals::kFixedArrayHeaderSize);
+ STATIC_ASSERT(kHeaderSize == Internals::kFixedArrayHeaderSize);
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
};
static const int kBitFieldOffset = kInstanceAttributesOffset + 2;
static const int kBitField2Offset = kInstanceAttributesOffset + 3;
- STATIC_CHECK(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset);
+ STATIC_ASSERT(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset);
// Bit positions for bit field.
static const int kHasNonInstancePrototype = 0;
static const int kArrayIndexLengthBits =
kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields;
- STATIC_CHECK((kArrayIndexLengthBits > 0));
+ STATIC_ASSERT((kArrayIndexLengthBits > 0));
static const int kArrayIndexHashLengthShift =
kArrayIndexValueBits + kNofHashBitFields;
// Check that kMaxCachedArrayIndexLength + 1 is a power of two so we
// could use a mask to test if the length of string is less than or equal to
// kMaxCachedArrayIndexLength.
- STATIC_CHECK(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
+ STATIC_ASSERT(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
static const unsigned int kContainsCachedArrayIndexMask =
(~kMaxCachedArrayIndexLength << kArrayIndexHashLengthShift) |
// Maximum number of characters to consider when trying to convert a string
// value into an array index.
static const int kMaxArrayIndexSize = 10;
- STATIC_CHECK(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
+ STATIC_ASSERT(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
// Max char codes.
static const int32_t kMaxOneByteCharCode = unibrow::Latin1::kMaxChar;
// Maximal memory usage for a single sequential ASCII string.
static const int kMaxSize = 512 * MB - 1;
- STATIC_CHECK((kMaxSize - kHeaderSize) >= String::kMaxLength);
+ STATIC_ASSERT((kMaxSize - kHeaderSize) >= String::kMaxLength);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SeqOneByteString);
// Maximal memory usage for a single sequential two-byte string.
static const int kMaxSize = 512 * MB - 1;
- STATIC_CHECK(static_cast<int>((kMaxSize - kHeaderSize)/sizeof(uint16_t)) >=
+ STATIC_ASSERT(static_cast<int>((kMaxSize - kHeaderSize)/sizeof(uint16_t)) >=
String::kMaxLength);
private:
// Return whether external string is short (data pointer is not cached).
inline bool is_short();
- STATIC_CHECK(kResourceOffset == Internals::kStringResourceOffset);
+ STATIC_ASSERT(kResourceOffset == Internals::kStringResourceOffset);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalString);
kToNumberOffset + kPointerSize,
kSize> BodyDescriptor;
- STATIC_CHECK(kKindOffset == Internals::kOddballKindOffset);
- STATIC_CHECK(kNull == Internals::kNullOddballKind);
- STATIC_CHECK(kUndefined == Internals::kUndefinedOddballKind);
+ STATIC_ASSERT(kKindOffset == Internals::kOddballKindOffset);
+ STATIC_ASSERT(kNull == Internals::kNullOddballKind);
+ STATIC_ASSERT(kUndefined == Internals::kUndefinedOddballKind);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Oddball);
static const int kHeaderSize = kPaddingOffset;
static const int kPaddingSize = kSize - kPaddingOffset;
- STATIC_CHECK(kPaddingSize >= 0);
+ STATIC_ASSERT(kPaddingSize >= 0);
typedef FixedBodyDescriptor<kHandlerOffset,
kPaddingOffset,
static const int kSize = JSFunction::kSize;
static const int kPaddingSize = kSize - kPaddingOffset;
- STATIC_CHECK(kPaddingSize >= 0);
+ STATIC_ASSERT(kPaddingSize >= 0);
typedef FixedBodyDescriptor<kHandlerOffset,
kConstructTrapOffset + kPointerSize,
static const int kForeignAddressOffset = HeapObject::kHeaderSize;
static const int kSize = kForeignAddressOffset + kPointerSize;
- STATIC_CHECK(kForeignAddressOffset == Internals::kForeignAddressOffset);
+ STATIC_ASSERT(kForeignAddressOffset == Internals::kForeignAddressOffset);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Foreign);
// equality is 0 and inequality is 1 so we have to negate the result
// from String::Equals.
ASSERT(not_equal == 0 || not_equal == 1);
- STATIC_CHECK(EQUAL == 0);
- STATIC_CHECK(NOT_EQUAL == 1);
+ STATIC_ASSERT(EQUAL == 0);
+ STATIC_ASSERT(NOT_EQUAL == 1);
return Smi::FromInt(not_equal);
}
};
-STATIC_CHECK(sizeof(MemoryChunk) <= MemoryChunk::kHeaderSize);
+STATIC_ASSERT(sizeof(MemoryChunk) <= MemoryChunk::kHeaderSize);
// -----------------------------------------------------------------------------
};
-STATIC_CHECK(sizeof(Page) <= MemoryChunk::kHeaderSize);
+STATIC_ASSERT(sizeof(Page) <= MemoryChunk::kHeaderSize);
class LargePage : public MemoryChunk {
friend class MemoryAllocator;
};
-STATIC_CHECK(sizeof(LargePage) <= MemoryChunk::kHeaderSize);
+STATIC_ASSERT(sizeof(LargePage) <= MemoryChunk::kHeaderSize);
// ----------------------------------------------------------------------------
// Space is the abstract superclass for all allocation spaces.
// (5b) Is subject external? If yes, go to (8).
__ testb(rbx, Immediate(kStringRepresentationMask));
// The underlying external string is never a short external string.
- STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength);
- STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength);
+ STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
+ STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
__ j(not_zero, &external_string); // Go to (8)
// (6) One byte sequential. Load regexp code for one byte.
// Handle external string.
// Rule out short external strings.
- STATIC_CHECK(kShortExternalStringTag != 0);
+ STATIC_ASSERT(kShortExternalStringTag != 0);
__ testb(rbx, Immediate(kShortExternalStringMask));
__ j(not_zero, &runtime);
__ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset));
__ Assert(zero, kExternalStringExpectedButNotFound);
}
// Rule out short external strings.
- STATIC_CHECK(kShortExternalStringTag != 0);
+ STATIC_ASSERT(kShortExternalStringTag != 0);
__ testb(result, Immediate(kShortExternalStringTag));
__ j(not_zero, call_runtime);
// Check encoding.
// (5b) Is subject external? If yes, go to (8).
__ test_b(ebx, kStringRepresentationMask);
// The underlying external string is never a short external string.
- STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength);
- STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength);
+ STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
+ STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
__ j(not_zero, &external_string); // Go to (8).
// eax: sequential subject string (or look-alike, external string)
// Handle external string.
// Rule out short external strings.
- STATIC_CHECK(kShortExternalStringTag != 0);
+ STATIC_ASSERT(kShortExternalStringTag != 0);
__ test_b(ebx, kShortExternalStringMask);
__ j(not_zero, &runtime);
__ mov(edi, FieldOperand(edi, ExternalString::kResourceDataOffset));
__ Assert(zero, kExternalStringExpectedButNotFound);
}
// Rule out short external strings.
- STATIC_CHECK(kShortExternalStringTag != 0);
+ STATIC_ASSERT(kShortExternalStringTag != 0);
__ test_b(result, kShortExternalStringMask);
__ j(not_zero, call_runtime);
// Check encoding.
Mutex mutex_;
int num_blocked_;
- STATIC_CHECK(N > 0);
+ STATIC_ASSERT(N > 0);
DISALLOW_COPY_AND_ASSIGN(ThreadBarrier);
};