随笔-341  评论-2670  文章-0  trackbacks-0
    根据之前的文章的讨论,Vczh Library++3.0泛型全局存储是一个大型的映射。假设你有下面的代码:
1 generic<T>
2 structure StorageType
3 {
4   wchar* name;
5   T data;
6 }
7 
8 generic<T>
9 variable StoragetType<T> storage;

    那么当你在使用storage<int>和storage<bool>的时候,实际上是在使用两个不同的全局变量。但是当你的storage实现在assembly A里面的时候,assembly B和assembly C里面所看到的&storage<int>是一样的。因此为storage<T>分配空间实际上是虚拟机做的事情。这里的assembly ABC可以看成是跟dll差不多的东西。

    这次实现了泛型全局存储之后,我还开发了一个新的Log函数用来把虚拟机的内部状态全部都log出来。虚拟机在加载一个二进制的assembly之后,首先会对它进行链接,其具体的做法就是对指令进行修改。而当指令要求特化一些泛型函数或泛型全局存储的同时,虚拟机会在一个内部创建的assembly为这些实例化的东西分配空间。因此在执行了UnitTest之后,可以看到链接前和链接后的assembly,以及虚拟机为了链接他们而保存的数据结构。现在我们来看一个例子。这个例子很简单,两个assembly包含下面的内容:
    1、storage<T>的声明
    2、Get<T>函数用于读取
    3、Set<T>函数用于写入
    然后main函数会分别通过直接读写、以及利用Get<T>和Set<T>进行间接读写的方法(用于检查特化后的模板函数对泛型全局存储的操作),对storage<int>和storage<char>写入两个值,读出来相加,最后返回结果。首先看代码:

1:programStorage.txt
 1 /*NativeX Code*/
 2 unit nativex_program_generated;
 3 generic<T>
 4 structure Storage
 5 {
 6     T data;
 7 }
 8 
 9 generic<U>
10 variable Storage<U> storage;
11 
12 generic<V>
13 function V Get()
14     (result = storage<V>.data);

2:programMain.txt
 1 /*NativeX Code*/
 2 unit nativex_program_generated;
 3 generic<T>
 4 structure Storage alias programStorage.Storage
 5 {
 6     T data;
 7 }
 8 
 9 generic<U>
10 variable Storage<U> storage alias programStorage.storage;
11 
12 generic<V>
13 function V Get() alias programStorage.Get;
14 
15 function int32 main()
16 {
17     (storage<int32>.data = 10s32);
18     Set<char>('');
19     variable int32 a = Get<int32>();
20     variable int32 b = storage<char>.data;
21     (result = (a + b));
22 }
23 
24 generic<W>
25 function void Set(W value)
26     (storage<W>.data = value);

    然后是他们产生的二进制程序集(链接前)的内容,以及虚拟机在执行完所有代码之后所产生的数据结构和那两个二进制程序集在链接后的内容:

1:programStorage
 1 /*NativeX Code*/
 2 unit nativex_program_generated;
 3 generic<T>
 4 structure Storage
 5 {
 6     T data;
 7 }
 8 
 9 generic<U>
10 variable Storage<U> storage;
11 
12 generic<V>
13 function V Get()
14     (result = storage<V>.data);
15 
16 
17 /*Assembly*/
18 .data
19 .label
20      0: instruction 3
21 .code
22 // unit nativex_program_generated;
23      0: stack_reserve 0
24      1: stack_reserve 0
25      2: ret 0
26 // function V Get()
27      3: stack_reserve 0
28 // (result = storage<V>.data);
29      4: generic_pushdata 0
30      5: push s32 0
31      6: add s32
32      7: resptr
33      8: copymem 0[Linear]
34 // function V Get()
35      9: stack_reserve 0
36     10: ret 0
37 .exports
38 Assembly Name: programStorage
39 Function Entries[0= {
40   Name = Get
41   Arguments = 1
42   Instruction = 3
43   Lengtht = 8
44   UniqueName = [programStorage]::[Get]
45 }
46 Variable Entries[0= {
47   Name = storage
48   Arguments = 1
49   Size = 1*T0 + 0
50   UniqueName = [programStorage]::[storage]
51 }
52 Targets[0= {
53   AssemblyName = programStorage
54   SymbolName = storage
55   ArgumentSizes[0= 1*T0 + 0
56   ArgumentNames[0= {0}
57 }
58 Linears[0= 1*T0 + 0
59 

2:programMain
  1 /*NativeX Code*/
  2 unit nativex_program_generated;
  3 generic<T>
  4 structure Storage alias programStorage.Storage
  5 {
  6     T data;
  7 }
  8 
  9 generic<U>
 10 variable Storage<U> storage alias programStorage.storage;
 11 
 12 generic<V>
 13 function V Get() alias programStorage.Get;
 14 
 15 function int32 main()
 16 {
 17     (storage<int32>.data = 10s32);
 18     Set<char>('');
 19     variable int32 a = Get<int32>();
 20     variable int32 b = storage<char>.data;
 21     (result = (a + b));
 22 }
 23 
 24 generic<W>
 25 function void Set(W value)
 26     (storage<W>.data = value);
 27 
 28 
 29 /*Assembly*/
 30 .data
 31 .label
 32      0: instruction 3
 33      1: instruction 32
 34 .code
 35 // unit nativex_program_generated;
 36      0: stack_reserve 0
 37      1: stack_reserve 0
 38      2: ret 0
 39 // function int32 main()
 40      3: stack_reserve 8
 41 // (storage<int32>.data = 10s32);
 42      4: push s32 10
 43      5: generic_pushdata 0
 44      6: push s32 0
 45      7: add s32
 46      8: write s32
 47 // Set<char>('');
 48      9: stack_reserve 1
 49     10: push s8 20
 50     11: stack_top 1
 51     12: generic_callfunc 1
 52     13: stack_reserve -1
 53 // variable int32 a = Get<int32>();
 54     14: stack_offset -4
 55     15: generic_callfunc 2
 56 // variable int32 b = storage<char>.data;
 57     16: generic_pushdata 3
 58     17: push s32 0
 59     18: add s32
 60     19: read s8
 61     20: convert s32 s8
 62     21: stack_offset -8
 63     22: write s32
 64 // (result = (a + b));
 65     23: stack_offset -8
 66     24: read s32
 67     25: stack_offset -4
 68     26: read s32
 69     27: add s32
 70     28: resptr
 71     29: write s32
 72 // function int32 main()
 73     30: stack_reserve -8
 74     31: ret 0
 75 // function void Set(W value)
 76     32: stack_reserve 0
 77 // (storage<W>.data = value);
 78     33: stack_offset 16
 79     34: generic_pushdata 4
 80     35: push s32 0
 81     36: add s32
 82     37: copymem 0[Linear]
 83 // function void Set(W value)
 84     38: stack_reserve 0
 85     39: ret 0[Linear]
 86 .exports
 87 Assembly Name: programMain
 88 Exports[0= (3, main)
 89 Function Entries[0= {
 90   Name = Set
 91   Arguments = 1
 92   Instruction = 32
 93   Lengtht = 8
 94   UniqueName = [programMain]::[Set]
 95 }
 96 Targets[0= {
 97   AssemblyName = programStorage
 98   SymbolName = storage
 99   ArgumentSizes[0= 4
100   ArgumentNames[0= s32
101 }
102 Targets[1= {
103   AssemblyName = programMain
104   SymbolName = Set
105   ArgumentSizes[0= 1
106   ArgumentNames[0= char_type
107 }
108 Targets[2= {
109   AssemblyName = programStorage
110   SymbolName = Get
111   ArgumentSizes[0= 4
112   ArgumentNames[0= s32
113 }
114 Targets[3= {
115   AssemblyName = programStorage
116   SymbolName = storage
117   ArgumentSizes[0= 1
118   ArgumentNames[0= char_type
119 }
120 Targets[4= {
121   AssemblyName = programStorage
122   SymbolName = storage
123   ArgumentSizes[0= 1*T0 + 0
124   ArgumentNames[0= {0}
125 }
126 Linears[0= 1*T0 + 0
127 

3:虚拟机
  1 -----------------------------------------------
  2 Loaded Assemblies[0]
  3 -----------------------------------------------
  4 .data
  5 .label
  6 .code
  7      0: stack_reserve 0
  8      1: stack_offset 16
  9      2: push u32 11268052
 10      3: push s32 0
 11      4: add s32
 12      5: copymem 1
 13      6: stack_reserve 0
 14      7: ret 1
 15      8: stack_reserve 0
 16      9: push u32 11268048
 17     10: push s32 0
 18     11: add s32
 19     12: resptr
 20     13: copymem 4
 21     14: stack_reserve 0
 22     15: ret 0
 23 
 24 -----------------------------------------------
 25 Loaded Assemblies[1]
 26 -----------------------------------------------
 27 .data
 28 .label
 29      0: instruction 3
 30 .code
 31      0: stack_reserve 0
 32      1: stack_reserve 0
 33      2: ret 0
 34      3: stack_reserve 0
 35      4: generic_pushdata 0
 36      5: push s32 0
 37      6: add s32
 38      7: resptr
 39      8: copymem 0[Linear]
 40      9: stack_reserve 0
 41     10: ret 0
 42 .exports
 43 Assembly Name: programStorage
 44 Function Entries[0= {
 45   Name = Get
 46   Arguments = 1
 47   Instruction = 3
 48   Lengtht = 8
 49   UniqueName = [programStorage]::[Get]
 50 }
 51 Variable Entries[0= {
 52   Name = storage
 53   Arguments = 1
 54   Size = 1*T0 + 0
 55   UniqueName = [programStorage]::[storage]
 56 }
 57 Targets[0= {
 58   AssemblyName = programStorage
 59   SymbolName = storage
 60   ArgumentSizes[0= 1*T0 + 0
 61   ArgumentNames[0= {0}
 62 }
 63 Linears[0= 1*T0 + 0
 64 
 65 -----------------------------------------------
 66 Loaded Assemblies[2]
 67 -----------------------------------------------
 68 .data
 69 .label
 70      0: instruction 3
 71      1: instruction 32
 72 .code
 73      0: stack_reserve 0
 74      1: stack_reserve 0
 75      2: ret 0
 76      3: stack_reserve 8
 77      4: push s32 10
 78      5: push u32 11268048
 79      6: push s32 0
 80      7: add s32
 81      8: write s32
 82      9: stack_reserve 1
 83     10: push s8 20
 84     11: stack_top 1
 85     12: call 0 0
 86     13: stack_reserve -1
 87     14: stack_offset -4
 88     15: call 8 0
 89     16: push u32 11268052
 90     17: push s32 0
 91     18: add s32
 92     19: read s8
 93     20: convert s32 s8
 94     21: stack_offset -8
 95     22: write s32
 96     23: stack_offset -8
 97     24: read s32
 98     25: stack_offset -4
 99     26: read s32
100     27: add s32
101     28: resptr
102     29: write s32
103     30: stack_reserve -8
104     31: ret 0
105     32: stack_reserve 0
106     33: stack_offset 16
107     34: generic_pushdata 4
108     35: push s32 0
109     36: add s32
110     37: copymem 0[Linear]
111     38: stack_reserve 0
112     39: ret 0[Linear]
113 .exports
114 Assembly Name: programMain
115 Exports[0= (3, main)
116 Function Entries[0= {
117   Name = Set
118   Arguments = 1
119   Instruction = 32
120   Lengtht = 8
121   UniqueName = [programMain]::[Set]
122 }
123 Targets[0= {
124   AssemblyName = programStorage
125   SymbolName = storage
126   ArgumentSizes[0= 4
127   ArgumentNames[0= s32
128 }
129 Targets[1= {
130   AssemblyName = programMain
131   SymbolName = Set
132   ArgumentSizes[0= 1
133   ArgumentNames[0= char_type
134 }
135 Targets[2= {
136   AssemblyName = programStorage
137   SymbolName = Get
138   ArgumentSizes[0= 4
139   ArgumentNames[0= s32
140 }
141 Targets[3= {
142   AssemblyName = programStorage
143   SymbolName = storage
144   ArgumentSizes[0= 1
145   ArgumentNames[0= char_type
146 }
147 Targets[4= {
148   AssemblyName = programStorage
149   SymbolName = storage
150   ArgumentSizes[0= 1*T0 + 0
151   ArgumentNames[0= {0}
152 }
153 Linears[0= 1*T0 + 0
154 
155 -----------------------------------------------
156 Assembly Name Map
157 -----------------------------------------------
158 programMain = 2
159 programStorage = 1
160 
161 -----------------------------------------------
162 Function Pointer Map
163 -----------------------------------------------
164 0 = Assemblies[-1].Instructions[-1]
165 1 = Assemblies[1].Instructions[3]
166 2 = Assemblies[2].Instructions[3]
167 3 = Assemblies[2].Instructions[32]
168 4 = Assemblies[0].Instructions[0]
169 5 = Assemblies[0].Instructions[8]
170 
171 -----------------------------------------------
172 Loaded Symbol Names
173 -----------------------------------------------
174 programMain.main
175 
176 -----------------------------------------------
177 Generic Function Entry Map
178 -----------------------------------------------
179 programMain.Set
180   Instruction = 32
181   Count = 8
182   Assembly = 2
183   Generic Argument Count = 1
184   Unique Entry ID = [programMain]::[Set]
185 programStorage.Get
186   Instruction = 3
187   Count = 8
188   Assembly = 1
189   Generic Argument Count = 1
190   Unique Entry ID = [programStorage]::[Get]
191 
192 -----------------------------------------------
193 Generic Variable Entry Map
194 -----------------------------------------------
195 programStorage.storage
196   Generic Argument Count = 1
197   Size = 1*T0 + 0
198   Unique Entry ID = [programStorage]::[storage]
199 
200 -----------------------------------------------
201 Instanciated Generic Function Map
202 -----------------------------------------------
203 [programMain]::[Set]<char_type> = 4
204 [programStorage]::[Get]<s32> = 5
205 
206 -----------------------------------------------
207 Instanciated Generic Variable Map
208 -----------------------------------------------
209 [programStorage]::[storage]<char_type> = 11268052
210 [programStorage]::[storage]<s32> = 11268048
211 
212 -----------------------------------------------
213 Cached Generic Target List
214 -----------------------------------------------
215 Assembly Name = programStorage
216 Symbol Name = storage
217 Arguments = {
218   Argument[0= {
219     Name = s32
220     Size = 4
221   }
222 }
223 Assembly Name = programMain
224 Symbol Name = Set
225 Arguments = {
226   Argument[0= {
227     Name = char_type
228     Size = 1
229   }
230 }
231 Assembly Name = programStorage
232 Symbol Name = storage
233 Arguments = {
234   Argument[0= {
235     Name = char_type
236     Size = 1
237   }
238 }
239 Assembly Name = programStorage
240 Symbol Name = Get
241 Arguments = {
242   Argument[0= {
243     Name = s32
244     Size = 4
245   }
246 }
247 Assembly Name = programStorage
248 Symbol Name = storage
249 Arguments = {
250   Argument[0= {
251     Name = s32
252     Size = 4
253   }
254 }
255 Assembly Name = programStorage
256 Symbol Name = storage
257 Arguments = {
258   Argument[0= {
259     Name = char_type
260     Size = 1
261   }
262 }
263 
264 

    如果仔细观察的话你会发现我暂时还没有对中间的数据结构进行优化,导致有时候会产生重复的信息。不过优化也是迟早的事情,现在先做功能,太早优化是魔鬼也。

    最新的代码可以在这里获得。
posted on 2010-07-17 21:28 陈梓瀚(vczh) 阅读(2829) 评论(2)  编辑 收藏 引用 所属分类: VL++3.0开发纪事

评论:
# re: Vczh Library++ 3.0实现泛型全局存储 2010-07-20 06:53 | 全图灵死程
- -!!   回复  更多评论
  
# re: Vczh Library++ 3.0实现泛型全局存储 2010-08-08 23:19 | 文殊广法
太深奥,看不懂。  回复  更多评论
  

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理