OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 function StringRef(string) { | 5 function StringRef(string) { |
6 this.pos = -1; | 6 this.pos = -1; |
7 this.string = string; | 7 this.string = string; |
8 } | 8 } |
9 | 9 |
10 function DataRef(data) { | 10 function DataRef(data) { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 var v = val & 0xff; | 129 var v = val & 0xff; |
130 val = val >>> 7; | 130 val = val >>> 7; |
131 if (val == 0) { | 131 if (val == 0) { |
132 bytes.push(v); | 132 bytes.push(v); |
133 break; | 133 break; |
134 } | 134 } |
135 bytes.push(v | 0x80); | 135 bytes.push(v | 0x80); |
136 } | 136 } |
137 } | 137 } |
138 | 138 |
| 139 function emit_section(bytes, section_code, content_generator) { |
| 140 // Start the section in a temporary buffer: its full length isn't know yet. |
| 141 var tmp_bytes = []; |
| 142 var string = section_names[section_code]; |
| 143 emit_varint(tmp_bytes, string.length); |
| 144 for (var i = 0; i != string.length; ++i) { |
| 145 tmp_bytes.push(string.charCodeAt(i)); |
| 146 } |
| 147 content_generator(tmp_bytes); |
| 148 // Now that we know the section length, emit it and copy the section. |
| 149 emit_varint(bytes, tmp_bytes.length); |
| 150 Array.prototype.push.apply(bytes, tmp_bytes); |
| 151 } |
| 152 |
139 WasmModuleBuilder.prototype.toArray = function(debug) { | 153 WasmModuleBuilder.prototype.toArray = function(debug) { |
140 // Add header bytes | 154 // Add header bytes |
141 var bytes = []; | 155 var bytes = []; |
142 bytes = bytes.concat([kWasmH0, kWasmH1, kWasmH2, kWasmH3, | 156 bytes = bytes.concat([kWasmH0, kWasmH1, kWasmH2, kWasmH3, |
143 kWasmV0, kWasmV1, kWasmV2, kWasmV3]); | 157 kWasmV0, kWasmV1, kWasmV2, kWasmV3]); |
144 | 158 |
| 159 var wasm = this; |
| 160 |
145 // Add memory section | 161 // Add memory section |
146 if (this.memory != undefined) { | 162 if (wasm.memory != undefined) { |
147 if (debug) print("emitting memory @ " + bytes.length); | 163 if (debug) print("emitting memory @ " + bytes.length); |
148 emit_u8(bytes, kDeclMemory); | 164 emit_section(bytes, kDeclMemory, function(bytes) { |
149 emit_varint(bytes, this.memory.min); | 165 emit_varint(bytes, wasm.memory.min); |
150 emit_varint(bytes, this.memory.max); | 166 emit_varint(bytes, wasm.memory.max); |
151 emit_u8(bytes, this.memory.exp ? 1 : 0); | 167 emit_u8(bytes, wasm.memory.exp ? 1 : 0); |
| 168 }); |
152 } | 169 } |
153 | 170 |
154 // Add signatures section | 171 // Add signatures section |
155 if (this.signatures.length > 0) { | 172 if (wasm.signatures.length > 0) { |
156 if (debug) print("emitting signatures @ " + bytes.length); | 173 if (debug) print("emitting signatures @ " + bytes.length); |
157 emit_u8(bytes, kDeclSignatures); | 174 emit_section(bytes, kDeclSignatures, function(bytes) { |
158 emit_varint(bytes, this.signatures.length); | 175 emit_varint(bytes, wasm.signatures.length); |
159 for (sig of this.signatures) { | 176 for (sig of wasm.signatures) { |
160 var params = sig.length - 1; | 177 var params = sig.length - 1; |
161 emit_u8(bytes, params); | 178 emit_u8(bytes, params); |
162 for (var j = 0; j < sig.length; j++) { | 179 for (var j = 0; j < sig.length; j++) { |
163 emit_u8(bytes, sig[j]); | 180 emit_u8(bytes, sig[j]); |
| 181 } |
164 } | 182 } |
165 } | 183 }); |
166 } | 184 } |
167 | 185 |
168 // Add imports section | 186 // Add imports section |
169 if (this.imports.length > 0) { | 187 if (wasm.imports.length > 0) { |
170 if (debug) print("emitting imports @ " + bytes.length); | 188 if (debug) print("emitting imports @ " + bytes.length); |
171 emit_u8(bytes, kDeclImportTable); | 189 emit_section(bytes, kDeclImportTable, function(bytes) { |
172 emit_varint(bytes, this.imports.length); | 190 emit_varint(bytes, wasm.imports.length); |
173 for (imp of this.imports) { | 191 for (imp of wasm.imports) { |
174 emit_u16(bytes, imp.sig_index); | 192 emit_u16(bytes, imp.sig_index); |
175 emit_string(bytes, ""); | 193 emit_string(bytes, ""); |
176 emit_string(bytes, imp.name); | 194 emit_string(bytes, imp.name); |
177 } | 195 } |
| 196 }); |
178 } | 197 } |
179 | 198 |
180 // Add functions section | 199 // Add functions section |
181 var names = false; | 200 var names = false; |
182 var exports = 0; | 201 var exports = 0; |
183 if (this.functions.length > 0) { | 202 if (wasm.functions.length > 0) { |
184 if (debug) print("emitting functions @ " + bytes.length); | 203 if (debug) print("emitting functions @ " + bytes.length); |
185 emit_u8(bytes, kDeclFunctions); | 204 emit_section(bytes, kDeclFunctions, function(bytes) { |
186 emit_varint(bytes, this.functions.length); | 205 emit_varint(bytes, wasm.functions.length); |
187 var index = 0; | 206 var index = 0; |
188 for (func of this.functions) { | 207 for (func of wasm.functions) { |
189 var flags = 0; | 208 var flags = 0; |
190 var hasName = func.name != undefined && func.name.length > 0; | 209 var hasName = func.name != undefined && func.name.length > 0; |
191 names = names || hasName; | 210 names = names || hasName; |
192 if (hasName) flags |= kDeclFunctionName; | 211 if (hasName) flags |= kDeclFunctionName; |
193 exports += func.exports.length; | 212 exports += func.exports.length; |
194 | 213 |
195 emit_u8(bytes, flags); | 214 emit_u8(bytes, flags); |
196 emit_u16(bytes, func.sig_index); | 215 emit_u16(bytes, func.sig_index); |
197 | 216 |
198 if (hasName) emit_string(bytes, func.name); | 217 if (hasName) emit_string(bytes, func.name); |
199 | 218 |
200 // Function body length will be patched later. | 219 // Function body length will be patched later. |
201 var length_pos = bytes.length; | 220 var length_pos = bytes.length; |
202 emit_u16(bytes, 0); | 221 emit_u16(bytes, 0); |
203 | 222 |
204 var local_decls = []; | 223 var local_decls = []; |
205 var l = func.locals; | 224 var l = func.locals; |
206 if (l != undefined) { | 225 if (l != undefined) { |
207 var local_decls_count = 0; | 226 var local_decls_count = 0; |
208 if (l.i32_count > 0) { | 227 if (l.i32_count > 0) { |
209 local_decls.push({count: l.i32_count, type: kAstI32}); | 228 local_decls.push({count: l.i32_count, type: kAstI32}); |
210 } | 229 } |
211 if (l.i64_count > 0) { | 230 if (l.i64_count > 0) { |
212 local_decls.push({count: l.i64_count, type: kAstI64}); | 231 local_decls.push({count: l.i64_count, type: kAstI64}); |
213 } | 232 } |
214 if (l.f32_count > 0) { | 233 if (l.f32_count > 0) { |
215 local_decls.push({count: l.f32_count, type: kAstF32}); | 234 local_decls.push({count: l.f32_count, type: kAstF32}); |
216 } | 235 } |
217 if (l.f64_count > 0) { | 236 if (l.f64_count > 0) { |
218 local_decls.push({count: l.f64_count, type: kAstF64}); | 237 local_decls.push({count: l.f64_count, type: kAstF64}); |
219 } | 238 } |
| 239 } |
| 240 emit_u8(bytes, local_decls.length); |
| 241 for (decl of local_decls) { |
| 242 emit_varint(bytes, decl.count); |
| 243 emit_u8(bytes, decl.type); |
| 244 } |
| 245 |
| 246 for (var i = 0; i < func.body.length; i++) { |
| 247 emit_u8(bytes, func.body[i]); |
| 248 } |
| 249 var length = bytes.length - length_pos - 2; |
| 250 bytes[length_pos] = length & 0xff; |
| 251 bytes[length_pos + 1] = (length >> 8) & 0xff; |
| 252 |
| 253 index++; |
220 } | 254 } |
221 emit_u8(bytes, local_decls.length); | 255 }); |
222 for (decl of local_decls) { | |
223 emit_varint(bytes, decl.count); | |
224 emit_u8(bytes, decl.type); | |
225 } | |
226 | |
227 for (var i = 0; i < func.body.length; i++) { | |
228 emit_u8(bytes, func.body[i]); | |
229 } | |
230 var length = bytes.length - length_pos - 2; | |
231 bytes[length_pos] = length & 0xff; | |
232 bytes[length_pos + 1] = (length >> 8) & 0xff; | |
233 | |
234 index++; | |
235 } | |
236 } | 256 } |
237 | 257 |
238 // Add start function section. | 258 // Add start function section. |
239 if (this.start_index != undefined) { | 259 if (wasm.start_index != undefined) { |
240 if (debug) print("emitting start function @ " + bytes.length); | 260 if (debug) print("emitting start function @ " + bytes.length); |
241 emit_u8(bytes, kDeclStartFunction); | 261 emit_section(bytes, kDeclStartFunction, function(bytes) { |
242 emit_varint(bytes, this.start_index); | 262 emit_varint(bytes, wasm.start_index); |
| 263 }); |
243 } | 264 } |
244 | 265 |
245 if (this.function_table.length > 0) { | 266 if (wasm.function_table.length > 0) { |
246 if (debug) print("emitting function table @ " + bytes.length); | 267 if (debug) print("emitting function table @ " + bytes.length); |
247 emit_u8(bytes, kDeclFunctionTable); | 268 emit_section(bytes, kDeclFunctionTable, function(bytes) { |
248 emit_varint(bytes, this.function_table.length); | 269 emit_varint(bytes, wasm.function_table.length); |
249 for (index of this.function_table) { | 270 for (index of wasm.function_table) { |
250 emit_u16(bytes, index); | 271 emit_u16(bytes, index); |
251 } | 272 } |
| 273 }); |
252 } | 274 } |
253 | 275 |
254 if (exports > 0) { | 276 if (exports > 0) { |
255 if (debug) print("emitting exports @ " + bytes.length); | 277 if (debug) print("emitting exports @ " + bytes.length); |
256 emit_u8(bytes, kDeclExportTable); | 278 emit_section(bytes, kDeclExportTable, function(bytes) { |
257 emit_varint(bytes, exports); | 279 emit_varint(bytes, exports); |
258 for (func of this.functions) { | 280 for (func of wasm.functions) { |
259 for (exp of func.exports) { | 281 for (exp of func.exports) { |
260 emit_u16(bytes, func.index); | 282 emit_u16(bytes, func.index); |
261 emit_string(bytes, exp); | 283 emit_string(bytes, exp); |
| 284 } |
262 } | 285 } |
263 } | 286 }); |
264 } | 287 } |
265 | 288 |
266 if (this.data_segments.length > 0) { | 289 if (wasm.data_segments.length > 0) { |
267 if (debug) print("emitting data segments @ " + bytes.length); | 290 if (debug) print("emitting data segments @ " + bytes.length); |
268 emit_u8(bytes, kDeclDataSegments); | 291 emit_section(bytes, kDeclDataSegments, function(bytes) { |
269 emit_varint(bytes, this.data_segments.length); | 292 emit_varint(bytes, wasm.data_segments.length); |
270 for (seg of this.data_segments) { | 293 for (seg of wasm.data_segments) { |
271 emit_u32(bytes, seg.addr); | 294 emit_u32(bytes, seg.addr); |
272 emit_data_ref(bytes, seg.data); | 295 emit_data_ref(bytes, seg.data); |
273 emit_u32(bytes, seg.data.length); | 296 emit_u32(bytes, seg.data.length); |
274 emit_u8(bytes, seg.init ? 1 : 0); | 297 emit_u8(bytes, seg.init ? 1 : 0); |
275 } | 298 } |
| 299 }); |
276 } | 300 } |
277 | 301 |
278 // Emit any explicitly added sections | 302 // Emit any explicitly added sections |
279 for (exp of this.explicit) { | 303 for (exp of wasm.explicit) { |
280 if (debug) print("emitting explicit @ " + bytes.length); | 304 if (debug) print("emitting explicit @ " + bytes.length); |
281 for (var i = 0; i < exp.length; i++) { | 305 for (var i = 0; i < exp.length; i++) { |
282 emit_u8(bytes, exp[i]); | 306 emit_u8(bytes, exp[i]); |
283 } | 307 } |
284 } | 308 } |
285 | 309 |
286 // End the module. | 310 // End the module. |
287 if (debug) print("emitting end @ " + bytes.length); | 311 if (debug) print("emitting end @ " + bytes.length); |
288 emit_u8(bytes, kDeclEnd); | 312 emit_section(bytes, kDeclEnd, function(bytes) {}); |
289 | 313 |
290 // Collect references and canonicalize strings. | 314 // Collect references and canonicalize strings. |
291 var strings = new Object(); | 315 var strings = new Object(); |
292 var data_segments = []; | 316 var data_segments = []; |
293 var count = 0; | 317 var count = 0; |
294 for (var i = 0; i < bytes.length; i++) { | 318 for (var i = 0; i < bytes.length; i++) { |
295 var b = bytes[i]; | 319 var b = bytes[i]; |
296 if (b instanceof StringRef) { | 320 if (b instanceof StringRef) { |
297 count++; | 321 count++; |
298 var prev = strings[b.string]; | 322 var prev = strings[b.string]; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 } | 381 } |
358 | 382 |
359 WasmModuleBuilder.prototype.instantiate = function(ffi, memory) { | 383 WasmModuleBuilder.prototype.instantiate = function(ffi, memory) { |
360 var buffer = this.toBuffer(); | 384 var buffer = this.toBuffer(); |
361 if (memory != undefined) { | 385 if (memory != undefined) { |
362 return Wasm.instantiateModule(buffer, ffi, memory); | 386 return Wasm.instantiateModule(buffer, ffi, memory); |
363 } else { | 387 } else { |
364 return Wasm.instantiateModule(buffer, ffi); | 388 return Wasm.instantiateModule(buffer, ffi); |
365 } | 389 } |
366 } | 390 } |
OLD | NEW |