Chromium Code Reviews| 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 WasmFunctionBuilder(name, sig_index) { | 5 function WasmFunctionBuilder(name, sig_index) { |
| 6 this.name = name; | 6 this.name = name; |
| 7 this.sig_index = sig_index; | 7 this.sig_index = sig_index; |
| 8 this.exports = []; | 8 this.exports = []; |
| 9 } | 9 } |
| 10 | 10 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 bytes.push(v | 0x80); | 124 bytes.push(v | 0x80); |
| 125 } | 125 } |
| 126 } | 126 } |
| 127 | 127 |
| 128 function emit_bytes(bytes, data) { | 128 function emit_bytes(bytes, data) { |
| 129 for (var i = 0; i < data.length; i++) { | 129 for (var i = 0; i < data.length; i++) { |
| 130 bytes.push(data[i] & 0xff); | 130 bytes.push(data[i] & 0xff); |
| 131 } | 131 } |
| 132 } | 132 } |
| 133 | 133 |
| 134 function emit_section(bytes, section_code, content_generator) { | |
| 135 // Start the section in a temporary buffer: its full length isn't know yet. | |
| 136 var tmp_bytes = []; | |
| 137 var string = section_names[section_code]; | |
| 138 emit_varint(tmp_bytes, string.length); | |
|
binji
2016/03/10 02:20:34
could use emit_string here
JF
2016/03/10 03:20:08
Ooh a new toy :-)
| |
| 139 for (var i = 0; i != string.length; ++i) { | |
| 140 tmp_bytes.push(string.charCodeAt(i)); | |
| 141 } | |
| 142 content_generator(tmp_bytes); | |
| 143 // Now that we know the section length, emit it and copy the section. | |
| 144 emit_varint(bytes, tmp_bytes.length); | |
| 145 Array.prototype.push.apply(bytes, tmp_bytes); | |
| 146 } | |
| 147 | |
| 134 WasmModuleBuilder.prototype.toArray = function(debug) { | 148 WasmModuleBuilder.prototype.toArray = function(debug) { |
| 135 // Add header bytes | 149 // Add header bytes |
| 136 var bytes = []; | 150 var bytes = []; |
| 137 bytes = bytes.concat([kWasmH0, kWasmH1, kWasmH2, kWasmH3, | 151 bytes = bytes.concat([kWasmH0, kWasmH1, kWasmH2, kWasmH3, |
| 138 kWasmV0, kWasmV1, kWasmV2, kWasmV3]); | 152 kWasmV0, kWasmV1, kWasmV2, kWasmV3]); |
| 139 | 153 |
| 154 var wasm = this; | |
| 155 | |
| 140 // Add memory section | 156 // Add memory section |
| 141 if (this.memory != undefined) { | 157 if (wasm.memory != undefined) { |
| 142 if (debug) print("emitting memory @ " + bytes.length); | 158 if (debug) print("emitting memory @ " + bytes.length); |
| 143 emit_u8(bytes, kDeclMemory); | 159 emit_section(bytes, kDeclMemory, function(bytes) { |
| 144 emit_varint(bytes, this.memory.min); | 160 emit_varint(bytes, wasm.memory.min); |
| 145 emit_varint(bytes, this.memory.max); | 161 emit_varint(bytes, wasm.memory.max); |
| 146 emit_u8(bytes, this.memory.exp ? 1 : 0); | 162 emit_u8(bytes, wasm.memory.exp ? 1 : 0); |
| 163 }); | |
| 147 } | 164 } |
| 148 | 165 |
| 149 // Add signatures section | 166 // Add signatures section |
| 150 if (this.signatures.length > 0) { | 167 if (wasm.signatures.length > 0) { |
| 151 if (debug) print("emitting signatures @ " + bytes.length); | 168 if (debug) print("emitting signatures @ " + bytes.length); |
| 152 emit_u8(bytes, kDeclSignatures); | 169 emit_section(bytes, kDeclSignatures, function(bytes) { |
| 153 emit_varint(bytes, this.signatures.length); | 170 emit_varint(bytes, wasm.signatures.length); |
| 154 for (sig of this.signatures) { | 171 for (sig of wasm.signatures) { |
| 155 var params = sig.length - 1; | 172 var params = sig.length - 1; |
| 156 emit_varint(bytes, params); | 173 emit_varint(bytes, params); |
| 157 for (var j = 0; j < sig.length; j++) { | 174 for (var j = 0; j < sig.length; j++) { |
| 158 emit_u8(bytes, sig[j]); | 175 emit_u8(bytes, sig[j]); |
| 176 } | |
| 159 } | 177 } |
| 160 } | 178 }); |
| 161 } | 179 } |
| 162 | 180 |
| 163 // Add imports section | 181 // Add imports section |
| 164 if (this.imports.length > 0) { | 182 if (wasm.imports.length > 0) { |
| 165 if (debug) print("emitting imports @ " + bytes.length); | 183 if (debug) print("emitting imports @ " + bytes.length); |
| 166 emit_u8(bytes, kDeclImportTable); | 184 emit_section(bytes, kDeclImportTable, function(bytes) { |
| 167 emit_varint(bytes, this.imports.length); | 185 emit_varint(bytes, wasm.imports.length); |
| 168 for (imp of this.imports) { | 186 for (imp of wasm.imports) { |
| 169 emit_varint(bytes, imp.sig_index); | 187 emit_varint(bytes, imp.sig_index); |
| 170 emit_string(bytes, imp.module); | 188 emit_string(bytes, imp.module); |
| 171 emit_string(bytes, imp.name || ''); | 189 emit_string(bytes, imp.name || ''); |
| 172 } | 190 } |
| 191 }); | |
| 173 } | 192 } |
| 174 | 193 |
| 175 // Add functions section | 194 // Add functions section |
| 176 var names = false; | 195 var names = false; |
| 177 var exports = 0; | 196 var exports = 0; |
| 178 if (this.functions.length > 0) { | 197 if (wasm.functions.length > 0) { |
| 179 var has_names = false; | 198 var has_names = false; |
| 180 | 199 |
| 181 // emit function signatures | 200 // emit function signatures |
| 182 if (debug) print("emitting function sigs @ " + bytes.length); | 201 if (debug) print("emitting function sigs @ " + bytes.length); |
| 183 emit_u8(bytes, kDeclFunctionSignatures); | 202 emit_section(bytes, kDeclFunctionSignatures, function(bytes) { |
| 184 emit_varint(bytes, this.functions.length); | 203 emit_varint(bytes, wasm.functions.length); |
| 185 for (func of this.functions) { | 204 for (func of wasm.functions) { |
| 186 has_names = has_names || (func.name != undefined && | 205 has_names = has_names || (func.name != undefined && |
| 187 func.name.length > 0); | 206 func.name.length > 0); |
| 188 exports += func.exports.length; | 207 exports += func.exports.length; |
| 189 | 208 |
| 190 emit_varint(bytes, func.sig_index); | 209 emit_varint(bytes, func.sig_index); |
| 191 } | 210 } |
| 211 }); | |
| 192 | 212 |
| 193 // emit function bodies | 213 // emit function bodies |
| 194 if (debug) print("emitting function bodies @ " + bytes.length); | 214 if (debug) print("emitting function bodies @ " + bytes.length); |
| 195 emit_u8(bytes, kDeclFunctionBodies); | 215 emit_section(bytes, kDeclFunctionBodies, function(bytes) { |
| 196 emit_varint(bytes, this.functions.length); | 216 emit_varint(bytes, wasm.functions.length); |
| 197 for (func of this.functions) { | 217 for (func of wasm.functions) { |
| 198 // Function body length will be patched later. | 218 // Function body length will be patched later. |
| 199 var local_decls = []; | 219 var local_decls = []; |
| 200 var l = func.locals; | 220 var l = func.locals; |
| 201 if (l != undefined) { | 221 if (l != undefined) { |
| 202 var local_decls_count = 0; | 222 var local_decls_count = 0; |
| 203 if (l.i32_count > 0) { | 223 if (l.i32_count > 0) { |
| 204 local_decls.push({count: l.i32_count, type: kAstI32}); | 224 local_decls.push({count: l.i32_count, type: kAstI32}); |
| 205 } | 225 } |
| 206 if (l.i64_count > 0) { | 226 if (l.i64_count > 0) { |
| 207 local_decls.push({count: l.i64_count, type: kAstI64}); | 227 local_decls.push({count: l.i64_count, type: kAstI64}); |
| 208 } | 228 } |
| 209 if (l.f32_count > 0) { | 229 if (l.f32_count > 0) { |
| 210 local_decls.push({count: l.f32_count, type: kAstF32}); | 230 local_decls.push({count: l.f32_count, type: kAstF32}); |
| 211 } | 231 } |
| 212 if (l.f64_count > 0) { | 232 if (l.f64_count > 0) { |
| 213 local_decls.push({count: l.f64_count, type: kAstF64}); | 233 local_decls.push({count: l.f64_count, type: kAstF64}); |
| 214 } | 234 } |
| 235 } | |
| 236 var header = new Array(); | |
| 237 | |
| 238 emit_varint(header, local_decls.length); | |
| 239 for (decl of local_decls) { | |
| 240 emit_varint(header, decl.count); | |
| 241 emit_u8(header, decl.type); | |
| 242 } | |
| 243 | |
| 244 emit_varint(bytes, header.length + func.body.length); | |
| 245 emit_bytes(bytes, header); | |
| 246 emit_bytes(bytes, func.body); | |
| 215 } | 247 } |
| 216 var header = new Array(); | 248 }); |
| 217 | |
| 218 emit_varint(header, local_decls.length); | |
| 219 for (decl of local_decls) { | |
| 220 emit_varint(header, decl.count); | |
| 221 emit_u8(header, decl.type); | |
| 222 } | |
| 223 | |
| 224 emit_varint(bytes, header.length + func.body.length); | |
| 225 emit_bytes(bytes, header); | |
| 226 emit_bytes(bytes, func.body); | |
| 227 } | |
| 228 } | 249 } |
| 229 | 250 |
| 230 // emit function names | 251 // emit function names |
| 231 if (has_names) { | 252 if (has_names) { |
| 232 if (debug) print("emitting names @ " + bytes.length); | 253 if (debug) print("emitting names @ " + bytes.length); |
| 233 emit_u8(bytes, kDeclNames); | 254 emit_section(bytes, kDeclNames, function(bytes) { |
| 234 emit_varint(bytes, this.functions.length); | 255 emit_varint(bytes, wasm.functions.length); |
| 235 for (func of this.functions) { | 256 for (func of wasm.functions) { |
| 236 var name = func.name == undefined ? "" : func.name; | 257 var name = func.name == undefined ? "" : func.name; |
| 237 emit_string(bytes, name); | 258 emit_string(bytes, name); |
| 238 emit_u8(bytes, 0); // local names count == 0 | 259 emit_u8(bytes, 0); // local names count == 0 |
| 239 } | 260 } |
| 261 }); | |
| 240 } | 262 } |
| 241 | 263 |
| 242 // Add start function section. | 264 // Add start function section. |
| 243 if (this.start_index != undefined) { | 265 if (wasm.start_index != undefined) { |
| 244 if (debug) print("emitting start function @ " + bytes.length); | 266 if (debug) print("emitting start function @ " + bytes.length); |
| 245 emit_u8(bytes, kDeclStartFunction); | 267 emit_section(bytes, kDeclStartFunction, function(bytes) { |
| 246 emit_varint(bytes, this.start_index); | 268 emit_varint(bytes, wasm.start_index); |
| 269 }); | |
| 247 } | 270 } |
| 248 | 271 |
| 249 if (this.function_table.length > 0) { | 272 if (wasm.function_table.length > 0) { |
| 250 if (debug) print("emitting function table @ " + bytes.length); | 273 if (debug) print("emitting function table @ " + bytes.length); |
| 251 emit_u8(bytes, kDeclFunctionTable); | 274 emit_section(bytes, kDeclFunctionTable, function(bytes) { |
| 252 emit_varint(bytes, this.function_table.length); | 275 emit_varint(bytes, wasm.function_table.length); |
| 253 for (index of this.function_table) { | 276 for (index of wasm.function_table) { |
| 254 emit_varint(bytes, index); | 277 emit_varint(bytes, index); |
| 255 } | 278 } |
| 279 }); | |
| 256 } | 280 } |
| 257 | 281 |
| 258 if (exports > 0) { | 282 if (exports > 0) { |
| 259 if (debug) print("emitting exports @ " + bytes.length); | 283 if (debug) print("emitting exports @ " + bytes.length); |
| 260 emit_u8(bytes, kDeclExportTable); | 284 emit_section(bytes, kDeclExportTable, function(bytes) { |
| 261 emit_varint(bytes, exports); | 285 emit_varint(bytes, exports); |
| 262 for (func of this.functions) { | 286 for (func of wasm.functions) { |
| 263 for (exp of func.exports) { | 287 for (exp of func.exports) { |
| 264 emit_varint(bytes, func.index); | 288 emit_varint(bytes, func.index); |
| 265 emit_string(bytes, exp); | 289 emit_string(bytes, exp); |
| 290 } | |
| 266 } | 291 } |
| 267 } | 292 }); |
| 268 } | 293 } |
| 269 | 294 |
| 270 if (this.data_segments.length > 0) { | 295 if (wasm.data_segments.length > 0) { |
| 271 if (debug) print("emitting data segments @ " + bytes.length); | 296 if (debug) print("emitting data segments @ " + bytes.length); |
| 272 emit_u8(bytes, kDeclDataSegments); | 297 emit_section(bytes, kDeclDataSegments, function(bytes) { |
| 273 emit_varint(bytes, this.data_segments.length); | 298 emit_varint(bytes, wasm.data_segments.length); |
| 274 for (seg of this.data_segments) { | 299 for (seg of wasm.data_segments) { |
| 275 emit_varint(bytes, seg.addr); | 300 for (seg of wasm.data_segments) { |
|
binji
2016/03/10 02:20:34
duped
JF
2016/03/10 03:20:08
Er wtf? I think it was a merge artifact, but it's
| |
| 276 emit_varint(bytes, seg.data.length); | 301 emit_varint(bytes, seg.addr); |
| 277 emit_bytes(bytes, seg.data); | 302 emit_varint(bytes, seg.data.length); |
| 278 } | 303 emit_bytes(bytes, seg.data); |
| 304 } | |
| 305 } | |
| 306 }); | |
| 279 } | 307 } |
| 280 | 308 |
| 281 // Emit any explicitly added sections | 309 // Emit any explicitly added sections |
| 282 for (exp of this.explicit) { | 310 for (exp of wasm.explicit) { |
| 283 if (debug) print("emitting explicit @ " + bytes.length); | 311 if (debug) print("emitting explicit @ " + bytes.length); |
| 284 emit_bytes(bytes, exp); | 312 emit_bytes(bytes, exp); |
| 285 } | 313 } |
| 286 | 314 |
| 287 // End the module. | 315 // End the module. |
| 288 if (debug) print("emitting end @ " + bytes.length); | 316 if (debug) print("emitting end @ " + bytes.length); |
| 289 emit_u8(bytes, kDeclEnd); | 317 emit_section(bytes, kDeclEnd, function(bytes) {}); |
| 290 | 318 |
| 291 return bytes; | 319 return bytes; |
| 292 } | 320 } |
| 293 | 321 |
| 294 WasmModuleBuilder.prototype.toBuffer = function(debug) { | 322 WasmModuleBuilder.prototype.toBuffer = function(debug) { |
| 295 var bytes = this.toArray(debug); | 323 var bytes = this.toArray(debug); |
| 296 var buffer = new ArrayBuffer(bytes.length); | 324 var buffer = new ArrayBuffer(bytes.length); |
| 297 var view = new Uint8Array(buffer); | 325 var view = new Uint8Array(buffer); |
| 298 for (var i = 0; i < bytes.length; i++) { | 326 for (var i = 0; i < bytes.length; i++) { |
| 299 var val = bytes[i]; | 327 var val = bytes[i]; |
| 300 if ((typeof val) == "string") val = val.charCodeAt(0); | 328 if ((typeof val) == "string") val = val.charCodeAt(0); |
| 301 view[i] = val | 0; | 329 view[i] = val | 0; |
| 302 } | 330 } |
| 303 return buffer; | 331 return buffer; |
| 304 } | 332 } |
| 305 | 333 |
| 306 WasmModuleBuilder.prototype.instantiate = function(ffi, memory) { | 334 WasmModuleBuilder.prototype.instantiate = function(ffi, memory) { |
| 307 var buffer = this.toBuffer(); | 335 var buffer = this.toBuffer(); |
| 308 if (memory != undefined) { | 336 if (memory != undefined) { |
| 309 return Wasm.instantiateModule(buffer, ffi, memory); | 337 return Wasm.instantiateModule(buffer, ffi, memory); |
| 310 } else { | 338 } else { |
| 311 return Wasm.instantiateModule(buffer, ffi); | 339 return Wasm.instantiateModule(buffer, ffi); |
| 312 } | 340 } |
| 313 } | 341 } |
| OLD | NEW |