Allow gcc to use strict-aliasing rules to control pointer aliasing when
authorerik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 3 Oct 2008 13:11:19 +0000 (13:11 +0000)
committererik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 3 Oct 2008 13:11:19 +0000 (13:11 +0000)
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
src/api.h
src/bootstrapper.cc
src/debug.cc
src/debug.h
src/globals.h
src/heap.cc

index 265c877..96ce466 100644 (file)
@@ -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'],
index 18dea43..99cda18 100644 (file)
--- a/src/api.h
+++ b/src/api.h
@@ -112,7 +112,7 @@ void NeanderObject::set(int offset, v8::internal::Object* value) {
 template <typename T> static inline T ToCData(v8::internal::Object* obj) {
   STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
   return reinterpret_cast<T>(
-      reinterpret_cast<int>(v8::internal::Proxy::cast(obj)->proxy()));
+      reinterpret_cast<intptr_t>(v8::internal::Proxy::cast(obj)->proxy()));
 }
 
 
@@ -120,7 +120,7 @@ template <typename T>
 static inline v8::internal::Handle<v8::internal::Object> FromCData(T obj) {
   STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
   return v8::internal::Factory::NewProxy(
-      reinterpret_cast<v8::internal::Address>(reinterpret_cast<int>(obj)));
+      reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(obj)));
 }
 
 
index cfc29df..925c8ff 100644 (file)
@@ -57,7 +57,7 @@ class SourceCodeCache BASE_EMBEDDED {
   }
 
   void Iterate(ObjectVisitor* v) {
-    v->VisitPointer(reinterpret_cast<Object**>(&cache_));
+    v->VisitPointer(bit_cast<Object**, FixedArray**>(&cache_));
   }
 
 
index e3fcb7b..acdf11d 100644 (file)
@@ -610,7 +610,7 @@ void Debug::Unload() {
 
 
 void Debug::Iterate(ObjectVisitor* v) {
-#define VISIT(field) v->VisitPointer(reinterpret_cast<Object**>(&(field)));
+#define VISIT(field) v->VisitPointer(bit_cast<Object**, Code**>(&(field)));
   VISIT(debug_break_return_entry_);
   VISIT(debug_break_return_);
 #undef VISIT
@@ -1725,7 +1725,7 @@ void DebugMessageThread::SetEventJSONFromEvent(Handle<Object> event_data) {
       }
       v8::String::Value val(json_event_string);
       Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
-                          json_event_string->Length());
+                           json_event_string->Length());
       SendMessage(str);
     } else {
       SendMessage(Vector<uint16_t>::empty());
index 94cd806..715ce1c 100644 (file)
@@ -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<Address *>(&registers_[r]);
+  static Object** register_address(int r) {
+    return &registers_[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<Address*>(&debug_break_return_);
+  static Code** debug_break_return_address() {
+    return &debug_break_return_;
   }
 
   static const int kEstimatedNofDebugInfoEntries = 16;
index 2a5cf34..26edda2 100644 (file)
@@ -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 <class Dest, class Source>
+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_
index ad2c038..4c4dfe6 100644 (file)
@@ -2350,7 +2350,7 @@ void Heap::IterateStrongRoots(ObjectVisitor* v) {
   SYNCHRONIZE_TAG("struct_map");
 
 #define SYMBOL_ITERATE(name, string) \
-  v->VisitPointer(reinterpret_cast<Object**>(&name##_));
+  v->VisitPointer(bit_cast<Object**, String**>(&name##_));
   SYMBOL_LIST(SYMBOL_ITERATE)
 #undef SYMBOL_ITERATE
   SYNCHRONIZE_TAG("symbol");