| 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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 var v = val & 0xff; | 118 var v = val & 0xff; |
| 119 val = val >>> 7; | 119 val = val >>> 7; |
| 120 if (val == 0) { | 120 if (val == 0) { |
| 121 bytes.push(v); | 121 bytes.push(v); |
| 122 break; | 122 break; |
| 123 } | 123 } |
| 124 bytes.push(v | 0x80); | 124 bytes.push(v | 0x80); |
| 125 } | 125 } |
| 126 } | 126 } |
| 127 | 127 |
| 128 function emit_bytes(bytes, data) { |
| 129 for (var i = 0; i < data.length; i++) { |
| 130 bytes.push(data[i] & 0xff); |
| 131 } |
| 132 } |
| 133 |
| 128 WasmModuleBuilder.prototype.toArray = function(debug) { | 134 WasmModuleBuilder.prototype.toArray = function(debug) { |
| 129 // Add header bytes | 135 // Add header bytes |
| 130 var bytes = []; | 136 var bytes = []; |
| 131 bytes = bytes.concat([kWasmH0, kWasmH1, kWasmH2, kWasmH3, | 137 bytes = bytes.concat([kWasmH0, kWasmH1, kWasmH2, kWasmH3, |
| 132 kWasmV0, kWasmV1, kWasmV2, kWasmV3]); | 138 kWasmV0, kWasmV1, kWasmV2, kWasmV3]); |
| 133 | 139 |
| 134 // Add memory section | 140 // Add memory section |
| 135 if (this.memory != undefined) { | 141 if (this.memory != undefined) { |
| 136 if (debug) print("emitting memory @ " + bytes.length); | 142 if (debug) print("emitting memory @ " + bytes.length); |
| 137 emit_u8(bytes, kDeclMemory); | 143 emit_u8(bytes, kDeclMemory); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 163 emit_varint(bytes, imp.sig_index); | 169 emit_varint(bytes, imp.sig_index); |
| 164 emit_string(bytes, imp.module); | 170 emit_string(bytes, imp.module); |
| 165 emit_string(bytes, imp.name || ''); | 171 emit_string(bytes, imp.name || ''); |
| 166 } | 172 } |
| 167 } | 173 } |
| 168 | 174 |
| 169 // Add functions section | 175 // Add functions section |
| 170 var names = false; | 176 var names = false; |
| 171 var exports = 0; | 177 var exports = 0; |
| 172 if (this.functions.length > 0) { | 178 if (this.functions.length > 0) { |
| 173 if (debug) print("emitting functions @ " + bytes.length); | 179 var has_names = false; |
| 174 emit_u8(bytes, kDeclFunctions); | 180 |
| 181 // emit function signatures |
| 182 if (debug) print("emitting function sigs @ " + bytes.length); |
| 183 emit_u8(bytes, kDeclFunctionSignatures); |
| 175 emit_varint(bytes, this.functions.length); | 184 emit_varint(bytes, this.functions.length); |
| 176 var index = 0; | |
| 177 for (func of this.functions) { | 185 for (func of this.functions) { |
| 178 var flags = 0; | 186 has_names = has_names || (func.name != undefined && |
| 179 var hasName = func.name != undefined && func.name.length > 0; | 187 func.name.length > 0); |
| 180 names = names || hasName; | 188 exports += func.exports.length; |
| 181 if (hasName) flags |= kDeclFunctionName; | |
| 182 exports += func.exports.length; | |
| 183 | 189 |
| 184 emit_u8(bytes, flags); | 190 emit_varint(bytes, func.sig_index); |
| 185 emit_u16(bytes, func.sig_index); | 191 } |
| 186 | 192 |
| 187 if (hasName) emit_string(bytes, func.name); | 193 // emit function bodies |
| 188 | 194 if (debug) print("emitting function bodies @ " + bytes.length); |
| 195 emit_u8(bytes, kDeclFunctionBodies); |
| 196 emit_varint(bytes, this.functions.length); |
| 197 for (func of this.functions) { |
| 189 // Function body length will be patched later. | 198 // Function body length will be patched later. |
| 190 var length_pos = bytes.length; | |
| 191 emit_u16(bytes, 0); | |
| 192 | |
| 193 var local_decls = []; | 199 var local_decls = []; |
| 194 var l = func.locals; | 200 var l = func.locals; |
| 195 if (l != undefined) { | 201 if (l != undefined) { |
| 196 var local_decls_count = 0; | 202 var local_decls_count = 0; |
| 197 if (l.i32_count > 0) { | 203 if (l.i32_count > 0) { |
| 198 local_decls.push({count: l.i32_count, type: kAstI32}); | 204 local_decls.push({count: l.i32_count, type: kAstI32}); |
| 199 } | 205 } |
| 200 if (l.i64_count > 0) { | 206 if (l.i64_count > 0) { |
| 201 local_decls.push({count: l.i64_count, type: kAstI64}); | 207 local_decls.push({count: l.i64_count, type: kAstI64}); |
| 202 } | 208 } |
| 203 if (l.f32_count > 0) { | 209 if (l.f32_count > 0) { |
| 204 local_decls.push({count: l.f32_count, type: kAstF32}); | 210 local_decls.push({count: l.f32_count, type: kAstF32}); |
| 205 } | 211 } |
| 206 if (l.f64_count > 0) { | 212 if (l.f64_count > 0) { |
| 207 local_decls.push({count: l.f64_count, type: kAstF64}); | 213 local_decls.push({count: l.f64_count, type: kAstF64}); |
| 208 } | 214 } |
| 209 } | 215 } |
| 210 emit_varint(bytes, local_decls.length); | 216 var header = new Array(); |
| 217 |
| 218 emit_varint(header, local_decls.length); |
| 211 for (decl of local_decls) { | 219 for (decl of local_decls) { |
| 212 emit_varint(bytes, decl.count); | 220 emit_varint(header, decl.count); |
| 213 emit_u8(bytes, decl.type); | 221 emit_u8(header, decl.type); |
| 214 } | 222 } |
| 215 | 223 |
| 216 for (var i = 0; i < func.body.length; i++) { | 224 emit_varint(bytes, header.length + func.body.length); |
| 217 emit_u8(bytes, func.body[i]); | 225 emit_bytes(bytes, header); |
| 218 } | 226 emit_bytes(bytes, func.body); |
| 219 var length = bytes.length - length_pos - 2; | 227 } |
| 220 bytes[length_pos] = length & 0xff; | 228 } |
| 221 bytes[length_pos + 1] = (length >> 8) & 0xff; | |
| 222 | 229 |
| 223 index++; | 230 // emit function names |
| 231 if (has_names) { |
| 232 if (debug) print("emitting names @ " + bytes.length); |
| 233 emit_u8(bytes, kDeclNames); |
| 234 emit_varint(bytes, this.functions.length); |
| 235 for (func of this.functions) { |
| 236 var name = func.name == undefined ? "" : func.name; |
| 237 emit_string(bytes, name); |
| 238 emit_u8(bytes, 0); // local names count == 0 |
| 224 } | 239 } |
| 225 } | 240 } |
| 226 | 241 |
| 227 // Add start function section. | 242 // Add start function section. |
| 228 if (this.start_index != undefined) { | 243 if (this.start_index != undefined) { |
| 229 if (debug) print("emitting start function @ " + bytes.length); | 244 if (debug) print("emitting start function @ " + bytes.length); |
| 230 emit_u8(bytes, kDeclStartFunction); | 245 emit_u8(bytes, kDeclStartFunction); |
| 231 emit_varint(bytes, this.start_index); | 246 emit_varint(bytes, this.start_index); |
| 232 } | 247 } |
| 233 | 248 |
| 234 if (this.function_table.length > 0) { | 249 if (this.function_table.length > 0) { |
| 235 if (debug) print("emitting function table @ " + bytes.length); | 250 if (debug) print("emitting function table @ " + bytes.length); |
| 236 emit_u8(bytes, kDeclFunctionTable); | 251 emit_u8(bytes, kDeclFunctionTable); |
| 237 emit_varint(bytes, this.function_table.length); | 252 emit_varint(bytes, this.function_table.length); |
| 238 for (index of this.function_table) { | 253 for (index of this.function_table) { |
| 239 emit_varint(bytes, index); | 254 emit_varint(bytes, index); |
| 240 } | 255 } |
| 241 } | 256 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 252 } | 267 } |
| 253 } | 268 } |
| 254 | 269 |
| 255 if (this.data_segments.length > 0) { | 270 if (this.data_segments.length > 0) { |
| 256 if (debug) print("emitting data segments @ " + bytes.length); | 271 if (debug) print("emitting data segments @ " + bytes.length); |
| 257 emit_u8(bytes, kDeclDataSegments); | 272 emit_u8(bytes, kDeclDataSegments); |
| 258 emit_varint(bytes, this.data_segments.length); | 273 emit_varint(bytes, this.data_segments.length); |
| 259 for (seg of this.data_segments) { | 274 for (seg of this.data_segments) { |
| 260 emit_varint(bytes, seg.addr); | 275 emit_varint(bytes, seg.addr); |
| 261 emit_varint(bytes, seg.data.length); | 276 emit_varint(bytes, seg.data.length); |
| 262 for (var i = 0; i < seg.data.length; i++) { | 277 emit_bytes(bytes, seg.data); |
| 263 emit_u8(bytes, seg.data[i]); | |
| 264 } | |
| 265 } | 278 } |
| 266 } | 279 } |
| 267 | 280 |
| 268 // Emit any explicitly added sections | 281 // Emit any explicitly added sections |
| 269 for (exp of this.explicit) { | 282 for (exp of this.explicit) { |
| 270 if (debug) print("emitting explicit @ " + bytes.length); | 283 if (debug) print("emitting explicit @ " + bytes.length); |
| 271 for (var i = 0; i < exp.length; i++) { | 284 emit_bytes(bytes, exp); |
| 272 emit_u8(bytes, exp[i]); | |
| 273 } | |
| 274 } | 285 } |
| 275 | 286 |
| 276 // End the module. | 287 // End the module. |
| 277 if (debug) print("emitting end @ " + bytes.length); | 288 if (debug) print("emitting end @ " + bytes.length); |
| 278 emit_u8(bytes, kDeclEnd); | 289 emit_u8(bytes, kDeclEnd); |
| 279 | 290 |
| 280 return bytes; | 291 return bytes; |
| 281 } | 292 } |
| 282 | 293 |
| 283 WasmModuleBuilder.prototype.toBuffer = function(debug) { | 294 WasmModuleBuilder.prototype.toBuffer = function(debug) { |
| 284 var bytes = this.toArray(debug); | 295 var bytes = this.toArray(debug); |
| 285 var buffer = new ArrayBuffer(bytes.length); | 296 var buffer = new ArrayBuffer(bytes.length); |
| 286 var view = new Uint8Array(buffer); | 297 var view = new Uint8Array(buffer); |
| 287 for (var i = 0; i < bytes.length; i++) { | 298 for (var i = 0; i < bytes.length; i++) { |
| 288 var val = bytes[i]; | 299 var val = bytes[i]; |
| 289 if ((typeof val) == "string") val = val.charCodeAt(0); | 300 if ((typeof val) == "string") val = val.charCodeAt(0); |
| 290 view[i] = val | 0; | 301 view[i] = val | 0; |
| 291 } | 302 } |
| 292 return buffer; | 303 return buffer; |
| 293 } | 304 } |
| 294 | 305 |
| 295 WasmModuleBuilder.prototype.instantiate = function(ffi, memory) { | 306 WasmModuleBuilder.prototype.instantiate = function(ffi, memory) { |
| 296 var buffer = this.toBuffer(); | 307 var buffer = this.toBuffer(); |
| 297 if (memory != undefined) { | 308 if (memory != undefined) { |
| 298 return Wasm.instantiateModule(buffer, ffi, memory); | 309 return Wasm.instantiateModule(buffer, ffi, memory); |
| 299 } else { | 310 } else { |
| 300 return Wasm.instantiateModule(buffer, ffi); | 311 return Wasm.instantiateModule(buffer, ffi); |
| 301 } | 312 } |
| 302 } | 313 } |
| OLD | NEW |