根据
之前的文章的讨论,
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) 阅读(2952)
评论(2) 编辑 收藏 引用 所属分类:
VL++3.0开发纪事