JIT脚本引擎:成员对齐详解

JIT脚本引擎:成员对齐详解
    为了让编译成x86后的代码可以转换成C++的函数指针,我们也必须处理成员对齐的事情。如果脚本里的结构成员对齐跟C++不一致的话,会造成很多麻烦。下面是成员对齐的计算方法:

    一个类型有两种属性,一种是尺寸,另一种是对齐单位,可以分别用sizeof和__alignof来表示。

    1:对于基本类型(char、short、double等)T有__alignof(T) == sizeof(T)
    2:对于数组类型T[N]有__alignof(T[N]) == __alignof(T),sizeof(T[N]) == sizeof(T)×N
    3:对于结构类型T=T1×T2×...×Tn,有__alignof(T) = max(__alignof(Ti)),sizeof(T) = align(offset(Tn)+sizeof(Tn) , __alignof(T))
    4:如果一个类型结构T为空,那么sizeof(T) == __alignof(T) == 1

    offset(Tn)是第n个成员相对于T起始位置的偏移,而align(S,A)可以用如下代码计算:
1  VInt Align(VInt Offset , VInt Alignment)
2  {
3       if (Alignment == 0 )
4      {
5          Alignment = 1 ;
6      }
7       return  (Offset + Alignment - 1 ) / Alignment * Alignment;
8  }

    于是就剩下offset(Tn)了。有了Align之后就可以递归定义offset(Tn):
    offset(T1)=0
    offset(Ti)=align(offset(Ti-1)+sizeof(Ti-1) , __alignof(Ti))

    于是我们可以得到定理:
    1:sizeof(T) == 0 (mod __alignof(T))
    2:当T=T1×T2×...×Tn中T1==T2==...==Tn的时候,T的结构与T1[n]的结构完全一致
    3:对于任意类型集合{T1 T2 ... Tn}有max(__alignof(Ti)) <= max(__alignof(基本类型集合))

    以上结论在VC++的缺省设置中有效,如果为一个struct强行指定了pack和__alignof,将使用另外的规则。

    为了证明以上式子,我写了一段程序,通过上面的方法计算成员的sizeof、__alignof以及offset,最后跟C++的编译结果互相验证:
 1  #include  " ..\..\..\..\VL++\Library\Platform\VL_Console.h "
 2  #include  " ..\..\..\..\VL++\Library\Script\JIT\Assembler\VL_JIT_MemberAlignment.h "
 3 
 4  using   namespace  vl;
 5  using   namespace  vl::jit::alignment;
 6  using   namespace  vl::platform;
 7 
 8  struct  SubStructForTest
 9  {
10       char  Char;
11       double  Double;
12       short  Short;
13       int  Int;
14  };
15 
16  struct  StructForTest
17  {
18      SubStructForTest Sub;
19       double  Double[ 8 ];
20      SubStructForTest Subs[ 10 ];
21       char  Char;
22  };
23 
24  #define  OFFSET_OF(TYPE,MEMBER) (VInt)(&((TYPE*)0)->MEMBER)
25 
26  void  Main_Alignment()
27  {
28      VL_AutoPtr < VL_AlignStruct >  SubStruct = new  VL_AlignStruct;
29      SubStruct -> AddMember( new  VL_AlignBasic(vabtAsciiChar));
30      SubStruct -> AddMember( new  VL_AlignBasic(vabtDouble));
31      SubStruct -> AddMember( new  VL_AlignBasic(vabtInt16));
32      SubStruct -> AddMember( new  VL_AlignBasic(vabtInt32));
33 
34      VL_AutoPtr < VL_AlignStruct >  Struct = new  VL_AlignStruct;
35      Struct -> AddMember(SubStruct);
36      Struct -> AddMember( new  VL_AlignArray( new  VL_AlignBasic(vabtDouble), 8 ));
37      Struct -> AddMember( new  VL_AlignArray(SubStruct, 10 ));
38      Struct -> AddMember( new  VL_AlignBasic(vabtAsciiChar));
39 
40      GetConsole() -> Write(VUnicodeString(SubStruct -> GetMember( 0 ).GetOffset()) + L " \t " + VUnicodeString(OFFSET_OF(SubStructForTest,Char)) + L " \r\n " );
41      GetConsole() -> Write(VUnicodeString(SubStruct -> GetMember( 1 ).GetOffset()) + L " \t " + VUnicodeString(OFFSET_OF(SubStructForTest,Double)) + L " \r\n " );
42      GetConsole() -> Write(VUnicodeString(SubStruct -> GetMember( 2 ).GetOffset()) + L " \t " + VUnicodeString(OFFSET_OF(SubStructForTest,Short)) + L " \r\n " );
43      GetConsole() -> Write(VUnicodeString(SubStruct -> GetMember( 3 ).GetOffset()) + L " \t " + VUnicodeString(OFFSET_OF(SubStructForTest,Int)) + L " \r\n " );
44      GetConsole() -> Write(VUnicodeString(SubStruct -> GetSize()) + L " \t " + VUnicodeString((VInt) sizeof (SubStructForTest)) + L " \r\n " );
45      GetConsole() -> Write(L " \t\n " );
46 
47      GetConsole() -> Write(VUnicodeString(Struct -> GetMember( 0 ).GetOffset()) + L " \t " + VUnicodeString(OFFSET_OF(StructForTest,Sub)) + L " \r\n " );
48      GetConsole() -> Write(VUnicodeString(Struct -> GetMember( 1 ).GetOffset()) + L " \t " + VUnicodeString(OFFSET_OF(StructForTest,Double)) + L " \r\n " );
49      GetConsole() -> Write(VUnicodeString(Struct -> GetMember( 2 ).GetOffset()) + L " \t " + VUnicodeString(OFFSET_OF(StructForTest,Subs)) + L " \r\n " );
50      GetConsole() -> Write(VUnicodeString(Struct -> GetMember( 3 ).GetOffset()) + L " \t " + VUnicodeString(OFFSET_OF(StructForTest,Char)) + L " \r\n " );
51      GetConsole() -> Write(VUnicodeString(Struct -> GetSize()) + L " \t " + VUnicodeString((VInt) sizeof (StructForTest)) + L " \r\n " );
52  }

    最后是结果:
JIT脚本引擎:成员对齐详解_第1张图片

    vl::jit::alignment头文件:
  1  /* ******************************************************************************
  2  Vczh Library++ 2.0
  3  JIT::成员对齐
  4  开发者:陈梓瀚
  5 
  6  接口:
  7  类:
  8  函数:
  9  ****************************************************************************** */
 10 
 11  #ifndef VL_JIT_MEMBERALIGNMENT
 12  #define  VL_JIT_MEMBERALIGNMENT
 13 
 14  #include  " ..\..\..\Data\Data\VL_Data_Basic.h "
 15  #include  " ..\..\..\Data\Data\VL_Data_List.h "
 16 
 17  namespace  vl
 18  {
 19       namespace  jit
 20      {
 21           namespace  alignment
 22          {
 23               using   namespace  collection;
 24 
 25               class  VL_AlignType :  public  VL_Base
 26              {
 27               public :
 28                  typedef VL_AutoPtr < VL_AlignType >             Ptr;
 29                  typedef VL_AutoPtr < const  VL_AlignType >         ConstPtr;
 30 
 31                   virtual  VInt                    GetSize() const = 0 ;
 32                   virtual  VInt                    GetAlignment() const = 0 ;
 33              };
 34 
 35               class  VL_AlignMember :  public  VL_Base
 36              {
 37               protected :
 38                  VL_AlignType::Ptr                FType;
 39                  VInt                            FMinOffset;
 40               public :
 41                  typedef VL_List < VL_AlignMember ,  false >         List;
 42 
 43                  VL_AlignMember();
 44 
 45                  VL_AlignType::ConstPtr            GetType() const ;
 46                   void                             SetType(VL_AlignType::Ptr Type);
 47                  VInt                            GetOffset() const ;
 48                   void                             SetMinOffset(VInt MinOffset);
 49              };
 50 
 51               class  VL_AlignArray :  public  VL_AlignType
 52              {
 53               protected :
 54                  VL_AlignType::Ptr                FType;
 55                  VInt                            FCount;
 56               public :
 57                  VL_AlignArray(VL_AlignType::Ptr Type , VInt Count);
 58 
 59                  VInt                            GetSize() const ;
 60                  VInt                            GetAlignment() const ;
 61                  VL_AlignType::ConstPtr            GetType() const ;
 62                  VInt                            GetCount() const ;
 63              };
 64 
 65               class  VL_AlignStruct :  public  VL_AlignType
 66              {
 67               protected :
 68                  mutable VL_AlignMember::List    FMembers;
 69                  mutable VInt                    FSize;
 70                  mutable VInt                    FAlignment;
 71               public :
 72                  VL_AlignStruct();
 73 
 74                  VInt                            GetSize() const ;
 75                  VInt                            GetAlignment() const ;
 76                   void                             AddMember(VL_AlignType::Ptr Type);
 77                   void                             InsertMember(VInt Index , VL_AlignType::Ptr Type);
 78                   void                             DeleteMember(VInt Index);
 79                  VInt                            GetMemberCount() const ;
 80                   const  VL_AlignMember &             GetMember(VInt Index) const ;
 81                   void                             Refresh() const ;
 82              };
 83 
 84               enum  VLE_AlignBasicType
 85              {
 86                  vabtInt8,
 87                  vabtInt16,
 88                  vabtInt32,
 89                  vabtAsciiChar,
 90                  vabtWideChar,
 91                  vabtFloat,
 92                  vabtDouble
 93              };
 94               class  VL_AlignBasic :  public  VL_AlignType
 95              {
 96               protected :
 97                  VLE_AlignBasicType                FType;
 98               public :
 99                  VL_AlignBasic(VLE_AlignBasicType Type);
100 
101                  VInt                            GetSize() const ;
102                  VInt                            GetAlignment() const ;
103                  VLE_AlignBasicType                GetType() const ;
104              };
105          }
106      }
107  }
108 
109  #endif

    实现文件:
  1  #include  " VL_JIT_MemberAlignment.h "
  2 
  3  namespace  vl
  4  {
  5       namespace  jit
  6      {
  7           namespace  alignment
  8          {
  9              VInt Align(VInt Offset , VInt Alignment)
 10              {
 11                   if (Alignment == 0 )
 12                  {
 13                      Alignment = 1 ;
 14                  }
 15                   return  (Offset + Alignment - 1 ) / Alignment * Alignment;
 16              }
 17 
 18  /* ********************************************************************************************************
 19  VL_AlignMember
 20  ******************************************************************************************************** */
 21 
 22              VL_AlignMember::VL_AlignMember()
 23              {
 24                  FMinOffset = 0 ;
 25              }
 26 
 27              VL_AlignType::ConstPtr VL_AlignMember::GetType() const
 28              {
 29                   return  FType;
 30              }
 31 
 32               void  VL_AlignMember::SetType(VL_AlignType::Ptr Type)
 33              {
 34                  FType = Type;
 35              }
 36 
 37              VInt VL_AlignMember::GetOffset() const
 38              {
 39                   return  Align(FMinOffset,FType -> GetAlignment());
 40              }
 41 
 42               void  VL_AlignMember::SetMinOffset(VInt MinOffset)
 43              {
 44                  FMinOffset = MinOffset;
 45              }
 46 
 47  /* ********************************************************************************************************
 48  VL_AlignArray
 49  ******************************************************************************************************** */
 50 
 51              VL_AlignArray::VL_AlignArray(VL_AlignType::Ptr Type , VInt Count)
 52              {
 53                  FType = Type;
 54                  FCount = Count;
 55              }
 56 
 57              VInt VL_AlignArray::GetSize() const
 58              {
 59                   return  FType -> GetSize() * FCount;
 60              }
 61              
 62              VInt VL_AlignArray::GetAlignment() const
 63              {
 64                   return  FType -> GetAlignment();
 65              }
 66 
 67              VL_AlignType::ConstPtr VL_AlignArray::GetType() const
 68              {
 69                   return  FType;
 70              }
 71 
 72              VInt VL_AlignArray::GetCount() const
 73              {
 74                   return  FCount;
 75              }
 76 
 77  /* ********************************************************************************************************
 78  VL_AlignStruct
 79  ******************************************************************************************************** */
 80 
 81              VL_AlignStruct::VL_AlignStruct()
 82              {
 83                  Refresh();
 84              }
 85 
 86              VInt VL_AlignStruct::GetSize() const
 87              {
 88                   return  FSize;
 89              }
 90 
 91              VInt VL_AlignStruct::GetAlignment() const
 92              {
 93                   return  FAlignment;
 94              }
 95 
 96               void  VL_AlignStruct::AddMember(VL_AlignType::Ptr Type)
 97              {
 98                  VL_AlignMember Member;
 99                  Member.SetType(Type);
100                  FMembers.Add(Member);
101                  Refresh();
102              }
103 
104               void  VL_AlignStruct::InsertMember(VInt Index , VL_AlignType::Ptr Type)
105              {
106                  VL_AlignMember Member;
107                  Member.SetType(Type);
108                  FMembers.Insert(Index,Member);
109                  Refresh();
110              }
111 
112               void  VL_AlignStruct::DeleteMember(VInt Index)
113              {
114                  FMembers.Delete(Index);
115                  Refresh();
116              }
117 
118              VInt VL_AlignStruct::GetMemberCount() const
119              {
120                   return  FMembers.GetCount();
121              }
122 
123               const  VL_AlignMember &  VL_AlignStruct::GetMember(VInt Index) const
124              {
125                   return  FMembers[Index];
126              }
127 
128               void  VL_AlignStruct::Refresh() const
129              {
130                  FSize = 0 ;
131                  FAlignment = 0 ;
132                   for (VInt i = 0 ;i < FMembers.GetCount();i ++ )
133                  {
134                       if (FAlignment < FMembers[i].GetType() -> GetAlignment())
135                      {
136                          FAlignment = FMembers[i].GetType() -> GetAlignment();
137                      }
138                      FMembers[i].SetMinOffset(FSize);
139                      FSize = FMembers[i].GetOffset() + FMembers[i].GetType() -> GetSize();
140                  }
141                  FSize = Align(FSize,FAlignment);
142                   if (FSize == 0 )
143                  {
144                      FAlignment = 1 ;
145                      FSize = 1 ;
146                  }
147              }
148 
149  /* ********************************************************************************************************
150  VL_AlignBasic
151  ******************************************************************************************************** */
152 
153              VL_AlignBasic::VL_AlignBasic(VLE_AlignBasicType Type)
154              {
155                  FType = Type;
156              }
157 
158              VInt VL_AlignBasic::GetSize() const
159              {
160                   switch (FType)
161                  {
162                   case  vabtInt8:         return   sizeof (VInt8s);
163                   case  vabtInt16:         return   sizeof (VInt16s);
164                   case  vabtInt32:         return   sizeof (VInt32s);
165                   case  vabtAsciiChar:     return   sizeof (VChar);
166                   case  vabtWideChar:     return   sizeof (VWChar);
167                   case  vabtFloat:         return   sizeof (VFloat);
168                   case  vabtDouble:     return   sizeof (VDouble);
169                   default :             return   0 ;
170                  }
171              }
172 
173              VInt VL_AlignBasic::GetAlignment() const
174              {
175                   return  GetSize();
176              }
177 
178              VLE_AlignBasicType VL_AlignBasic::GetType() const
179              {
180                   return  FType;
181              }
182          }
183      }
184  }

你可能感兴趣的:(JIT脚本引擎:成员对齐详解)