From 70fa44ecea77d2aa863a5838ff6dd4684cdc9a7a Mon Sep 17 00:00:00 2001 From: "erik.corry@gmail.com" Date: Fri, 3 Oct 2008 13:11:19 +0000 Subject: [PATCH] Allow gcc to use strict-aliasing rules to control pointer aliasing when optimizing. Obfuscate a few casts with bit_cast to avoid warnings from gcc. Review URL: http://codereview.chromium.org/6236 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@428 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- SConstruct | 5 ++--- src/api.h | 4 ++-- src/bootstrapper.cc | 2 +- src/debug.cc | 4 ++-- src/debug.h | 8 ++++---- src/globals.h | 36 ++++++++++++++++++++++++++++++++++++ src/heap.cc | 2 +- 7 files changed, 48 insertions(+), 13 deletions(-) diff --git a/SConstruct b/SConstruct index 265c877..96ce466 100644 --- a/SConstruct +++ b/SConstruct @@ -43,8 +43,7 @@ LIBRARY_FLAGS = { 'gcc': { 'all': { 'DIALECTFLAGS': ['-ansi'], - 'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS', - '-fno-strict-aliasing'], + 'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS'], 'CXXFLAGS': ['$CCFLAGS', '-fno-rtti', '-fno-exceptions'], 'LIBS': ['pthread'] }, @@ -53,7 +52,7 @@ LIBRARY_FLAGS = { 'CPPDEFINES': ['ENABLE_DISASSEMBLER', 'DEBUG'] }, 'mode:release': { - 'CCFLAGS': ['-O9'] + 'CCFLAGS': ['-O3'] }, 'wordsize:64': { 'CCFLAGS': ['-m32'], diff --git a/src/api.h b/src/api.h index 18dea43..99cda18 100644 --- a/src/api.h +++ b/src/api.h @@ -112,7 +112,7 @@ void NeanderObject::set(int offset, v8::internal::Object* value) { template static inline T ToCData(v8::internal::Object* obj) { STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address)); return reinterpret_cast( - reinterpret_cast(v8::internal::Proxy::cast(obj)->proxy())); + reinterpret_cast(v8::internal::Proxy::cast(obj)->proxy())); } @@ -120,7 +120,7 @@ template static inline v8::internal::Handle FromCData(T obj) { STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address)); return v8::internal::Factory::NewProxy( - reinterpret_cast(reinterpret_cast(obj))); + reinterpret_cast(reinterpret_cast(obj))); } diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index cfc29df..925c8ff 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -57,7 +57,7 @@ class SourceCodeCache BASE_EMBEDDED { } void Iterate(ObjectVisitor* v) { - v->VisitPointer(reinterpret_cast(&cache_)); + v->VisitPointer(bit_cast(&cache_)); } diff --git a/src/debug.cc b/src/debug.cc index e3fcb7b..acdf11d 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -610,7 +610,7 @@ void Debug::Unload() { void Debug::Iterate(ObjectVisitor* v) { -#define VISIT(field) v->VisitPointer(reinterpret_cast(&(field))); +#define VISIT(field) v->VisitPointer(bit_cast(&(field))); VISIT(debug_break_return_entry_); VISIT(debug_break_return_); #undef VISIT @@ -1725,7 +1725,7 @@ void DebugMessageThread::SetEventJSONFromEvent(Handle event_data) { } v8::String::Value val(json_event_string); Vector str(reinterpret_cast(*val), - json_event_string->Length()); + json_event_string->Length()); SendMessage(str); } else { SendMessage(Vector::empty()); diff --git a/src/debug.h b/src/debug.h index 94cd806..715ce1c 100644 --- a/src/debug.h +++ b/src/debug.h @@ -233,16 +233,16 @@ class Debug { } // Support for saving/restoring registers when handling debug break calls. - static Address* register_address(int r) { - return reinterpret_cast
(®isters_[r]); + static Object** register_address(int r) { + return ®isters_[r]; } // Address of the debug break return entry code. static Code* debug_break_return_entry() { return debug_break_return_entry_; } // Support for getting the address of the debug break on return code. - static Address* debug_break_return_address() { - return reinterpret_cast(&debug_break_return_); + static Code** debug_break_return_address() { + return &debug_break_return_; } static const int kEstimatedNofDebugInfoEntries = 16; diff --git a/src/globals.h b/src/globals.h index 2a5cf34..26edda2 100644 --- a/src/globals.h +++ b/src/globals.h @@ -463,6 +463,42 @@ F FUNCTION_CAST(Address addr) { #define INLINE(header) inline header #endif +// The type-based aliasing rule allows the compiler to assume that pointers of +// different types (for some definition of different) never alias each other. +// Thus the following code does not work: +// +// float f = foo(); +// int fbits = *(int*)(&f); +// +// The compiler 'knows' that the int pointer can't refer to f since the types +// don't match, so the compiler may cache f in a register, leaving random data +// in fbits. Using C++ style casts makes no difference, however a pointer to +// char data is assumed to alias any other pointer. This is the 'memcpy +// exception'. +// +// Bit_cast uses the memcpy exception to move the bits from a variable of one +// type o a variable of another type. Of course the end result is likely to +// be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005) +// will completely optimize bit_cast away. +// +// There is an additional use for bit_cast. +// Recent gccs will warn when they see casts that may result in breakage due to +// the type-based aliasing rule. If you have checked that there is no breakage +// you can use bit_cast to cast one pointer type to another. This confuses gcc +// enough that it can no longer see that you have cast one pointer type to +// another thus avoiding the warning. +template +inline Dest bit_cast(const Source& source) { + // Compile time assertion: sizeof(Dest) == sizeof(Source) + // A compile error here means your Dest and Source have different sizes. + typedef char VerifySizesAreEqual [sizeof(Dest) == sizeof(Source) ? 1 : -1]; + + Dest dest; + memcpy(&dest, &source, sizeof(dest)); + return dest; +} + + } } // namespace v8::internal #endif // V8_GLOBALS_H_ diff --git a/src/heap.cc b/src/heap.cc index ad2c038..4c4dfe6 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -2350,7 +2350,7 @@ void Heap::IterateStrongRoots(ObjectVisitor* v) { SYNCHRONIZE_TAG("struct_map"); #define SYMBOL_ITERATE(name, string) \ - v->VisitPointer(reinterpret_cast(&name##_)); + v->VisitPointer(bit_cast(&name##_)); SYMBOL_LIST(SYMBOL_ITERATE) #undef SYMBOL_ITERATE SYNCHRONIZE_TAG("symbol"); -- 2.7.4