Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: test/mjsunit/wasm/wasm-module-builder.js

Issue 2084573002: Upgrade Wasm JS API, step 1 (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebaseline interpreter tests Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 WasmFunctionBuilder(name, sig_index) { 5 function emit_u8(bytes, val) {
bradnelson 2016/06/21 06:26:51 Indent seems off on these?
6 bytes.push(val);
7 }
8
9 function emit_u16(bytes, val) {
10 bytes.push(val & 0xff);
11 bytes.push((val >> 8) & 0xff);
12 }
13
14 function emit_u32(bytes, val) {
15 bytes.push(val & 0xff);
16 bytes.push((val >> 8) & 0xff);
17 bytes.push((val >> 16) & 0xff);
18 bytes.push((val >> 24) & 0xff);
19 }
20
21 function emit_string(bytes, string) {
22 // When testing illegal names, we pass a byte array directly.
23 if (string instanceof Array) {
24 emit_varint(bytes, string.length);
25 emit_bytes(bytes, string);
26 return;
27 }
28
29 // This is the hacky way to convert a JavaScript scring to a UTF8 encoded
30 // string only containing single-byte characters.
31 let string_utf8 = unescape(encodeURIComponent(string));
32 emit_varint(bytes, string_utf8.length);
33 for (let i = 0; i < string_utf8.length; i++) {
34 emit_u8(bytes, string_utf8.charCodeAt(i));
35 }
36 }
37
38 function emit_varint(bytes, val) {
39 while (true) {
40 let v = val & 0xff;
41 val = val >>> 7;
42 if (val == 0) {
43 bytes.push(v);
44 break;
45 }
46 bytes.push(v | 0x80);
47 }
48 }
49
50 function emit_bytes(bytes, data) {
51 for (let i = 0; i < data.length; i++) {
52 bytes.push(data[i] & 0xff);
53 }
54 }
55
56 function emit_section(bytes, section_code, content_generator) {
57 // Emit section name.
58 emit_string(bytes, section_names[section_code]);
59 // Emit the section to a temporary buffer: its full length isn't know yet.
60 let tmp_bytes = [];
61 content_generator(tmp_bytes);
62 // Emit section length.
63 emit_varint(bytes, tmp_bytes.length);
64 // Copy the temporary buffer.
65 Array.prototype.push.apply(bytes, tmp_bytes);
66 }
67
68
69 class WasmFunctionBuilder {
bradnelson 2016/06/21 06:26:51 Maybe land this refactoring as a separate CL?
rossberg 2016/06/21 12:23:48 Done.
70 constructor(name, sig_index) {
6 this.name = name; 71 this.name = name;
7 this.sig_index = sig_index; 72 this.sig_index = sig_index;
8 this.exports = []; 73 this.exports = [];
74 }
75
76 exportAs(name) {
77 this.exports.push(name);
78 return this;
79 }
80
81 exportFunc() {
82 this.exports.push(this.name);
83 return this;
84 }
85
86 addBody(body) {
87 this.body = body;
88 return this;
89 }
90
91 addLocals(locals) {
92 this.locals = locals;
93 return this;
94 }
9 } 95 }
10 96
11 WasmFunctionBuilder.prototype.exportAs = function(name) { 97 class WasmModuleBuilder {
12 this.exports.push(name); 98 constructor() {
13 return this;
14 }
15
16 WasmFunctionBuilder.prototype.exportFunc = function() {
17 this.exports.push(this.name);
18 return this;
19 }
20
21 WasmFunctionBuilder.prototype.addBody = function(body) {
22 this.body = body;
23 return this;
24 }
25
26 WasmFunctionBuilder.prototype.addLocals = function(locals) {
27 this.locals = locals;
28 return this;
29 }
30
31 function WasmModuleBuilder() {
32 this.signatures = []; 99 this.signatures = [];
33 this.imports = []; 100 this.imports = [];
34 this.functions = []; 101 this.functions = [];
35 this.exports = []; 102 this.exports = [];
36 this.function_table = []; 103 this.function_table = [];
37 this.data_segments = []; 104 this.data_segments = [];
38 this.explicit = []; 105 this.explicit = [];
39 return this; 106 }
40 } 107
41 108 addStart(start_index) {
42 WasmModuleBuilder.prototype.addStart = function(start_index) {
43 this.start_index = start_index; 109 this.start_index = start_index;
44 } 110 }
45 111
46 WasmModuleBuilder.prototype.addMemory = function(min, max, exp) { 112 addMemory(min, max, exp) {
47 this.memory = {min: min, max: max, exp: exp}; 113 this.memory = {min: min, max: max, exp: exp};
48 return this; 114 return this;
49 } 115 }
50 116
51 WasmModuleBuilder.prototype.addExplicitSection = function(bytes) { 117 addExplicitSection(bytes) {
52 this.explicit.push(bytes); 118 this.explicit.push(bytes);
53 return this; 119 return this;
54 } 120 }
55 121
56 // Add a signature; format is [param_count, param0, param1, ..., retcount, ret0] 122 // Add a signature; format is
57 WasmModuleBuilder.prototype.addSignature = function(sig) { 123 // [param_count, param0, param1, ..., retcount, ret0]
124 addSignature(sig) {
58 // TODO: canonicalize signatures? 125 // TODO: canonicalize signatures?
59 this.signatures.push(sig); 126 this.signatures.push(sig);
60 return this.signatures.length - 1; 127 return this.signatures.length - 1;
61 } 128 }
62 129
63 WasmModuleBuilder.prototype.addFunction = function(name, sig) { 130 addFunction(name, sig) {
64 var sig_index = (typeof sig) == "number" ? sig : this.addSignature(sig); 131 let sig_index = (typeof sig) == "number" ? sig : this.addSignature(sig);
65 var func = new WasmFunctionBuilder(name, sig_index); 132 let func = new WasmFunctionBuilder(name, sig_index);
66 func.index = this.functions.length; 133 func.index = this.functions.length;
67 this.functions.push(func); 134 this.functions.push(func);
68 return func; 135 return func;
69 } 136 }
70 137
71 WasmModuleBuilder.prototype.addImportWithModule = function(module, name, sig) { 138 addImportWithModule(module, name, sig) {
72 var sig_index = (typeof sig) == "number" ? sig : this.addSignature(sig); 139 let sig_index = (typeof sig) == "number" ? sig : this.addSignature(sig);
73 this.imports.push({module: module, name: name, sig_index: sig_index}); 140 this.imports.push({module: module, name: name, sig_index: sig_index});
74 return this.imports.length - 1; 141 return this.imports.length - 1;
75 } 142 }
76 143
77 WasmModuleBuilder.prototype.addImport = function(name, sig) { 144 addImport(name, sig) {
78 this.addImportWithModule(name, undefined, sig); 145 this.addImportWithModule(name, undefined, sig);
79 } 146 }
80 147
81 WasmModuleBuilder.prototype.addDataSegment = function(addr, data, init) { 148 addDataSegment(addr, data, init) {
82 this.data_segments.push({addr: addr, data: data, init: init}); 149 this.data_segments.push({addr: addr, data: data, init: init});
83 return this.data_segments.length - 1; 150 return this.data_segments.length - 1;
84 } 151 }
85 152
86 WasmModuleBuilder.prototype.appendToFunctionTable = function(array) { 153 appendToFunctionTable(array) {
87 this.function_table = this.function_table.concat(array); 154 this.function_table = this.function_table.concat(array);
88 return this; 155 return this;
89 } 156 }
90 157
91 function emit_u8(bytes, val) { 158 toArray(debug) {
92 bytes.push(val & 0xff);
93 }
94
95 function emit_u16(bytes, val) {
96 bytes.push(val & 0xff);
97 bytes.push((val >> 8) & 0xff);
98 }
99
100 function emit_u32(bytes, val) {
101 bytes.push(val & 0xff);
102 bytes.push((val >> 8) & 0xff);
103 bytes.push((val >> 16) & 0xff);
104 bytes.push((val >> 24) & 0xff);
105 }
106
107 function emit_string(bytes, string) {
108 // When testing illegal names, we pass a byte array directly.
109 if (string instanceof Array) {
110 emit_varint(bytes, string.length);
111 emit_bytes(bytes, string);
112 return;
113 }
114
115 // This is the hacky way to convert a JavaScript scring to a UTF8 encoded
116 // string only containing single-byte characters.
117 var string_utf8 = unescape(encodeURIComponent(string));
118 emit_varint(bytes, string_utf8.length);
119 for (var i = 0; i < string_utf8.length; i++) {
120 emit_u8(bytes, string_utf8.charCodeAt(i));
121 }
122 }
123
124 function emit_varint(bytes, val) {
125 while (true) {
126 var v = val & 0xff;
127 val = val >>> 7;
128 if (val == 0) {
129 bytes.push(v);
130 break;
131 }
132 bytes.push(v | 0x80);
133 }
134 }
135
136 function emit_bytes(bytes, data) {
137 for (var i = 0; i < data.length; i++) {
138 bytes.push(data[i] & 0xff);
139 }
140 }
141
142 function emit_section(bytes, section_code, content_generator) {
143 // Emit section name.
144 emit_string(bytes, section_names[section_code]);
145 // Emit the section to a temporary buffer: its full length isn't know yet.
146 var tmp_bytes = [];
147 content_generator(tmp_bytes);
148 // Emit section length.
149 emit_varint(bytes, tmp_bytes.length);
150 // Copy the temporary buffer.
151 Array.prototype.push.apply(bytes, tmp_bytes);
152 }
153
154 WasmModuleBuilder.prototype.toArray = function(debug) {
155 // Add header bytes 159 // Add header bytes
156 var bytes = []; 160 let bytes =
157 bytes = bytes.concat([kWasmH0, kWasmH1, kWasmH2, kWasmH3, 161 [].concat([kWasmH0, kWasmH1, kWasmH2, kWasmH3,
158 kWasmV0, kWasmV1, kWasmV2, kWasmV3]); 162 kWasmV0, kWasmV1, kWasmV2, kWasmV3]);
159 163
160 var wasm = this; 164 let wasm = this;
161 165
162 // Add signatures section 166 // Add signatures section
163 if (wasm.signatures.length > 0) { 167 if (wasm.signatures.length > 0) {
164 if (debug) print("emitting signatures @ " + bytes.length); 168 if (debug) print("emitting signatures @ " + bytes.length);
165 emit_section(bytes, kDeclSignatures, function(bytes) { 169 emit_section(bytes, kDeclSignatures, function(bytes) {
166 emit_varint(bytes, wasm.signatures.length); 170 emit_varint(bytes, wasm.signatures.length);
167 for (sig of wasm.signatures) { 171 for (let sig of wasm.signatures) {
168 emit_u8(bytes, kWasmFunctionTypeForm); 172 emit_u8(bytes, kWasmFunctionTypeForm);
169 for (var j = 0; j < sig.length; j++) { 173 for (let j = 0; j < sig.length; j++) {
170 emit_u8(bytes, sig[j]); 174 emit_u8(bytes, sig[j]);
171 } 175 }
172 } 176 }
173 }); 177 });
174 } 178 }
175 179
176 // Add imports section 180 // Add imports section
177 if (wasm.imports.length > 0) { 181 if (wasm.imports.length > 0) {
178 if (debug) print("emitting imports @ " + bytes.length); 182 if (debug) print("emitting imports @ " + bytes.length);
179 emit_section(bytes, kDeclImportTable, function(bytes) { 183 emit_section(bytes, kDeclImportTable, function(bytes) {
180 emit_varint(bytes, wasm.imports.length); 184 emit_varint(bytes, wasm.imports.length);
181 for (imp of wasm.imports) { 185 for (let imp of wasm.imports) {
182 emit_varint(bytes, imp.sig_index); 186 emit_varint(bytes, imp.sig_index);
183 emit_string(bytes, imp.module); 187 emit_string(bytes, imp.module);
184 emit_string(bytes, imp.name || ''); 188 emit_string(bytes, imp.name || '');
185 } 189 }
186 }); 190 });
187 } 191 }
188 192
189 // Add functions declarations 193 // Add functions declarations
190 var names = false; 194 let has_names = false;
191 var exports = 0; 195 let names = false;
196 let exports = 0;
192 if (wasm.functions.length > 0) { 197 if (wasm.functions.length > 0) {
193 var has_names = false; 198 // emit function signatures
194 199 if (debug) print("emitting function sigs @ " + bytes.length);
195 // emit function signatures 200 emit_section(bytes, kDeclFunctionSignatures, function(bytes) {
196 if (debug) print("emitting function sigs @ " + bytes.length); 201 emit_varint(bytes, wasm.functions.length);
197 emit_section(bytes, kDeclFunctionSignatures, function(bytes) { 202 for (let func of wasm.functions) {
198 emit_varint(bytes, wasm.functions.length); 203 has_names = has_names || (func.name != undefined &&
199 for (func of wasm.functions) { 204 func.name.length > 0);
200 has_names = has_names || (func.name != undefined && 205 exports += func.exports.length;
201 func.name.length > 0); 206 emit_varint(bytes, func.sig_index);
202 exports += func.exports.length; 207 }
203 208 });
204 emit_varint(bytes, func.sig_index);
205 }
206 });
207
208 } 209 }
209 210
210 // Add function table. 211 // Add function table.
211 if (wasm.function_table.length > 0) { 212 if (wasm.function_table.length > 0) {
212 if (debug) print("emitting function table @ " + bytes.length); 213 if (debug) print("emitting function table @ " + bytes.length);
213 emit_section(bytes, kDeclFunctionTable, function(bytes) { 214 emit_section(bytes, kDeclFunctionTable, function(bytes) {
214 emit_varint(bytes, wasm.function_table.length); 215 emit_varint(bytes, wasm.function_table.length);
215 for (index of wasm.function_table) { 216 for (let index of wasm.function_table) {
216 emit_varint(bytes, index); 217 emit_varint(bytes, index);
217 } 218 }
218 }); 219 });
219 } 220 }
220 221
221 // Add memory section 222 // Add memory section
222 if (wasm.memory != undefined) { 223 if (wasm.memory != undefined) {
223 if (debug) print("emitting memory @ " + bytes.length); 224 if (debug) print("emitting memory @ " + bytes.length);
224 emit_section(bytes, kDeclMemory, function(bytes) { 225 emit_section(bytes, kDeclMemory, function(bytes) {
225 emit_varint(bytes, wasm.memory.min); 226 emit_varint(bytes, wasm.memory.min);
226 emit_varint(bytes, wasm.memory.max); 227 emit_varint(bytes, wasm.memory.max);
227 emit_u8(bytes, wasm.memory.exp ? 1 : 0); 228 emit_u8(bytes, wasm.memory.exp ? 1 : 0);
228 }); 229 });
229 } 230 }
230 231
231 232
232 // Add export table. 233 // Add export table.
233 if (exports > 0) { 234 if (exports > 0) {
234 if (debug) print("emitting exports @ " + bytes.length); 235 if (debug) print("emitting exports @ " + bytes.length);
235 emit_section(bytes, kDeclExportTable, function(bytes) { 236 emit_section(bytes, kDeclExportTable, function(bytes) {
236 emit_varint(bytes, exports); 237 emit_varint(bytes, exports);
237 for (func of wasm.functions) { 238 for (let func of wasm.functions) {
238 for (exp of func.exports) { 239 for (let exp of func.exports) {
239 emit_varint(bytes, func.index); 240 emit_varint(bytes, func.index);
240 emit_string(bytes, exp); 241 emit_string(bytes, exp);
241 } 242 }
242 } 243 }
243 }); 244 });
244 } 245 }
245 246
246 // Add start function section. 247 // Add start function section.
247 if (wasm.start_index != undefined) { 248 if (wasm.start_index != undefined) {
248 if (debug) print("emitting start function @ " + bytes.length); 249 if (debug) print("emitting start function @ " + bytes.length);
249 emit_section(bytes, kDeclStartFunction, function(bytes) { 250 emit_section(bytes, kDeclStartFunction, function(bytes) {
250 emit_varint(bytes, wasm.start_index); 251 emit_varint(bytes, wasm.start_index);
251 }); 252 });
252 } 253 }
253 254
254 // Add function bodies. 255 // Add function bodies.
255 if (wasm.functions.length > 0) { 256 if (wasm.functions.length > 0) {
256 // emit function bodies 257 // emit function bodies
257 if (debug) print("emitting function bodies @ " + bytes.length); 258 if (debug) print("emitting function bodies @ " + bytes.length);
258 emit_section(bytes, kDeclFunctionBodies, function(bytes) { 259 emit_section(bytes, kDeclFunctionBodies, function(bytes) {
259 emit_varint(bytes, wasm.functions.length); 260 emit_varint(bytes, wasm.functions.length);
260 for (func of wasm.functions) { 261 for (let func of wasm.functions) {
261 // Function body length will be patched later. 262 // Function body length will be patched later.
262 var local_decls = []; 263 let local_decls = [];
263 var l = func.locals; 264 let l = func.locals;
264 if (l != undefined) { 265 if (l != undefined) {
265 var local_decls_count = 0; 266 let local_decls_count = 0;
266 if (l.i32_count > 0) { 267 if (l.i32_count > 0) {
267 local_decls.push({count: l.i32_count, type: kAstI32}); 268 local_decls.push({count: l.i32_count, type: kAstI32});
268 } 269 }
269 if (l.i64_count > 0) { 270 if (l.i64_count > 0) {
270 local_decls.push({count: l.i64_count, type: kAstI64}); 271 local_decls.push({count: l.i64_count, type: kAstI64});
271 } 272 }
272 if (l.f32_count > 0) { 273 if (l.f32_count > 0) {
273 local_decls.push({count: l.f32_count, type: kAstF32}); 274 local_decls.push({count: l.f32_count, type: kAstF32});
274 } 275 }
275 if (l.f64_count > 0) { 276 if (l.f64_count > 0) {
276 local_decls.push({count: l.f64_count, type: kAstF64}); 277 local_decls.push({count: l.f64_count, type: kAstF64});
277 } 278 }
278 } 279 }
279 var header = new Array(); 280 let header = new Array();
280 281
281 emit_varint(header, local_decls.length); 282 emit_varint(header, local_decls.length);
282 for (decl of local_decls) { 283 for (let decl of local_decls) {
283 emit_varint(header, decl.count); 284 emit_varint(header, decl.count);
284 emit_u8(header, decl.type); 285 emit_u8(header, decl.type);
285 } 286 }
286 287
287 emit_varint(bytes, header.length + func.body.length); 288 emit_varint(bytes, header.length + func.body.length);
288 emit_bytes(bytes, header); 289 emit_bytes(bytes, header);
289 emit_bytes(bytes, func.body); 290 emit_bytes(bytes, func.body);
290 } 291 }
291 }); 292 });
292 } 293 }
293 294
294 // Add data segments. 295 // Add data segments.
295 if (wasm.data_segments.length > 0) { 296 if (wasm.data_segments.length > 0) {
296 if (debug) print("emitting data segments @ " + bytes.length); 297 if (debug) print("emitting data segments @ " + bytes.length);
297 emit_section(bytes, kDeclDataSegments, function(bytes) { 298 emit_section(bytes, kDeclDataSegments, function(bytes) {
298 emit_varint(bytes, wasm.data_segments.length); 299 emit_varint(bytes, wasm.data_segments.length);
299 for (seg of wasm.data_segments) { 300 for (let seg of wasm.data_segments) {
300 emit_varint(bytes, seg.addr); 301 emit_varint(bytes, seg.addr);
301 emit_varint(bytes, seg.data.length); 302 emit_varint(bytes, seg.data.length);
302 emit_bytes(bytes, seg.data); 303 emit_bytes(bytes, seg.data);
303 } 304 }
304 }); 305 });
305 } 306 }
306 307
307 // Add any explicitly added sections 308 // Add any explicitly added sections
308 for (exp of wasm.explicit) { 309 for (let exp of wasm.explicit) {
309 if (debug) print("emitting explicit @ " + bytes.length); 310 if (debug) print("emitting explicit @ " + bytes.length);
310 emit_bytes(bytes, exp); 311 emit_bytes(bytes, exp);
311 } 312 }
312 313
313 // Add function names. 314 // Add function names.
314 if (has_names) { 315 if (has_names) {
315 if (debug) print("emitting names @ " + bytes.length); 316 if (debug) print("emitting names @ " + bytes.length);
316 emit_section(bytes, kDeclNames, function(bytes) { 317 emit_section(bytes, kDeclNames, function(bytes) {
317 emit_varint(bytes, wasm.functions.length); 318 emit_varint(bytes, wasm.functions.length);
318 for (func of wasm.functions) { 319 for (let func of wasm.functions) {
319 var name = func.name == undefined ? "" : func.name; 320 var name = func.name == undefined ? "" : func.name;
320 emit_string(bytes, name); 321 emit_string(bytes, name);
321 emit_u8(bytes, 0); // local names count == 0 322 emit_u8(bytes, 0); // local names count == 0
322 } 323 }
323 }); 324 });
324 } 325 }
325 326
326 // End the module. 327 // End the module.
327 if (debug) print("emitting end @ " + bytes.length); 328 if (debug) print("emitting end @ " + bytes.length);
328 emit_section(bytes, kDeclEnd, function(bytes) {}); 329 emit_section(bytes, kDeclEnd, function(bytes) {});
329 330
330 return bytes; 331 return bytes;
331 } 332 }
332 333
333 WasmModuleBuilder.prototype.toBuffer = function(debug) { 334 toBuffer(debug) {
334 var bytes = this.toArray(debug); 335 let bytes = this.toArray(debug);
335 var buffer = new ArrayBuffer(bytes.length); 336 let buffer = new ArrayBuffer(bytes.length);
336 var view = new Uint8Array(buffer); 337 let view = new Uint8Array(buffer);
337 for (var i = 0; i < bytes.length; i++) { 338 for (let i = 0; i < bytes.length; i++) {
338 var val = bytes[i]; 339 let val = bytes[i];
339 if ((typeof val) == "string") val = val.charCodeAt(0); 340 if ((typeof val) == "string") val = val.charCodeAt(0);
340 view[i] = val | 0; 341 view[i] = val | 0;
341 } 342 }
342 return buffer; 343 return buffer;
344 }
345
346 instantiate(...args) {
bradnelson 2016/06/21 06:26:51 Well, except for this. Or keep the old flavor as a
347 let module = new WebAssembly.Module(this.toBuffer());
348 let instance = new WebAssembly.Instance(module, ...args);
349 return instance;
350 }
343 } 351 }
344
345 WasmModuleBuilder.prototype.instantiate = function(ffi, memory) {
346 var buffer = this.toBuffer();
347 if (memory != undefined) {
348 return Wasm.instantiateModule(buffer, ffi, memory);
349 } else {
350 return Wasm.instantiateModule(buffer, ffi);
351 }
352 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698