 Chromium Code Reviews
 Chromium Code Reviews Issue 2390113003:
  [wasm] Refactor import handling for 0xC.  (Closed)
    
  
    Issue 2390113003:
  [wasm] Refactor import handling for 0xC.  (Closed) 
  | 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 // Used for encoding f32 and double constants to bits. | |
| 6 let __buffer = new ArrayBuffer(8); | |
| 7 let byte_view = new Int8Array(__buffer); | |
| 8 let f32_view = new Float32Array(__buffer); | |
| 9 let f64_view = new Float64Array(__buffer); | |
| 10 | |
| 5 class Binary extends Array { | 11 class Binary extends Array { | 
| 6 emit_u8(val) { | 12 emit_u8(val) { | 
| 7 this.push(val); | 13 this.push(val); | 
| 8 } | 14 } | 
| 9 | 15 | 
| 10 emit_u16(val) { | 16 emit_u16(val) { | 
| 11 this.push(val & 0xff); | 17 this.push(val & 0xff); | 
| 12 this.push((val >> 8) & 0xff); | 18 this.push((val >> 8) & 0xff); | 
| 13 } | 19 } | 
| 14 | 20 | 
| 15 emit_u32(val) { | 21 emit_u32(val) { | 
| 16 this.push(val & 0xff); | 22 this.push(val & 0xff); | 
| 17 this.push((val >> 8) & 0xff); | 23 this.push((val >> 8) & 0xff); | 
| 18 this.push((val >> 16) & 0xff); | 24 this.push((val >> 16) & 0xff); | 
| 19 this.push((val >> 24) & 0xff); | 25 this.push((val >> 24) & 0xff); | 
| 20 } | 26 } | 
| 21 | 27 | 
| 22 emit_varint(val) { | 28 emit_u32v(val) { | 
| 23 while (true) { | 29 while (true) { | 
| 24 let v = val & 0xff; | 30 let v = val & 0xff; | 
| 25 val = val >>> 7; | 31 val = val >>> 7; | 
| 26 if (val == 0) { | 32 if (val == 0) { | 
| 27 this.push(v); | 33 this.push(v); | 
| 28 break; | 34 break; | 
| 29 } | 35 } | 
| 30 this.push(v | 0x80); | 36 this.push(v | 0x80); | 
| 31 } | 37 } | 
| 32 } | 38 } | 
| 33 | 39 | 
| 34 emit_bytes(data) { | 40 emit_bytes(data) { | 
| 35 for (let i = 0; i < data.length; i++) { | 41 for (let i = 0; i < data.length; i++) { | 
| 36 this.push(data[i] & 0xff); | 42 this.push(data[i] & 0xff); | 
| 37 } | 43 } | 
| 38 } | 44 } | 
| 39 | 45 | 
| 40 emit_string(string) { | 46 emit_string(string) { | 
| 41 // When testing illegal names, we pass a byte array directly. | 47 // When testing illegal names, we pass a byte array directly. | 
| 42 if (string instanceof Array) { | 48 if (string instanceof Array) { | 
| 43 this.emit_varint(string.length); | 49 this.emit_u32v(string.length); | 
| 44 this.emit_bytes(string); | 50 this.emit_bytes(string); | 
| 45 return; | 51 return; | 
| 46 } | 52 } | 
| 47 | 53 | 
| 48 // This is the hacky way to convert a JavaScript string to a UTF8 encoded | 54 // This is the hacky way to convert a JavaScript string to a UTF8 encoded | 
| 49 // string only containing single-byte characters. | 55 // string only containing single-byte characters. | 
| 50 let string_utf8 = unescape(encodeURIComponent(string)); | 56 let string_utf8 = unescape(encodeURIComponent(string)); | 
| 51 this.emit_varint(string_utf8.length); | 57 this.emit_u32v(string_utf8.length); | 
| 52 for (let i = 0; i < string_utf8.length; i++) { | 58 for (let i = 0; i < string_utf8.length; i++) { | 
| 53 this.emit_u8(string_utf8.charCodeAt(i)); | 59 this.emit_u8(string_utf8.charCodeAt(i)); | 
| 54 } | 60 } | 
| 55 } | 61 } | 
| 56 | 62 | 
| 57 emit_header() { | 63 emit_header() { | 
| 58 this.push(kWasmH0, kWasmH1, kWasmH2, kWasmH3, | 64 this.push(kWasmH0, kWasmH1, kWasmH2, kWasmH3, | 
| 59 kWasmV0, kWasmV1, kWasmV2, kWasmV3); | 65 kWasmV0, kWasmV1, kWasmV2, kWasmV3); | 
| 60 } | 66 } | 
| 61 | 67 | 
| 62 emit_section(section_code, content_generator) { | 68 emit_section(section_code, content_generator) { | 
| 63 // Emit section name. | 69 // Emit section name. | 
| 64 this.emit_u8(section_code); | 70 this.emit_u8(section_code); | 
| 65 // Emit the section to a temporary buffer: its full length isn't know yet. | 71 // Emit the section to a temporary buffer: its full length isn't know yet. | 
| 66 let section = new Binary; | 72 let section = new Binary; | 
| 67 content_generator(section); | 73 content_generator(section); | 
| 68 // Emit section length. | 74 // Emit section length. | 
| 69 this.emit_varint(section.length); | 75 this.emit_u32v(section.length); | 
| 70 // Copy the temporary buffer. | 76 // Copy the temporary buffer. | 
| 71 this.push(...section); | 77 this.push(...section); | 
| 72 } | 78 } | 
| 73 } | 79 } | 
| 74 | 80 | 
| 75 class WasmFunctionBuilder { | 81 class WasmFunctionBuilder { | 
| 76 constructor(name, type_index) { | 82 constructor(module, name, type_index) { | 
| 83 this.module = module; | |
| 77 this.name = name; | 84 this.name = name; | 
| 78 this.type_index = type_index; | 85 this.type_index = type_index; | 
| 79 this.exports = []; | |
| 80 } | 86 } | 
| 81 | 87 | 
| 82 exportAs(name) { | 88 exportAs(name) { | 
| 83 this.exports.push(name); | 89 this.module.exports.push({name: name, kind: kExternalFunction, index: this.i ndex}); | 
| 84 return this; | 90 return this; | 
| 85 } | 91 } | 
| 86 | 92 | 
| 87 exportFunc() { | 93 exportFunc() { | 
| 88 this.exports.push(this.name); | 94 this.exportAs(this.name); | 
| 89 return this; | 95 return this; | 
| 90 } | 96 } | 
| 91 | 97 | 
| 92 addBody(body) { | 98 addBody(body) { | 
| 93 this.body = body; | 99 this.body = body; | 
| 94 return this; | 100 return this; | 
| 95 } | 101 } | 
| 96 | 102 | 
| 97 addLocals(locals) { | 103 addLocals(locals) { | 
| 98 this.locals = locals; | 104 this.locals = locals; | 
| 99 return this; | 105 return this; | 
| 100 } | 106 } | 
| 101 } | 107 } | 
| 102 | 108 | 
| 109 class WasmGlobalBuilder { | |
| 110 constructor(module, type, mutable) { | |
| 111 this.module = module; | |
| 112 this.type = type; | |
| 113 this.mutable = mutable; | |
| 114 this.init = 0; | |
| 115 } | |
| 116 | |
| 117 exportAs(name) { | |
| 118 this.module.exports.push({name: name, kind: kExternalGlobal, index: this.ind ex}); | |
| 119 return this; | |
| 120 } | |
| 121 } | |
| 122 | |
| 103 class WasmModuleBuilder { | 123 class WasmModuleBuilder { | 
| 104 constructor() { | 124 constructor() { | 
| 105 this.types = []; | 125 this.types = []; | 
| 106 this.imports = []; | 126 this.imports = []; | 
| 127 this.exports = []; | |
| 107 this.globals = []; | 128 this.globals = []; | 
| 108 this.functions = []; | 129 this.functions = []; | 
| 109 this.exports = []; | |
| 110 this.table = []; | 130 this.table = []; | 
| 111 this.segments = []; | 131 this.segments = []; | 
| 112 this.explicit = []; | 132 this.explicit = []; | 
| 113 this.pad = null; | 133 this.pad = null; | 
| 134 this.num_imported_funcs = 0; | |
| 135 this.num_imported_globals = 0; | |
| 114 return this; | 136 return this; | 
| 115 } | 137 } | 
| 116 | 138 | 
| 117 addStart(start_index) { | 139 addStart(start_index) { | 
| 118 this.start_index = start_index; | 140 this.start_index = start_index; | 
| 119 } | 141 } | 
| 120 | 142 | 
| 121 addMemory(min, max, exp) { | 143 addMemory(min, max, exp) { | 
| 122 this.memory = {min: min, max: max, exp: exp}; | 144 this.memory = {min: min, max: max, exp: exp}; | 
| 123 return this; | 145 return this; | 
| 124 } | 146 } | 
| 125 | 147 | 
| 126 addPadFunctionTable(size) { | 148 addPadFunctionTable(size) { | 
| 127 this.pad = size; | 149 this.pad = size; | 
| 128 return this; | 150 return this; | 
| 129 } | 151 } | 
| 130 | 152 | 
| 131 addExplicitSection(bytes) { | 153 addExplicitSection(bytes) { | 
| 132 this.explicit.push(bytes); | 154 this.explicit.push(bytes); | 
| 133 return this; | 155 return this; | 
| 134 } | 156 } | 
| 135 | 157 | 
| 136 addType(type) { | 158 addType(type) { | 
| 137 // TODO: canonicalize types? | 159 // TODO: canonicalize types? | 
| 138 this.types.push(type); | 160 this.types.push(type); | 
| 139 return this.types.length - 1; | 161 return this.types.length - 1; | 
| 140 } | 162 } | 
| 141 | 163 | 
| 142 addGlobal(local_type) { | 164 addGlobal(local_type, mutable) { | 
| 143 this.globals.push(local_type); | 165 let glob = new WasmGlobalBuilder(this, local_type, mutable); | 
| 144 return this.globals.length - 1; | 166 glob.index = this.globals.length + this.num_imported_globals; | 
| 167 this.globals.push(glob); | |
| 168 return glob; | |
| 145 } | 169 } | 
| 146 | 170 | 
| 147 addFunction(name, type) { | 171 addFunction(name, type) { | 
| 148 let type_index = (typeof type) == "number" ? type : this.addType(type); | 172 let type_index = (typeof type) == "number" ? type : this.addType(type); | 
| 149 let func = new WasmFunctionBuilder(name, type_index); | 173 let func = new WasmFunctionBuilder(this, name, type_index); | 
| 150 func.index = this.functions.length + this.imports.length; | 174 func.index = this.functions.length + this.num_imported_funcs; | 
| 151 this.functions.push(func); | 175 this.functions.push(func); | 
| 152 return func; | 176 return func; | 
| 153 } | 177 } | 
| 154 | 178 | 
| 155 addImportWithModule(module, name, type) { | 179 addImportWithModule(module, name, type) { | 
| 156 let type_index = (typeof type) == "number" ? type : this.addType(type); | 180 let type_index = (typeof type) == "number" ? type : this.addType(type); | 
| 157 this.imports.push({module: module, name: name, type: type_index}); | 181 this.imports.push({module: module, name: name, kind: kExternalFunction, type : type_index}); | 
| 158 return this.imports.length - 1; | 182 return this.num_imported_funcs++; | 
| 159 } | 183 } | 
| 160 | 184 | 
| 161 addImport(name, type) { | 185 addImport(name, type) { | 
| 162 return this.addImportWithModule(name, undefined, type); | 186 return this.addImportWithModule(name, undefined, type); | 
| 163 } | 187 } | 
| 164 | 188 | 
| 189 addImportedGlobal(module, name, type) { | |
| 190 let o = {module: module, name: name, kind: kExternalGlobal, type: type, muta ble: false} | |
| 
Mircea Trofin
2016/10/05 16:21:09
80 chars
 | |
| 191 this.imports.push(o); | |
| 192 return this.num_imported_globals++; | |
| 193 } | |
| 194 | |
| 165 addDataSegment(addr, data, init) { | 195 addDataSegment(addr, data, init) { | 
| 166 this.segments.push({addr: addr, data: data, init: init}); | 196 this.segments.push({addr: addr, data: data, init: init}); | 
| 167 return this.segments.length - 1; | 197 return this.segments.length - 1; | 
| 168 } | 198 } | 
| 169 | 199 | 
| 170 appendToTable(array) { | 200 appendToTable(array) { | 
| 171 this.table.push(...array); | 201 this.table.push(...array); | 
| 172 return this; | 202 return this; | 
| 173 } | 203 } | 
| 174 | 204 | 
| 175 toArray(debug) { | 205 toArray(debug) { | 
| 176 let binary = new Binary; | 206 let binary = new Binary; | 
| 177 let wasm = this; | 207 let wasm = this; | 
| 178 | 208 | 
| 179 // Add header | 209 // Add header | 
| 180 binary.emit_header(); | 210 binary.emit_header(); | 
| 181 | 211 | 
| 182 // Add type section | 212 // Add type section | 
| 183 if (wasm.types.length > 0) { | 213 if (wasm.types.length > 0) { | 
| 184 if (debug) print("emitting types @ " + binary.length); | 214 if (debug) print("emitting types @ " + binary.length); | 
| 185 binary.emit_section(kTypeSectionCode, section => { | 215 binary.emit_section(kTypeSectionCode, section => { | 
| 186 section.emit_varint(wasm.types.length); | 216 section.emit_u32v(wasm.types.length); | 
| 187 for (let type of wasm.types) { | 217 for (let type of wasm.types) { | 
| 188 section.emit_u8(kWasmFunctionTypeForm); | 218 section.emit_u8(kWasmFunctionTypeForm); | 
| 189 section.emit_varint(type.params.length); | 219 section.emit_u32v(type.params.length); | 
| 190 for (let param of type.params) { | 220 for (let param of type.params) { | 
| 191 section.emit_u8(param); | 221 section.emit_u8(param); | 
| 192 } | 222 } | 
| 193 section.emit_varint(type.results.length); | 223 section.emit_u32v(type.results.length); | 
| 194 for (let result of type.results) { | 224 for (let result of type.results) { | 
| 195 section.emit_u8(result); | 225 section.emit_u8(result); | 
| 196 } | 226 } | 
| 197 } | 227 } | 
| 198 }); | 228 }); | 
| 199 } | 229 } | 
| 200 | 230 | 
| 201 // Add imports section | 231 // Add imports section | 
| 202 if (wasm.imports.length > 0) { | 232 if (wasm.imports.length > 0) { | 
| 203 if (debug) print("emitting imports @ " + binary.length); | 233 if (debug) print("emitting imports @ " + binary.length); | 
| 204 binary.emit_section(kImportSectionCode, section => { | 234 binary.emit_section(kImportSectionCode, section => { | 
| 205 section.emit_varint(wasm.imports.length); | 235 section.emit_u32v(wasm.imports.length); | 
| 206 for (let imp of wasm.imports) { | 236 for (let imp of wasm.imports) { | 
| 207 section.emit_string(imp.module); | 237 section.emit_string(imp.module); | 
| 208 section.emit_string(imp.name || ''); | 238 section.emit_string(imp.name || ''); | 
| 209 section.emit_u8(kExternalFunction); | 239 section.emit_u8(imp.kind); | 
| 210 section.emit_varint(imp.type); | 240 if (imp.kind == kExternalFunction) { | 
| 241 section.emit_u32v(imp.type); | |
| 242 } else if (imp.kind == kExternalGlobal) { | |
| 243 section.emit_u32v(imp.type); | |
| 244 section.emit_u8(imp.mutable); | |
| 245 } else { | |
| 246 throw new Error("unknown/unsupported import kind " + imp.kind); | |
| 247 } | |
| 211 } | 248 } | 
| 212 }); | 249 }); | 
| 213 } | 250 } | 
| 214 | 251 | 
| 215 // Add functions declarations | 252 // Add functions declarations | 
| 216 let has_names = false; | 253 let has_names = false; | 
| 217 let names = false; | 254 let names = false; | 
| 218 let exports = 0; | |
| 219 if (wasm.functions.length > 0) { | 255 if (wasm.functions.length > 0) { | 
| 220 if (debug) print("emitting function decls @ " + binary.length); | 256 if (debug) print("emitting function decls @ " + binary.length); | 
| 221 binary.emit_section(kFunctionSectionCode, section => { | 257 binary.emit_section(kFunctionSectionCode, section => { | 
| 222 section.emit_varint(wasm.functions.length); | 258 section.emit_u32v(wasm.functions.length); | 
| 223 for (let func of wasm.functions) { | 259 for (let func of wasm.functions) { | 
| 224 has_names = has_names || (func.name != undefined && | 260 has_names = has_names || (func.name != undefined && | 
| 225 func.name.length > 0); | 261 func.name.length > 0); | 
| 226 exports += func.exports.length; | 262 section.emit_u32v(func.type_index); | 
| 227 section.emit_varint(func.type_index); | |
| 228 } | 263 } | 
| 229 }); | 264 }); | 
| 230 } | 265 } | 
| 231 | 266 | 
| 232 // Add table. | 267 // Add table. | 
| 233 if (wasm.table.length > 0) { | 268 if (wasm.table.length > 0) { | 
| 234 if (debug) print("emitting table @ " + binary.length); | 269 if (debug) print("emitting table @ " + binary.length); | 
| 235 binary.emit_section(kTableSectionCode, section => { | 270 binary.emit_section(kTableSectionCode, section => { | 
| 236 section.emit_u8(1); // one table entry | 271 section.emit_u8(1); // one table entry | 
| 237 section.emit_u8(kWasmAnyFunctionTypeForm); | 272 section.emit_u8(kWasmAnyFunctionTypeForm); | 
| 238 section.emit_u8(1); | 273 section.emit_u8(1); | 
| 239 section.emit_varint(wasm.table.length); | 274 section.emit_u32v(wasm.table.length); | 
| 240 section.emit_varint(wasm.table.length); | 275 section.emit_u32v(wasm.table.length); | 
| 241 }); | 276 }); | 
| 242 } | 277 } | 
| 243 | 278 | 
| 244 // Add memory section | 279 // Add memory section | 
| 245 if (wasm.memory != undefined) { | 280 if (wasm.memory != undefined) { | 
| 246 if (debug) print("emitting memory @ " + binary.length); | 281 if (debug) print("emitting memory @ " + binary.length); | 
| 247 binary.emit_section(kMemorySectionCode, section => { | 282 binary.emit_section(kMemorySectionCode, section => { | 
| 248 section.emit_u8(1); // one memory entry | 283 section.emit_u8(1); // one memory entry | 
| 249 section.emit_varint(kResizableMaximumFlag); | 284 section.emit_u32v(kResizableMaximumFlag); | 
| 250 section.emit_varint(wasm.memory.min); | 285 section.emit_u32v(wasm.memory.min); | 
| 251 section.emit_varint(wasm.memory.max); | 286 section.emit_u32v(wasm.memory.max); | 
| 252 }); | 287 }); | 
| 253 } | 288 } | 
| 254 | 289 | 
| 255 // Add global section. | 290 // Add global section. | 
| 256 if (wasm.globals.length > 0) { | 291 if (wasm.globals.length > 0) { | 
| 257 if (debug) print ("emitting globals @ " + binary.length); | 292 if (debug) print ("emitting globals @ " + binary.length); | 
| 258 binary.emit_section(kGlobalSectionCode, section => { | 293 binary.emit_section(kGlobalSectionCode, section => { | 
| 259 section.emit_varint(wasm.globals.length); | 294 section.emit_u32v(wasm.globals.length); | 
| 260 for (let global_type of wasm.globals) { | 295 for (let global of wasm.globals) { | 
| 261 section.emit_u8(global_type); | 296 section.emit_u8(global.type); | 
| 262 section.emit_u8(true); // mutable | 297 section.emit_u8(global.mutable); | 
| 263 switch (global_type) { | 298 if ((typeof global.init_index) == "undefined") { | 
| 299 // Emit a constant initializer. | |
| 300 switch (global.type) { | |
| 264 case kAstI32: | 301 case kAstI32: | 
| 265 section.emit_u8(kExprI32Const); | 302 section.emit_u8(kExprI32Const); | 
| 266 section.emit_u8(0); | 303 section.emit_u32v(global.init); | 
| 267 break; | 304 break; | 
| 268 case kAstI64: | 305 case kAstI64: | 
| 269 section.emit_u8(kExprI64Const); | 306 section.emit_u8(kExprI64Const); | 
| 270 section.emit_u8(0); | 307 section.emit_u8(global.init); | 
| 271 break; | 308 break; | 
| 272 case kAstF32: | 309 case kAstF32: | 
| 273 section.emit_u8(kExprF32Const); | 310 section.emit_u8(kExprF32Const); | 
| 274 section.emit_u32(0); | 311 f32_view[0] = global.init; | 
| 312 section.emit_u8(byte_view[0]); | |
| 313 section.emit_u8(byte_view[1]); | |
| 314 section.emit_u8(byte_view[2]); | |
| 315 section.emit_u8(byte_view[3]); | |
| 275 break; | 316 break; | 
| 276 case kAstF64: | 317 case kAstF64: | 
| 277 section.emit_u8(kExprI32Const); | 318 section.emit_u8(kExprF64Const); | 
| 278 section.emit_u32(0); | 319 f64_view[0] = global.init; | 
| 279 section.emit_u32(0); | 320 section.emit_u8(byte_view[0]); | 
| 321 section.emit_u8(byte_view[1]); | |
| 322 section.emit_u8(byte_view[2]); | |
| 323 section.emit_u8(byte_view[3]); | |
| 324 section.emit_u8(byte_view[4]); | |
| 325 section.emit_u8(byte_view[5]); | |
| 326 section.emit_u8(byte_view[6]); | |
| 327 section.emit_u8(byte_view[7]); | |
| 280 break; | 328 break; | 
| 329 } | |
| 330 } else { | |
| 331 // Emit a global-index initializer. | |
| 332 section.emit_u8(kExprGetGlobal); | |
| 333 section.emit_u32v(global.init_index); | |
| 281 } | 334 } | 
| 282 section.emit_u8(kExprEnd); // end of init expression | 335 section.emit_u8(kExprEnd); // end of init expression | 
| 283 } | 336 } | 
| 284 }); | 337 }); | 
| 285 } | 338 } | 
| 286 | 339 | 
| 287 // Add export table. | 340 // Add export table. | 
| 288 var mem_export = (wasm.memory != undefined && wasm.memory.exp); | 341 var mem_export = (wasm.memory != undefined && wasm.memory.exp); | 
| 289 if (exports > 0 || mem_export) { | 342 var exports_count = wasm.exports.length + (mem_export ? 1 : 0); | 
| 343 if (exports_count > 0) { | |
| 290 if (debug) print("emitting exports @ " + binary.length); | 344 if (debug) print("emitting exports @ " + binary.length); | 
| 291 binary.emit_section(kExportSectionCode, section => { | 345 binary.emit_section(kExportSectionCode, section => { | 
| 292 section.emit_varint(exports + (mem_export ? 1 : 0)); | 346 section.emit_u32v(exports_count); | 
| 293 for (let func of wasm.functions) { | 347 for (let exp of wasm.exports) { | 
| 294 for (let exp of func.exports) { | 348 section.emit_string(exp.name); | 
| 295 section.emit_string(exp); | 349 section.emit_u8(exp.kind); | 
| 296 section.emit_u8(kExternalFunction); | 350 section.emit_u32v(exp.index); | 
| 297 section.emit_varint(func.index); | |
| 298 } | |
| 299 } | 351 } | 
| 300 if (mem_export) { | 352 if (mem_export) { | 
| 301 section.emit_string("memory"); | 353 section.emit_string("memory"); | 
| 302 section.emit_u8(kExternalMemory); | 354 section.emit_u8(kExternalMemory); | 
| 303 section.emit_u8(0); | 355 section.emit_u8(0); | 
| 304 } | 356 } | 
| 305 }); | 357 }); | 
| 306 } | 358 } | 
| 307 | 359 | 
| 308 // Add start function section. | 360 // Add start function section. | 
| 309 if (wasm.start_index != undefined) { | 361 if (wasm.start_index != undefined) { | 
| 310 if (debug) print("emitting start function @ " + binary.length); | 362 if (debug) print("emitting start function @ " + binary.length); | 
| 311 binary.emit_section(kStartSectionCode, section => { | 363 binary.emit_section(kStartSectionCode, section => { | 
| 312 section.emit_varint(wasm.start_index); | 364 section.emit_u32v(wasm.start_index); | 
| 313 }); | 365 }); | 
| 314 } | 366 } | 
| 315 | 367 | 
| 316 // Add table elements. | 368 // Add table elements. | 
| 317 if (wasm.table.length > 0) { | 369 if (wasm.table.length > 0) { | 
| 318 if (debug) print("emitting table @ " + binary.length); | 370 if (debug) print("emitting table @ " + binary.length); | 
| 319 binary.emit_section(kElementSectionCode, section => { | 371 binary.emit_section(kElementSectionCode, section => { | 
| 320 section.emit_u8(1); | 372 section.emit_u8(1); | 
| 321 section.emit_u8(0); // table index | 373 section.emit_u8(0); // table index | 
| 322 section.emit_u8(kExprI32Const); | 374 section.emit_u8(kExprI32Const); | 
| 323 section.emit_u8(0); | 375 section.emit_u8(0); | 
| 324 section.emit_u8(kExprEnd); | 376 section.emit_u8(kExprEnd); | 
| 325 section.emit_varint(wasm.table.length); | 377 section.emit_u32v(wasm.table.length); | 
| 326 for (let index of wasm.table) { | 378 for (let index of wasm.table) { | 
| 327 section.emit_varint(index); | 379 section.emit_u32v(index); | 
| 328 } | 380 } | 
| 329 }); | 381 }); | 
| 330 } | 382 } | 
| 331 | 383 | 
| 332 // Add function bodies. | 384 // Add function bodies. | 
| 333 if (wasm.functions.length > 0) { | 385 if (wasm.functions.length > 0) { | 
| 334 // emit function bodies | 386 // emit function bodies | 
| 335 if (debug) print("emitting code @ " + binary.length); | 387 if (debug) print("emitting code @ " + binary.length); | 
| 336 binary.emit_section(kCodeSectionCode, section => { | 388 binary.emit_section(kCodeSectionCode, section => { | 
| 337 section.emit_varint(wasm.functions.length); | 389 section.emit_u32v(wasm.functions.length); | 
| 338 for (let func of wasm.functions) { | 390 for (let func of wasm.functions) { | 
| 339 // Function body length will be patched later. | 391 // Function body length will be patched later. | 
| 340 let local_decls = []; | 392 let local_decls = []; | 
| 341 let l = func.locals; | 393 let l = func.locals; | 
| 342 if (l != undefined) { | 394 if (l != undefined) { | 
| 343 let local_decls_count = 0; | 395 let local_decls_count = 0; | 
| 344 if (l.i32_count > 0) { | 396 if (l.i32_count > 0) { | 
| 345 local_decls.push({count: l.i32_count, type: kAstI32}); | 397 local_decls.push({count: l.i32_count, type: kAstI32}); | 
| 346 } | 398 } | 
| 347 if (l.i64_count > 0) { | 399 if (l.i64_count > 0) { | 
| 348 local_decls.push({count: l.i64_count, type: kAstI64}); | 400 local_decls.push({count: l.i64_count, type: kAstI64}); | 
| 349 } | 401 } | 
| 350 if (l.f32_count > 0) { | 402 if (l.f32_count > 0) { | 
| 351 local_decls.push({count: l.f32_count, type: kAstF32}); | 403 local_decls.push({count: l.f32_count, type: kAstF32}); | 
| 352 } | 404 } | 
| 353 if (l.f64_count > 0) { | 405 if (l.f64_count > 0) { | 
| 354 local_decls.push({count: l.f64_count, type: kAstF64}); | 406 local_decls.push({count: l.f64_count, type: kAstF64}); | 
| 355 } | 407 } | 
| 356 } | 408 } | 
| 357 | 409 | 
| 358 let header = new Binary; | 410 let header = new Binary; | 
| 359 header.emit_varint(local_decls.length); | 411 header.emit_u32v(local_decls.length); | 
| 360 for (let decl of local_decls) { | 412 for (let decl of local_decls) { | 
| 361 header.emit_varint(decl.count); | 413 header.emit_u32v(decl.count); | 
| 362 header.emit_u8(decl.type); | 414 header.emit_u8(decl.type); | 
| 363 } | 415 } | 
| 364 | 416 | 
| 365 section.emit_varint(header.length + func.body.length); | 417 section.emit_u32v(header.length + func.body.length); | 
| 366 section.emit_bytes(header); | 418 section.emit_bytes(header); | 
| 367 section.emit_bytes(func.body); | 419 section.emit_bytes(func.body); | 
| 368 } | 420 } | 
| 369 }); | 421 }); | 
| 370 } | 422 } | 
| 371 | 423 | 
| 372 // Add data segments. | 424 // Add data segments. | 
| 373 if (wasm.segments.length > 0) { | 425 if (wasm.segments.length > 0) { | 
| 374 if (debug) print("emitting data segments @ " + binary.length); | 426 if (debug) print("emitting data segments @ " + binary.length); | 
| 375 binary.emit_section(kDataSectionCode, section => { | 427 binary.emit_section(kDataSectionCode, section => { | 
| 376 section.emit_varint(wasm.segments.length); | 428 section.emit_u32v(wasm.segments.length); | 
| 377 for (let seg of wasm.segments) { | 429 for (let seg of wasm.segments) { | 
| 378 section.emit_u8(0); // linear memory index 0 | 430 section.emit_u8(0); // linear memory index 0 | 
| 379 section.emit_u8(kExprI32Const); | 431 section.emit_u8(kExprI32Const); | 
| 380 section.emit_varint(seg.addr); | 432 section.emit_u32v(seg.addr); | 
| 381 section.emit_u8(kExprEnd); | 433 section.emit_u8(kExprEnd); | 
| 382 section.emit_varint(seg.data.length); | 434 section.emit_u32v(seg.data.length); | 
| 383 section.emit_bytes(seg.data); | 435 section.emit_bytes(seg.data); | 
| 384 } | 436 } | 
| 385 }); | 437 }); | 
| 386 } | 438 } | 
| 387 | 439 | 
| 388 // Add any explicitly added sections | 440 // Add any explicitly added sections | 
| 389 for (let exp of wasm.explicit) { | 441 for (let exp of wasm.explicit) { | 
| 390 if (debug) print("emitting explicit @ " + binary.length); | 442 if (debug) print("emitting explicit @ " + binary.length); | 
| 391 binary.emit_bytes(exp); | 443 binary.emit_bytes(exp); | 
| 392 } | 444 } | 
| 393 | 445 | 
| 394 // Add function names. | 446 // Add function names. | 
| 395 if (has_names) { | 447 if (has_names) { | 
| 396 if (debug) print("emitting names @ " + binary.length); | 448 if (debug) print("emitting names @ " + binary.length); | 
| 397 binary.emit_section(kUnknownSectionCode, section => { | 449 binary.emit_section(kUnknownSectionCode, section => { | 
| 398 section.emit_string("name"); | 450 section.emit_string("name"); | 
| 399 section.emit_varint(wasm.functions.length); | 451 section.emit_u32v(wasm.functions.length); | 
| 400 for (let func of wasm.functions) { | 452 for (let func of wasm.functions) { | 
| 401 var name = func.name == undefined ? "" : func.name; | 453 var name = func.name == undefined ? "" : func.name; | 
| 402 section.emit_string(name); | 454 section.emit_string(name); | 
| 403 section.emit_u8(0); // local names count == 0 | 455 section.emit_u8(0); // local names count == 0 | 
| 404 } | 456 } | 
| 405 }); | 457 }); | 
| 406 } | 458 } | 
| 407 | 459 | 
| 408 return binary; | 460 return binary; | 
| 409 } | 461 } | 
| 410 | 462 | 
| 411 toBuffer(debug) { | 463 toBuffer(debug) { | 
| 412 let bytes = this.toArray(debug); | 464 let bytes = this.toArray(debug); | 
| 413 let buffer = new ArrayBuffer(bytes.length); | 465 let buffer = new ArrayBuffer(bytes.length); | 
| 414 let view = new Uint8Array(buffer); | 466 let view = new Uint8Array(buffer); | 
| 415 for (let i = 0; i < bytes.length; i++) { | 467 for (let i = 0; i < bytes.length; i++) { | 
| 416 let val = bytes[i]; | 468 let val = bytes[i]; | 
| 417 if ((typeof val) == "string") val = val.charCodeAt(0); | 469 if ((typeof val) == "string") val = val.charCodeAt(0); | 
| 418 view[i] = val | 0; | 470 view[i] = val | 0; | 
| 419 } | 471 } | 
| 420 return buffer; | 472 return buffer; | 
| 421 } | 473 } | 
| 422 | 474 | 
| 423 instantiate(...args) { | 475 instantiate(...args) { | 
| 424 let module = new WebAssembly.Module(this.toBuffer()); | 476 let module = new WebAssembly.Module(this.toBuffer()); | 
| 425 let instance = new WebAssembly.Instance(module, ...args); | 477 let instance = new WebAssembly.Instance(module, ...args); | 
| 426 return instance; | 478 return instance; | 
| 427 } | 479 } | 
| 428 } | 480 } | 
| OLD | NEW |