[GOLD] Reduce size of class Symbol
authorAlan Modra <amodra@gmail.com>
Tue, 29 Aug 2017 06:22:45 +0000 (15:52 +0930)
committerAlan Modra <amodra@gmail.com>
Tue, 29 Aug 2017 11:59:37 +0000 (21:29 +0930)
On 64-bit targets there is a 32-bit hole in symbol->u_, and another
due to symbol flags exceeding 32 bits.  By splitting the union,
the total size of the class reduces by one 64-bit word.

* symtab.h (Symbol): Split u_ into u1_ and u2_.  Adjust accessors
to suit.  Move plt_offset_ before got_offsets_.
* symtab.cc (Symbol::init_fields): Adjust for union change.
(Symbol::init_base_output_data): Likewise.
(Symbol::init_base_output_segment): Likewise.
(Symbol::allocate_base_common): Likewise.
(Symbol::output_section): Likewise.
(Symbol::set_output_section): Likewise.
(Symbol::set_output_segment): Likewise.
* resolve.cc (Symbol::override_base): Likewise.
(Symbol::override_base_with_special): Likewise.

gold/ChangeLog
gold/resolve.cc
gold/symtab.cc
gold/symtab.h

index 7a1ea63100527c60eb4dd4cfef6c369aca5d6b80..04b68f846a667fe1bfd1aaa73c2e2581bd709e4c 100644 (file)
@@ -1,3 +1,17 @@
+2017-08-29  Alan Modra  <amodra@gmail.com>
+
+       * symtab.h (Symbol): Split u_ into u1_ and u2_.  Adjust accessors
+       to suit.  Move plt_offset_ before got_offsets_.
+       * symtab.cc (Symbol::init_fields): Adjust for union change.
+       (Symbol::init_base_output_data): Likewise.
+       (Symbol::init_base_output_segment): Likewise.
+       (Symbol::allocate_base_common): Likewise.
+       (Symbol::output_section): Likewise.
+       (Symbol::set_output_section): Likewise.
+       (Symbol::set_output_segment): Likewise.
+       * resolve.cc (Symbol::override_base): Likewise.
+       (Symbol::override_base_with_special): Likewise.
+
 2017-08-28  Igor Kudrin  <ikudrin@accesssoftek.com>
 
        * aarch64.cc (Target_aarch64::Relocate::relocate_tls):
index 7c2260680072c84da5b803a785adff889fd2508f..042d03254de8ad39b8a9381964e51fb7d52369ac 100644 (file)
@@ -92,9 +92,9 @@ Symbol::override_base(const elfcpp::Sym<size, big_endian>& sym,
                      Object* object, const char* version)
 {
   gold_assert(this->source_ == FROM_OBJECT);
-  this->u_.from_object.object = object;
+  this->u1_.object = object;
   this->override_version(version);
-  this->u_.from_object.shndx = st_shndx;
+  this->u2_.shndx = st_shndx;
   this->is_ordinary_shndx_ = is_ordinary;
   // Don't override st_type from plugin placeholder symbols.
   if (object->pluginobj() == NULL)
@@ -952,13 +952,10 @@ Symbol::override_base_with_special(const Symbol* from)
   switch (from->source_)
     {
     case FROM_OBJECT:
-      this->u_.from_object = from->u_.from_object;
-      break;
     case IN_OUTPUT_DATA:
-      this->u_.in_output_data = from->u_.in_output_data;
-      break;
     case IN_OUTPUT_SEGMENT:
-      this->u_.in_output_segment = from->u_.in_output_segment;
+      this->u1_ = from->u1_;
+      this->u2_ = from->u2_;
       break;
     case IS_CONSTANT:
     case IS_UNDEFINED:
index 7e0a3f80d2637dd987397970da3334484ef1e01e..1555de6e5b3c3a9cef26ebfb23bd208105e0d9b5 100644 (file)
@@ -47,8 +47,8 @@ namespace gold
 
 // Class Symbol.
 
-// Initialize fields in Symbol.  This initializes everything except u_
-// and source_.
+// Initialize fields in Symbol.  This initializes everything except
+// u1_, u2_ and source_.
 
 void
 Symbol::init_fields(const char* name, const char* version,
@@ -120,8 +120,8 @@ Symbol::init_base_object(const char* name, const char* version, Object* object,
 {
   this->init_fields(name, version, sym.get_st_type(), sym.get_st_bind(),
                    sym.get_st_visibility(), sym.get_st_nonvis());
-  this->u_.from_object.object = object;
-  this->u_.from_object.shndx = st_shndx;
+  this->u1_.object = object;
+  this->u2_.shndx = st_shndx;
   this->is_ordinary_shndx_ = is_ordinary;
   this->source_ = FROM_OBJECT;
   this->in_reg_ = !object->is_dynamic();
@@ -140,8 +140,8 @@ Symbol::init_base_output_data(const char* name, const char* version,
                              bool is_predefined)
 {
   this->init_fields(name, version, type, binding, visibility, nonvis);
-  this->u_.in_output_data.output_data = od;
-  this->u_.in_output_data.offset_is_from_end = offset_is_from_end;
+  this->u1_.output_data = od;
+  this->u2_.offset_is_from_end = offset_is_from_end;
   this->source_ = IN_OUTPUT_DATA;
   this->in_reg_ = true;
   this->in_real_elf_ = true;
@@ -160,8 +160,8 @@ Symbol::init_base_output_segment(const char* name, const char* version,
                                 bool is_predefined)
 {
   this->init_fields(name, version, type, binding, visibility, nonvis);
-  this->u_.in_output_segment.output_segment = os;
-  this->u_.in_output_segment.offset_base = offset_base;
+  this->u1_.output_segment = os;
+  this->u2_.offset_base = offset_base;
   this->source_ = IN_OUTPUT_SEGMENT;
   this->in_reg_ = true;
   this->in_real_elf_ = true;
@@ -206,8 +206,8 @@ Symbol::allocate_base_common(Output_data* od)
 {
   gold_assert(this->is_common());
   this->source_ = IN_OUTPUT_DATA;
-  this->u_.in_output_data.output_data = od;
-  this->u_.in_output_data.offset_is_from_end = false;
+  this->u1_.output_data = od;
+  this->u2_.offset_is_from_end = false;
 }
 
 // Initialize the fields in Sized_symbol for SYM in OBJECT.
@@ -488,19 +488,19 @@ Symbol::output_section() const
     {
     case FROM_OBJECT:
       {
-       unsigned int shndx = this->u_.from_object.shndx;
+       unsigned int shndx = this->u2_.shndx;
        if (shndx != elfcpp::SHN_UNDEF && this->is_ordinary_shndx_)
          {
-           gold_assert(!this->u_.from_object.object->is_dynamic());
-           gold_assert(this->u_.from_object.object->pluginobj() == NULL);
-           Relobj* relobj = static_cast<Relobj*>(this->u_.from_object.object);
+           gold_assert(!this->u1_.object->is_dynamic());
+           gold_assert(this->u1_.object->pluginobj() == NULL);
+           Relobj* relobj = static_cast<Relobj*>(this->u1_.object);
            return relobj->output_section(shndx);
          }
        return NULL;
       }
 
     case IN_OUTPUT_DATA:
-      return this->u_.in_output_data.output_data->output_section();
+      return this->u1_.output_data->output_section();
 
     case IN_OUTPUT_SEGMENT:
     case IS_CONSTANT:
@@ -527,8 +527,8 @@ Symbol::set_output_section(Output_section* os)
       break;
     case IS_CONSTANT:
       this->source_ = IN_OUTPUT_DATA;
-      this->u_.in_output_data.output_data = os;
-      this->u_.in_output_data.offset_is_from_end = false;
+      this->u1_.output_data = os;
+      this->u2_.offset_is_from_end = false;
       break;
     case IN_OUTPUT_SEGMENT:
     case IS_UNDEFINED:
@@ -546,8 +546,8 @@ Symbol::set_output_segment(Output_segment* os, Segment_offset_base base)
 {
   gold_assert(this->is_predefined_);
   this->source_ = IN_OUTPUT_SEGMENT;
-  this->u_.in_output_segment.output_segment = os;
-  this->u_.in_output_segment.offset_base = base;
+  this->u1_.output_segment = os;
+  this->u2_.offset_base = base;
 }
 
 // Set the symbol to undefined.  This is used for pre-defined
index c371731b5ebf449fa74a901b0994518c5f4335c1..88d6c2782ba01c3b9c00a70c8c8b0f9fa374a6cd 100644 (file)
@@ -159,7 +159,7 @@ class Symbol
   object() const
   {
     gold_assert(this->source_ == FROM_OBJECT);
-    return this->u_.from_object.object;
+    return this->u1_.object;
   }
 
   // Return the index of the section in the input relocatable or
@@ -169,7 +169,7 @@ class Symbol
   {
     gold_assert(this->source_ == FROM_OBJECT);
     *is_ordinary = this->is_ordinary_shndx_;
-    return this->u_.from_object.shndx;
+    return this->u2_.shndx;
   }
 
   // Return the output data section with which this symbol is
@@ -179,7 +179,7 @@ class Symbol
   output_data() const
   {
     gold_assert(this->source_ == IN_OUTPUT_DATA);
-    return this->u_.in_output_data.output_data;
+    return this->u1_.output_data;
   }
 
   // If this symbol was defined with respect to an output data
@@ -188,7 +188,7 @@ class Symbol
   offset_is_from_end() const
   {
     gold_assert(this->source_ == IN_OUTPUT_DATA);
-    return this->u_.in_output_data.offset_is_from_end;
+    return this->u2_.offset_is_from_end;
   }
 
   // Return the output segment with which this symbol is associated,
@@ -198,7 +198,7 @@ class Symbol
   output_segment() const
   {
     gold_assert(this->source_ == IN_OUTPUT_SEGMENT);
-    return this->u_.in_output_segment.output_segment;
+    return this->u1_.output_segment;
   }
 
   // If this symbol was defined with respect to an output segment,
@@ -207,7 +207,7 @@ class Symbol
   offset_base() const
   {
     gold_assert(this->source_ == IN_OUTPUT_SEGMENT);
-    return this->u_.in_output_segment.offset_base;
+    return this->u2_.offset_base;
   }
 
   // Return the symbol binding.
@@ -973,38 +973,38 @@ class Symbol
 
   union
   {
-    // This struct is used if SOURCE_ == FROM_OBJECT.
-    struct
-    {
-      // Object in which symbol is defined, or in which it was first
-      // seen.
-      Object* object;
-      // Section number in object_ in which symbol is defined.
-      unsigned int shndx;
-    } from_object;
-
-    // This struct is used if SOURCE_ == IN_OUTPUT_DATA.
-    struct
-    {
-      // Output_data in which symbol is defined.  Before
-      // Layout::finalize the symbol's value is an offset within the
-      // Output_data.
-      Output_data* output_data;
-      // True if the offset is from the end, false if the offset is
-      // from the beginning.
-      bool offset_is_from_end;
-    } in_output_data;
-
-    // This struct is used if SOURCE_ == IN_OUTPUT_SEGMENT.
-    struct
-    {
-      // Output_segment in which the symbol is defined.  Before
-      // Layout::finalize the symbol's value is an offset.
-      Output_segment* output_segment;
-      // The base to use for the offset before Layout::finalize.
-      Segment_offset_base offset_base;
-    } in_output_segment;
-  } u_;
+    // This is used if SOURCE_ == FROM_OBJECT.
+    // Object in which symbol is defined, or in which it was first
+    // seen.
+    Object* object;
+
+    // This is used if SOURCE_ == IN_OUTPUT_DATA.
+    // Output_data in which symbol is defined.  Before
+    // Layout::finalize the symbol's value is an offset within the
+    // Output_data.
+    Output_data* output_data;
+
+    // This is used if SOURCE_ == IN_OUTPUT_SEGMENT.
+    // Output_segment in which the symbol is defined.  Before
+    // Layout::finalize the symbol's value is an offset.
+    Output_segment* output_segment;
+  } u1_;
+
+  union
+  {
+    // This is used if SOURCE_ == FROM_OBJECT.
+    // Section number in object in which symbol is defined.
+    unsigned int shndx;
+
+    // This is used if SOURCE_ == IN_OUTPUT_DATA.
+    // True if the offset is from the end, false if the offset is
+    // from the beginning.
+    bool offset_is_from_end;
+
+    // This is used if SOURCE_ == IN_OUTPUT_SEGMENT.
+    // The base to use for the offset before Layout::finalize.
+    Segment_offset_base offset_base;
+  } u2_;
 
   // The index of this symbol in the output file.  If the symbol is
   // not going into the output file, this value is -1U.  This field
@@ -1018,16 +1018,16 @@ class Symbol
   // non-zero value during Layout::finalize.
   unsigned int dynsym_index_;
 
-  // The GOT section entries for this symbol.  A symbol may have more
-  // than one GOT offset (e.g., when mixing modules compiled with two
-  // different TLS models), but will usually have at most one.
-  Got_offset_list got_offsets_;
-
   // If this symbol has an entry in the PLT section, then this is the
   // offset from the start of the PLT section.  This is -1U if there
   // is no PLT entry.
   unsigned int plt_offset_;
 
+  // The GOT section entries for this symbol.  A symbol may have more
+  // than one GOT offset (e.g., when mixing modules compiled with two
+  // different TLS models), but will usually have at most one.
+  Got_offset_list got_offsets_;
+
   // Symbol type (bits 0 to 3).
   elfcpp::STT type_ : 4;
   // Symbol binding (bits 4 to 7).
@@ -1069,7 +1069,7 @@ class Symbol
   // True if this symbol was forced to local visibility by a version
   // script (bit 28).
   bool is_forced_local_ : 1;
-  // True if the field u_.from_object.shndx is an ordinary section
+  // True if the field u2_.shndx is an ordinary section
   // index, not one of the special codes from SHN_LORESERVE to
   // SHN_HIRESERVE (bit 29).
   bool is_ordinary_shndx_ : 1;