Changeset 209123 in webkit
- Timestamp:
- Nov 29, 2016 11:22:17 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 40 edited
- 7 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r209121 r209123 1 2016-11-29 JF Bastien <jfbastien@apple.com> 2 3 WebAssembly JS API: improve Instance 4 https://bugs.webkit.org/show_bug.cgi?id=164757 5 6 Reviewed by Keith Miller. 7 8 An Instance's `exports` property wasn't populated with exports. 9 10 A follow-up patch will do imports. 11 12 A few things of note: 13 14 - LowLevelBinary: support 3-byte integers. 15 - LowLevelBinary: support proper UTF-8 2003 code points (instead of UTF-16). 16 17 * wasm/Builder.js: 18 * wasm/Builder_WebAssemblyBinary.js: wire up exports, stub other things out some more 19 (const.emitters.Export): 20 * wasm/LowLevelBinary.js: 21 (export.default.LowLevelBinary.prototype.uint24): add, used for UTF-8 22 (export.default.LowLevelBinary.prototype.string): support UTF-8 23 (export.default.LowLevelBinary.prototype.getUint24): add, used for UTF-8 24 (export.default.LowLevelBinary.prototype.getVaruint1): was missing 25 (export.default.LowLevelBinary.prototype.getString): support UTF-8 26 (export.default.LowLevelBinary): 27 * wasm/js-api/test_Instance.js: instance.exports.answer() // <-- this is where the magic of this entire patch is 28 (ExportedAnswerI32): 29 * wasm/js-api/test_basic_api.js: punt test to later 30 (const.c.in.constructorProperties.switch): 31 * wasm/self-test/test_BuilderWebAssembly.js: UTF-8 32 (CustomSection): 33 * wasm/self-test/test_LowLevelBinary_string.js: UTF-8 now works 34 * wasm/self-test/test_LowLevelBinary_uint16.js: was missing one value 35 * wasm/self-test/test_LowLevelBinary_uint24.js: Copied from JSTests/wasm/self-test/test_LowLevelBinary_uint8.js. 36 * wasm/self-test/test_LowLevelBinary_uint8.js: was missing one value 37 * wasm/self-test/test_LowLevelBinary_varuint1.js: Added. 38 * wasm/utilities.js: this `dump` thing was useful 39 (const._dump): 40 1 41 2016-11-29 Saam Barati <sbarati@apple.com> 2 42 -
trunk/JSTests/wasm/Builder.js
r208634 r209123 217 217 case "default_target": throw new Error(`Unimplemented: "${expect.name}" on "${op}"`); 218 218 case "relative_depth": throw new Error(`Unimplemented: "${expect.name}" on "${op}"`); 219 case "sig": throw new Error(`Unimplemented: "${expect.name}" on "${op}"`); 219 case "sig": 220 // FIXME this should be isValidBlockType https://bugs.webkit.org/show_bug.cgi?id=164724 221 assert.truthy(WASM.isValidValueType(imms[idx]), `Invalid block type on ${op}: "${imms[idx]}"`); 222 break; 220 223 case "target_count": throw new Error(`Unimplemented: "${expect.name}" on "${op}"`); 221 224 case "target_table": throw new Error(`Unimplemented: "${expect.name}" on "${op}"`); … … 356 359 }; 357 360 break; 361 358 362 case "Import": 359 363 this[section] = function() { … … 370 374 break; 371 375 376 case "Function": 377 this[section] = function() { 378 const s = this._addSection(section); 379 const exportBuilder = { 380 End: () => this 381 // FIXME: add ability to add this with whatever. 382 }; 383 return exportBuilder; 384 }; 385 break; 386 387 case "Table": 388 // FIXME Implement table https://bugs.webkit.org/show_bug.cgi?id=164135 389 this[section] = () => { throw new Error(`Unimplemented: section type "${section}"`); }; 390 break; 391 392 case "Memory": 393 this[section] = function() { 394 const s = this._addSection(section); 395 const exportBuilder = { 396 End: () => this, 397 InitialMaxPages: (initial, max) => { 398 s.data.push({ initial, max }); 399 return exportBuilder; 400 } 401 }; 402 return exportBuilder; 403 }; 404 break; 405 406 case "Global": 407 // FIXME implement global https://bugs.webkit.org/show_bug.cgi?id=164133 408 this[section] = () => { throw new Error(`Unimplemented: section type "${section}"`); }; 409 break; 410 372 411 case "Export": 373 412 this[section] = function() { … … 384 423 break; 385 424 386 case "Memory": 387 this[section] = function() { 388 const s = this._addSection(section); 389 const exportBuilder = { 390 End: () => this, 391 InitialMaxPages: (initial, max) => { 392 s.data.push({ initial, max }); 393 return exportBuilder; 394 } 395 }; 396 return exportBuilder; 397 } 398 break; 399 400 case "Function": 401 this[section] = function() { 402 const s = this._addSection(section); 403 const exportBuilder = { 404 End: () => this 405 // FIXME: add ability to add this with whatever. 406 } 407 return exportBuilder; 408 } 425 case "Start": 426 // FIXME implement start https://bugs.webkit.org/show_bug.cgi?id=161709 427 this[section] = () => { throw new Error(`Unimplemented: section type "${section}"`); }; 428 break; 429 430 case "Element": 431 // FIXME implement element https://bugs.webkit.org/show_bug.cgi?id=161709 432 this[section] = () => { throw new Error(`Unimplemented: section type "${section}"`); }; 409 433 break; 410 434 … … 454 478 break; 455 479 480 case "Data": 481 // FIXME implement data https://bugs.webkit.org/show_bug.cgi?id=161709 482 this[section] = () => { throw new Error(`Unimplemented: section type "${section}"`); }; 483 break; 484 456 485 default: 457 this[section] = () => { throw new Error(`Un implemented:section type "${section}"`); };486 this[section] = () => { throw new Error(`Unknown section type "${section}"`); }; 458 487 break; 459 488 } 460 489 } 490 461 491 this.Unknown = function(name) { 462 492 const s = this._addSection(name); -
trunk/JSTests/wasm/Builder_WebAssemblyBinary.js
r208627 r209123 83 83 84 84 Global: (section, bin) => { throw new Error(`Not yet implemented`); }, 85 Export: (section, bin) => { throw new Error(`Not yet implemented`); }, 85 Export: (section, bin) => { 86 put(bin, "varuint32", section.data.length); 87 for (const entry of section.data) { 88 put(bin, "string", entry.field); 89 put(bin, "uint8", WASM.externalKindValue[entry.kind]); 90 switch (entry.kind) { 91 default: throw new Error(`Implementation problem: unexpected kind ${entry.kind}`); 92 case "Function": put(bin, "varuint32", entry.index); break; 93 case "Table": throw new Error(`Not yet implemented`); 94 case "Memory": throw new Error(`Not yet implemented`); 95 case "Global": throw new Error(`Not yet implemented`); 96 } 97 } 98 }, 86 99 Start: (section, bin) => { throw new Error(`Not yet implemented`); }, 87 100 Element: (section, bin) => { throw new Error(`Not yet implemented`); }, -
trunk/JSTests/wasm/LowLevelBinary.js
r208634 r209123 24 24 */ 25 25 26 import * as assert from 'assert.js'; 26 27 import * as WASM from 'WASM.js'; 27 28 … … 105 106 this._push8(v >>> 8); 106 107 } 108 uint24(v) { 109 if ((v & 0xFFFFFF) >>> 0 !== v) 110 throw new RangeError(`Invalid uint24 ${v}`); 111 this._maybeGrow(3); 112 this._push8(v); 113 this._push8(v >>> 8); 114 this._push8(v >>> 16); 115 } 107 116 uint32(v) { 108 117 if ((v & 0xFFFFFFFF) >>> 0 !== v) … … 156 165 string(str) { 157 166 let patch = this.newPatchable("varuint32"); 158 for (const char of str) 159 patch.uint16(char.charCodeAt()); 167 for (const char of str) { 168 // Encode UTF-8 2003 code points. 169 const code = char.codePointAt(); 170 if (code <= 0x007F) { 171 const utf8 = code; 172 patch.uint8(utf8); 173 } else if (code <= 0x07FF) { 174 const utf8 = 0x80C0 | ((code & 0x7C0) >> 6) | ((code & 0x3F) << 8); 175 patch.uint16(utf8); 176 } else if (code <= 0xFFFF) { 177 const utf8 = 0x8080E0 | ((code & 0xF000) >> 12) | ((code & 0xFC0) << 2) | ((code & 0x3F) << 16); 178 patch.uint24(utf8); 179 } else if (code <= 0x10FFFF) { 180 const utf8 = (0x808080F0 | ((code & 0x1C0000) >> 18) | ((code & 0x3F000) >> 4) | ((code & 0xFC0) << 10) | ((code & 0x3F) << 24)) >>> 0; 181 patch.uint32(utf8); 182 } else 183 throw new Error(`Unexpectedly large UTF-8 character code point '${char}' 0x${code.toString(16)}`); 184 } 160 185 patch.apply(); 161 186 } … … 170 195 _getterRangeCheck(this, at, 2); 171 196 return this._buf[at] | (this._buf[at + 1] << 8); 197 } 198 getUint24(at) { 199 _getterRangeCheck(this, at, 3); 200 return this._buf[at] | (this._buf[at + 1] << 8) | (this._buf[at + 2] << 16); 172 201 } 173 202 getUint32(at) { … … 206 235 return { value: v, next: at }; 207 236 } 237 getVaruint1(at) { 238 const res = this.getVaruint32(at); 239 if (res.value !== 0 && res.value !== 1) throw new Error(`Expected a varuint1, got value ${res.value}`); 240 return res; 241 } 208 242 getVaruint7(at) { 209 243 const res = this.getVaruint32(at); … … 213 247 getString(at) { 214 248 const size = this.getVaruint32(at); 249 const last = size.next + size.value; 250 let i = size.next; 215 251 let str = ""; 216 for (let i = size.next; i !== size.next + size.value; i += 2) 217 str += String.fromCharCode(this.getUint16(i)); 252 while (i < last) { 253 // Decode UTF-8 2003 code points. 254 const peek = this.getUint8(i); 255 let code; 256 if ((peek & 0x80) === 0x0) { 257 const utf8 = this.getUint8(i); 258 assert.eq(utf8 & 0x80, 0x00); 259 i += 1; 260 code = utf8; 261 } else if ((peek & 0xE0) === 0xC0) { 262 const utf8 = this.getUint16(i); 263 assert.eq(utf8 & 0xC0E0, 0x80C0); 264 i += 2; 265 code = ((utf8 & 0x1F) << 6) | ((utf8 & 0x3F00) >> 8); 266 } else if ((peek & 0xF0) === 0xE0) { 267 const utf8 = this.getUint24(i); 268 assert.eq(utf8 & 0xC0C0F0, 0x8080E0); 269 i += 3; 270 code = ((utf8 & 0xF) << 12) | ((utf8 & 0x3F00) >> 2) | ((utf8 & 0x3F0000) >> 16); 271 } else if ((peek & 0xF8) === 0xF0) { 272 const utf8 = this.getUint32(i); 273 assert.eq((utf8 & 0xC0C0C0F8) | 0, 0x808080F0 | 0); 274 i += 4; 275 code = ((utf8 & 0x7) << 18) | ((utf8 & 0x3F00) << 4) | ((utf8 & 0x3F0000) >> 10) | ((utf8 & 0x3F000000) >> 24); 276 } else 277 throw new Error(`Unexpectedly large UTF-8 initial byte 0x${peek.toString(16)}`); 278 str += String.fromCodePoint(code); 279 } 280 if (i !== last) 281 throw new Error(`String decoding read up to ${i}, expected ${last}, UTF-8 decoding was too greedy`); 218 282 return str; 219 283 } -
trunk/JSTests/wasm/README.md
r207363 r209123 1 1 # `wasmjs`: JavaScript tooling for WebAssembly 2 2 3 `wasmjs` is a self-contained collection of JavaScript tools which can manipulate 4 WebAssembly. At its core is `wasm.json`, a JSON decription of the WebAssembly 5 format and other interesting facts about WebAssembly as used by the Webkit 6 project (such as the names of associated JavaScriptCore opcodes). 3 `wasmjs` is a self-contained collection of JavaScript tools which can create and 4 manipulate WebAssembly representations and binaries. At its core is `wasm.json`, 5 a JSON decription of the WebAssembly format and other interesting facts about 6 WebAssembly as used by the Webkit project (such as the names of associated 7 JavaScriptCore B3 opcodes). 7 8 8 9 `wasmjs` requires modern JavaScript features such as ES6 modules, which is … … 13 14 14 15 The current core API of `wasmjs` is the `Builder` API from `Builder.js`. It is 15 used to build WebAssembly modules. 16 used to build WebAssembly modules, and assemble them to valid `.wasm` binaries 17 (held in an `ArrayBuffer`). The `Builder` is a small DSL which looks similar to 18 the WebAssembly [binary format][]. Each section is declared through a property 19 on the `Builder` object, and each declaration returns a proxy object which has 20 properties specific to that section. Proxies are "popped" back by invoking their 21 `.End()` property. 22 23 The `Code` section has properties for each [WebAssembly opcode][]. Opcode which 24 create a scope can be nested using a lambda. 25 26 [binary format]: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#high-level-structure 27 [WebAssembly opcode]: https://github.com/WebAssembly/design/blob/master/Semantics.md 16 28 17 29 A simple example: … … 22 34 const builder = new Builder(); 23 35 24 // Construct the equivalent of: (module (func (nop) (nop)))36 // Construct the equivalent of: (module (func "answer" (i32.const 42) (return))) 25 37 builder 38 .setChecked(false) // FIXME remove once checking is better implemented. 39 // Declare a Type section, which the builder will auto-fill as functions are defined. 40 .Type().End() 41 // Declare a Function section, which the builder will auto-fill as functions are defined. 42 .Function().End() 43 .Export() 44 // Export the "answer" function (defined below) to JavaScript. 45 .Function("answer") 46 .End() 26 47 .Code() 27 .Function() 28 .Nop() 29 .Nop() 30 .End() 31 .End(); 48 // The "answer" function takes an i32 parameters, and returns an i32. 49 .Function("answer", { params: ["i32"], ret: "i32" }) 50 // Create a block returning an i32, whose body is the enclosed lambda. 51 .Block("i32", b => b 52 .GetLocal(0) // Parameters are in the same index space as locals. 53 .I32Const(0) // Generate an i32 constant. 54 .I32Eq() // A comparison, using the two values currently on the stack. 55 .If("i32") // Consume the comparison result, returning an i32. 56 .I32Const(42) 57 .Else() 58 .I32Const(1) 59 .End() 60 ) 61 .Return() // Return the top of the stack: the value returned by the block. 62 .End() // End the current function. 63 .End(); // End the Code section. 32 64 33 65 // Create an ArrayBuffer which is a valid WebAssembly `.wasm` file. 34 const binary = builder.WebAssembly(); 66 const bin = builder.WebAssembly().get(); 67 68 // Use the standard WebAssembly JavaScript API to compile the module, and instantiate it. 69 const module = new WebAssembly.Module(bin); 70 const instance = new WebAssembly.Instance(module); 71 72 // Invoke the compiled WebAssembly function. 73 const result0 = instance.exports.answer(0); 74 if (result0 !== 42) 75 throw new Error(`Expected 42, got ${result0}.`); 76 77 const result1 = instance.exports.answer(1); 78 if (result1 !== 1) 79 throw new Error(`Expected 1, got ${result1}.`); 35 80 ``` 36 37 Code such as the above can then be used with JavaScript's `WebAssembly` global38 object.39 81 40 82 41 83 # Testing 42 84 43 Tests can be executed using: 85 * `self-test` tests `wasmjs` itself. 86 * `js-api` tests the [WebAssembly JavaScript API](https://github.com/WebAssembly/design/blob/master/JS.md). 87 * `function-tests` tests the WebAssembly compiler's implementation. 88 89 All tests can be executed using: 44 90 45 91 ```bash … … 52 98 ./Tools/Scripts/run-javascriptcore-tests --release --filter wasm -arch x86_64 53 99 ``` 54 55 The `self-test` folder contains tests for `wasmjs` itself. Future additions will56 also test the JavaScript engine's WebAssembly implementation (both JavaScript57 API and usage of that API to compile and execute WebAssembly modules). -
trunk/JSTests/wasm/js-api/test_Instance.js
r207929 r209123 9 9 assert.instanceof(instance, WebAssembly.Instance); 10 10 })(); 11 12 (function ExportedAnswerI32() { 13 const builder = (new Builder()) 14 .Type().End() 15 .Function().End() 16 .Export() 17 .Function("answer") 18 .End() 19 .Code() 20 .Function("answer", { params: [], ret: "i32" }) 21 .I32Const(42) 22 .Return() 23 .End() 24 .End(); 25 const bin = builder.WebAssembly().get(); 26 const module = new WebAssembly.Module(bin); 27 const instance = new WebAssembly.Instance(module); 28 const result = instance.exports.answer(); 29 assert.isA(result, "number"); 30 assert.eq(result, 42); 31 })(); -
trunk/JSTests/wasm/js-api/test_basic_api.js
r208401 r209123 69 69 assert.isNotUndef(instance.exports); 70 70 checkOwnPropertyDescriptor(instance, "exports", { typeofvalue: "object", writable: true, configurable: true, enumerable: true }); 71 assert.isUndef(instance.exports.__proto__); 72 assert.eq(Reflect.isExtensible(instance.exports), false); 73 assert.eq(Symbol.iterator in instance.exports, true); 74 assert.eq(Symbol.toStringTag in instance.exports, true); 71 // FIXME these should pass, requires a module namespace object. https://bugs.webkit.org/show_bug.cgi?id=165121 72 // assert.isUndef(instance.exports.__proto__); 73 // assert.eq(Reflect.isExtensible(instance.exports), false); 74 // assert.eq(Symbol.iterator in instance.exports, true); 75 // assert.eq(Symbol.toStringTag in instance.exports, true); 75 76 break; 76 77 case "Memory": -
trunk/JSTests/wasm/self-test/test_BuilderWebAssembly.js
r208401 r209123 28 28 .WebAssembly(); 29 29 assert.eq(bin.hexdump().trim(), 30 ["00000000 00 61 73 6d 0c 00 00 00 00 0 f 0a 4f 00 48 00 48 |·asm·······O·H·H|",31 "00000010 00 41 00 49 00 de ad c0 fe |·A·I·····|"].join("\n"));30 ["00000000 00 61 73 6d 0c 00 00 00 00 0a 05 4f 48 48 41 49 |·asm·······OHHAI|", 31 "00000010 de ad c0 fe |···· |"].join("\n")); 32 32 })(); -
trunk/JSTests/wasm/self-test/test_LowLevelBinary_string.js
r207363 r209123 8 8 "焼きたて!! ジャぱん", 9 9 "(╯°□°)╯︵ ┻━┻", 10 "�", 11 // Should we use code points instead of UTF-16? 12 // The following doesn't work: "👨❤️💋👨", 10 "$¢€𐍈�", 11 "👨❤️💋👨", 13 12 ]; 14 13 -
trunk/JSTests/wasm/self-test/test_LowLevelBinary_uint16.js
r207363 r209123 2 2 3 3 let values = []; 4 for (let i = 0; i !== 0xFFFF; ++i) values.push(i);4 for (let i = 0; i <= 0xFFFF; ++i) values.push(i); 5 5 6 6 for (const i of values) { -
trunk/JSTests/wasm/self-test/test_LowLevelBinary_uint24.js
r209122 r209123 2 2 3 3 let values = []; 4 for (let i = 0; i !== 0xFF; ++i) values.push(i); 4 for (let i = 0; i <= 0xFFFF; ++i) values.push(i); 5 for (let i = 0xFFFFFF - 0xFFFF; i <= 0xFFFFFF; ++i) values.push(i); 5 6 6 7 for (const i of values) { 7 8 let b = new LowLevelBinary(); 8 b.uint 8(i);9 const v = b.getUint 8(0);9 b.uint24(i); 10 const v = b.getUint24(0); 10 11 if (v !== i) 11 12 throw new Error(`Wrote "${i}" and read back "${v}"`); -
trunk/JSTests/wasm/self-test/test_LowLevelBinary_uint8.js
r207363 r209123 2 2 3 3 let values = []; 4 for (let i = 0; i !== 0xFF; ++i) values.push(i);4 for (let i = 0; i <= 0xFF; ++i) values.push(i); 5 5 6 6 for (const i of values) { -
trunk/JSTests/wasm/test.sh
r207363 r209123 9 9 xargs -n1 -t -I{} "$JSSHELL" -m {} 10 10 11 "$JSSHELL" -m generate-wasmops-header.js > /dev/null12 13 11 echo "All tests passed" -
trunk/JSTests/wasm/utilities.js
r207572 r209123 67 67 } 68 68 69 const _dump = (what, name, pad = ' ') => { 70 const value = v => { 71 try { return `"${v}"`; } 72 catch (e) { return `Error: "${e.message}"`; } 73 }; 74 let s = `${pad}${name} ${typeof what}: ${value(what)}`; 75 for (let p in what) { 76 s += `\n${pad}${pad}${p}: ${value(what[p])} ${typeof v}`; 77 s += '\n' + _dump(what[p], p, pad + pad); 78 } 79 return s; 80 }; 81 69 82 // Use underscore names to avoid clashing with builtin names. 70 export { _eval as eval, _read as read, _load as load, _json as json, _global as global }; 83 export { 84 _dump as dump, 85 _eval as eval, 86 _read as read, 87 _load as load, 88 _json as json, 89 _global as global 90 }; -
trunk/Source/JavaScriptCore/CMakeLists.txt
r208953 r209123 645 645 profiler/ProfilerUID.cpp 646 646 647 runtime/AbstractModuleRecord.cpp 647 648 runtime/ArgList.cpp 648 649 runtime/ArrayBuffer.cpp … … 913 914 wasm/js/WebAssemblyCompileErrorConstructor.cpp 914 915 wasm/js/WebAssemblyCompileErrorPrototype.cpp 916 wasm/js/WebAssemblyFunction.cpp 917 wasm/js/WebAssemblyFunctionCell.cpp 915 918 wasm/js/WebAssemblyInstanceConstructor.cpp 916 919 wasm/js/WebAssemblyInstancePrototype.cpp … … 919 922 wasm/js/WebAssemblyModuleConstructor.cpp 920 923 wasm/js/WebAssemblyModulePrototype.cpp 924 wasm/js/WebAssemblyModuleRecord.cpp 921 925 wasm/js/WebAssemblyPrototype.cpp 922 926 wasm/js/WebAssemblyRuntimeErrorConstructor.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r209121 r209123 1 2016-11-29 JF Bastien <jfbastien@apple.com> 2 3 WebAssembly JS API: improve Instance 4 https://bugs.webkit.org/show_bug.cgi?id=164757 5 6 Reviewed by Keith Miller. 7 8 An Instance's `exports` property wasn't populated with exports. 9 10 According to the spec [0], `exports` should present itself as a WebAssembly 11 Module Record. In order to do this we need to split JSModuleRecord into 12 AbstractModuleRecord (without the `link` and `evaluate` functions), and 13 JSModuleRecord (which implements link and evaluate). We can then have a separate 14 WebAssemblyModuleRecord which shares most of the implementation. 15 16 `exports` then maps function names to WebAssemblyFunction and 17 WebAssemblyFunctionCell, which call into the B3-generated WebAssembly code. 18 19 A follow-up patch will do imports. 20 21 A few things of note: 22 23 - Use Identifier instead of String. They get uniqued, we need them for the JSModuleNamespaceObject. This is safe because JSWebAssemblyModule creation is on the main thread. 24 - JSWebAssemblyInstance needs to refer to the JSWebAssemblyModule used to create it, because the module owns the code, identifiers, etc. The world would be very sad if it got GC'd. 25 - Instance.exports shouldn't use putWithoutTransition because it affects all Structures, whereas here each instance needs its own exports. 26 - Expose the compiled functions, and pipe them to the InstanceConstructor. Start moving things around to split JSModuleRecord out into JS and WebAssembly parts. 27 28 [0]: https://github.com/WebAssembly/design/blob/master/JS.md#webassemblyinstance-constructor 29 30 * CMakeLists.txt: 31 * JavaScriptCore.xcodeproj/project.pbxproj: 32 * runtime/AbstractModuleRecord.cpp: Copied from Source/JavaScriptCore/runtime/JSModuleRecord.cpp, which I split in two 33 (JSC::AbstractModuleRecord::AbstractModuleRecord): 34 (JSC::AbstractModuleRecord::destroy): 35 (JSC::AbstractModuleRecord::finishCreation): 36 (JSC::AbstractModuleRecord::visitChildren): 37 (JSC::AbstractModuleRecord::appendRequestedModule): 38 (JSC::AbstractModuleRecord::addStarExportEntry): 39 (JSC::AbstractModuleRecord::addImportEntry): 40 (JSC::AbstractModuleRecord::addExportEntry): 41 (JSC::identifierToJSValue): 42 (JSC::AbstractModuleRecord::hostResolveImportedModule): 43 (JSC::AbstractModuleRecord::ResolveQuery::ResolveQuery): 44 (JSC::AbstractModuleRecord::ResolveQuery::isEmptyValue): 45 (JSC::AbstractModuleRecord::ResolveQuery::isDeletedValue): 46 (JSC::AbstractModuleRecord::ResolveQuery::Hash::hash): 47 (JSC::AbstractModuleRecord::ResolveQuery::Hash::equal): 48 (JSC::AbstractModuleRecord::cacheResolution): 49 (JSC::getExportedNames): 50 (JSC::AbstractModuleRecord::getModuleNamespace): 51 (JSC::printableName): 52 (JSC::AbstractModuleRecord::dump): 53 * runtime/AbstractModuleRecord.h: Copied from Source/JavaScriptCore/runtime/JSModuleRecord.h. 54 (JSC::AbstractModuleRecord::ImportEntry::isNamespace): 55 (JSC::AbstractModuleRecord::sourceCode): 56 (JSC::AbstractModuleRecord::moduleKey): 57 (JSC::AbstractModuleRecord::requestedModules): 58 (JSC::AbstractModuleRecord::exportEntries): 59 (JSC::AbstractModuleRecord::importEntries): 60 (JSC::AbstractModuleRecord::starExportEntries): 61 (JSC::AbstractModuleRecord::declaredVariables): 62 (JSC::AbstractModuleRecord::lexicalVariables): 63 (JSC::AbstractModuleRecord::moduleEnvironment): 64 * runtime/JSGlobalObject.cpp: 65 (JSC::JSGlobalObject::init): 66 (JSC::JSGlobalObject::visitChildren): 67 * runtime/JSGlobalObject.h: 68 (JSC::JSGlobalObject::webAssemblyModuleRecordStructure): 69 (JSC::JSGlobalObject::webAssemblyFunctionStructure): 70 * runtime/JSModuleEnvironment.cpp: 71 (JSC::JSModuleEnvironment::create): 72 (JSC::JSModuleEnvironment::finishCreation): 73 (JSC::JSModuleEnvironment::getOwnPropertySlot): 74 (JSC::JSModuleEnvironment::getOwnNonIndexPropertyNames): 75 (JSC::JSModuleEnvironment::put): 76 (JSC::JSModuleEnvironment::deleteProperty): 77 * runtime/JSModuleEnvironment.h: 78 (JSC::JSModuleEnvironment::create): 79 (JSC::JSModuleEnvironment::offsetOfModuleRecord): 80 (JSC::JSModuleEnvironment::allocationSize): 81 (JSC::JSModuleEnvironment::moduleRecord): 82 (JSC::JSModuleEnvironment::moduleRecordSlot): 83 * runtime/JSModuleNamespaceObject.cpp: 84 (JSC::JSModuleNamespaceObject::finishCreation): 85 (JSC::JSModuleNamespaceObject::getOwnPropertySlot): 86 * runtime/JSModuleNamespaceObject.h: 87 (JSC::JSModuleNamespaceObject::create): 88 (JSC::JSModuleNamespaceObject::moduleRecord): 89 * runtime/JSModuleRecord.cpp: 90 (JSC::JSModuleRecord::createStructure): 91 (JSC::JSModuleRecord::create): 92 (JSC::JSModuleRecord::JSModuleRecord): 93 (JSC::JSModuleRecord::destroy): 94 (JSC::JSModuleRecord::finishCreation): 95 (JSC::JSModuleRecord::visitChildren): 96 (JSC::JSModuleRecord::instantiateDeclarations): 97 * runtime/JSModuleRecord.h: 98 * runtime/JSScope.cpp: 99 (JSC::abstractAccess): 100 (JSC::JSScope::collectClosureVariablesUnderTDZ): 101 * runtime/VM.cpp: 102 (JSC::VM::VM): 103 * runtime/VM.h: 104 * wasm/JSWebAssembly.h: 105 * wasm/WasmFormat.h: use Identifier instead of String 106 * wasm/WasmModuleParser.cpp: 107 (JSC::Wasm::ModuleParser::parse): 108 (JSC::Wasm::ModuleParser::parseType): 109 (JSC::Wasm::ModuleParser::parseImport): fix off-by-one 110 (JSC::Wasm::ModuleParser::parseFunction): 111 (JSC::Wasm::ModuleParser::parseExport): 112 * wasm/WasmModuleParser.h: 113 (JSC::Wasm::ModuleParser::ModuleParser): 114 * wasm/WasmPlan.cpp: 115 (JSC::Wasm::Plan::run): 116 * wasm/js/JSWebAssemblyInstance.cpp: 117 (JSC::JSWebAssemblyInstance::create): 118 (JSC::JSWebAssemblyInstance::finishCreation): 119 (JSC::JSWebAssemblyInstance::visitChildren): 120 * wasm/js/JSWebAssemblyInstance.h: 121 (JSC::JSWebAssemblyInstance::module): 122 * wasm/js/JSWebAssemblyModule.cpp: 123 (JSC::JSWebAssemblyModule::create): 124 (JSC::JSWebAssemblyModule::finishCreation): 125 (JSC::JSWebAssemblyModule::visitChildren): 126 * wasm/js/JSWebAssemblyModule.h: 127 (JSC::JSWebAssemblyModule::moduleInformation): 128 (JSC::JSWebAssemblyModule::compiledFunctions): 129 (JSC::JSWebAssemblyModule::exportSymbolTable): 130 * wasm/js/WebAssemblyFunction.cpp: Added. 131 (JSC::callWebAssemblyFunction): 132 (JSC::WebAssemblyFunction::create): 133 (JSC::WebAssemblyFunction::createStructure): 134 (JSC::WebAssemblyFunction::WebAssemblyFunction): 135 (JSC::WebAssemblyFunction::visitChildren): 136 (JSC::WebAssemblyFunction::finishCreation): 137 * wasm/js/WebAssemblyFunction.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h. 138 (JSC::CallableWebAssemblyFunction::CallableWebAssemblyFunction): 139 (JSC::WebAssemblyFunction::webAssemblyFunctionCell): 140 * wasm/js/WebAssemblyFunctionCell.cpp: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h. 141 (JSC::WebAssemblyFunctionCell::create): 142 (JSC::WebAssemblyFunctionCell::WebAssemblyFunctionCell): 143 (JSC::WebAssemblyFunctionCell::destroy): 144 (JSC::WebAssemblyFunctionCell::createStructure): 145 * wasm/js/WebAssemblyFunctionCell.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h. 146 (JSC::WebAssemblyFunctionCell::function): 147 * wasm/js/WebAssemblyInstanceConstructor.cpp: 148 (JSC::constructJSWebAssemblyInstance): 149 * wasm/js/WebAssemblyModuleConstructor.cpp: 150 (JSC::constructJSWebAssemblyModule): 151 * wasm/js/WebAssemblyModuleRecord.cpp: Added. 152 (JSC::WebAssemblyModuleRecord::createStructure): 153 (JSC::WebAssemblyModuleRecord::create): 154 (JSC::WebAssemblyModuleRecord::WebAssemblyModuleRecord): 155 (JSC::WebAssemblyModuleRecord::destroy): 156 (JSC::WebAssemblyModuleRecord::finishCreation): 157 (JSC::WebAssemblyModuleRecord::visitChildren): 158 (JSC::WebAssemblyModuleRecord::link): 159 (JSC::WebAssemblyModuleRecord::evaluate): 160 * wasm/js/WebAssemblyModuleRecord.h: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h. 161 1 162 2016-11-29 Saam Barati <sbarati@apple.com> 2 163 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r208953 r209123 2000 2000 AD2FCC311DB83D4900B3E736 /* JSWebAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = AD2FCC2F1DB839F700B3E736 /* JSWebAssembly.h */; }; 2001 2001 AD2FCC331DC4045400B3E736 /* WasmFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD2FCC321DC4045300B3E736 /* WasmFormat.cpp */; }; 2002 AD4937C31DDBE6140077C807 /* AbstractModuleRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD4937C11DDBE60A0077C807 /* AbstractModuleRecord.cpp */; }; 2003 AD4937C41DDBE6140077C807 /* AbstractModuleRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = AD4937C21DDBE60A0077C807 /* AbstractModuleRecord.h */; settings = {ATTRIBUTES = (Private, ); }; }; 2004 AD4937C71DDD0AAE0077C807 /* WebAssemblyModuleRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD4937C51DDCDCF00077C807 /* WebAssemblyModuleRecord.cpp */; }; 2005 AD4937C81DDD0AAE0077C807 /* WebAssemblyModuleRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = AD4937C61DDCDCF00077C807 /* WebAssemblyModuleRecord.h */; }; 2006 AD4937D11DDD27DE0077C807 /* WebAssemblyFunctionCell.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD4937CD1DDD27D90077C807 /* WebAssemblyFunctionCell.cpp */; }; 2007 AD4937D21DDD27DE0077C807 /* WebAssemblyFunctionCell.h in Headers */ = {isa = PBXBuildFile; fileRef = AD4937CE1DDD27D90077C807 /* WebAssemblyFunctionCell.h */; }; 2008 AD4937D31DDD27DE0077C807 /* WebAssemblyFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD4937C91DDD27340077C807 /* WebAssemblyFunction.cpp */; }; 2009 AD4937D41DDD27DE0077C807 /* WebAssemblyFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = AD4937CA1DDD27340077C807 /* WebAssemblyFunction.h */; }; 2002 2010 AD86A93E1AA4D88D002FE77F /* WeakGCMapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; 2003 2011 ADDB1F6318D77DBE009B58A8 /* OpaqueRootSet.h in Headers */ = {isa = PBXBuildFile; fileRef = ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 4462 4470 AD2FCC2F1DB839F700B3E736 /* JSWebAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebAssembly.h; sourceTree = "<group>"; }; 4463 4471 AD2FCC321DC4045300B3E736 /* WasmFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmFormat.cpp; sourceTree = "<group>"; }; 4472 AD4937C11DDBE60A0077C807 /* AbstractModuleRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractModuleRecord.cpp; sourceTree = "<group>"; }; 4473 AD4937C21DDBE60A0077C807 /* AbstractModuleRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractModuleRecord.h; sourceTree = "<group>"; }; 4474 AD4937C51DDCDCF00077C807 /* WebAssemblyModuleRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyModuleRecord.cpp; path = js/WebAssemblyModuleRecord.cpp; sourceTree = "<group>"; }; 4475 AD4937C61DDCDCF00077C807 /* WebAssemblyModuleRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyModuleRecord.h; path = js/WebAssemblyModuleRecord.h; sourceTree = "<group>"; }; 4476 AD4937C91DDD27340077C807 /* WebAssemblyFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyFunction.cpp; path = js/WebAssemblyFunction.cpp; sourceTree = "<group>"; }; 4477 AD4937CA1DDD27340077C807 /* WebAssemblyFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyFunction.h; path = js/WebAssemblyFunction.h; sourceTree = "<group>"; }; 4478 AD4937CD1DDD27D90077C807 /* WebAssemblyFunctionCell.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyFunctionCell.cpp; path = js/WebAssemblyFunctionCell.cpp; sourceTree = "<group>"; }; 4479 AD4937CE1DDD27D90077C807 /* WebAssemblyFunctionCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyFunctionCell.h; path = js/WebAssemblyFunctionCell.h; sourceTree = "<group>"; }; 4464 4480 AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakGCMapInlines.h; sourceTree = "<group>"; }; 4465 4481 ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpaqueRootSet.h; sourceTree = "<group>"; }; … … 6055 6071 isa = PBXGroup; 6056 6072 children = ( 6073 AD4937C11DDBE60A0077C807 /* AbstractModuleRecord.cpp */, 6074 AD4937C21DDBE60A0077C807 /* AbstractModuleRecord.h */, 6057 6075 BCF605110E203EF800B9A64D /* ArgList.cpp */, 6058 6076 BCF605120E203EF800B9A64D /* ArgList.h */, … … 7549 7567 isa = PBXGroup; 7550 7568 children = ( 7569 AD4937CD1DDD27D90077C807 /* WebAssemblyFunctionCell.cpp */, 7570 AD4937CE1DDD27D90077C807 /* WebAssemblyFunctionCell.h */, 7571 AD4937C91DDD27340077C807 /* WebAssemblyFunction.cpp */, 7572 AD4937CA1DDD27340077C807 /* WebAssemblyFunction.h */, 7573 AD4937C51DDCDCF00077C807 /* WebAssemblyModuleRecord.cpp */, 7574 AD4937C61DDCDCF00077C807 /* WebAssemblyModuleRecord.h */, 7551 7575 AD2FCC261DB838C400B3E736 /* WebAssemblyPrototype.cpp */, 7552 7576 AD2FCC271DB838C400B3E736 /* WebAssemblyPrototype.h */, … … 7983 8007 53529A4C1C457B75000B49C6 /* APIUtils.h in Headers */, 7984 8008 0FEA0A32170D40BF00BB722C /* DFGCommonData.h in Headers */, 8009 AD4937D21DDD27DE0077C807 /* WebAssemblyFunctionCell.h in Headers */, 7985 8010 0F725CB01C506D3B00AD943A /* B3FoldPathConstants.h in Headers */, 7986 8011 0F38B01817CFE75500B144D3 /* DFGCompilationKey.h in Headers */, … … 8009 8034 A7986D5717A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h in Headers */, 8010 8035 0F8F14341ADF090100ED792C /* DFGEpoch.h in Headers */, 8036 AD4937C81DDD0AAE0077C807 /* WebAssemblyModuleRecord.h in Headers */, 8011 8037 0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */, 8012 8038 A78A9775179738B8009DF744 /* DFGFailedFinalizer.h in Headers */, … … 8141 8167 DCFDFBDA1D1F5D9E00FE3D72 /* B3TypeMap.h in Headers */, 8142 8168 0F3B3A2C15475002003ED0FF /* DFGValidate.h in Headers */, 8169 AD4937C41DDBE6140077C807 /* AbstractModuleRecord.h in Headers */, 8143 8170 0F2BDC481522802900CD8910 /* DFGValueSource.h in Headers */, 8144 8171 0F0123331944EA1B00843A0C /* DFGValueStrength.h in Headers */, … … 8425 8452 0FC712E317CD8793008CC93C /* JITToDFGDeferredCompilationCallback.h in Headers */, 8426 8453 AD2FCBE31DB58DAD00B3E736 /* JSWebAssemblyCompileError.h in Headers */, 8454 AD4937D41DDD27DE0077C807 /* WebAssemblyFunction.h in Headers */, 8427 8455 840480131021A1D9008E7F01 /* JSAPIValueWrapper.h in Headers */, 8428 8456 C2CF39C216E15A8100DD69BE /* JSAPIWrapperObject.h in Headers */, … … 9697 9725 0FDF67D31D9C6D2A001B9825 /* B3Kind.cpp in Sources */, 9698 9726 0F8F2B99172F04FF007DBDA5 /* DFGDesiredIdentifiers.cpp in Sources */, 9727 AD4937C31DDBE6140077C807 /* AbstractModuleRecord.cpp in Sources */, 9699 9728 C2C0F7CD17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp in Sources */, 9700 9729 0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */, … … 9954 9983 1429D7D40ED2128200B89619 /* Interpreter.cpp in Sources */, 9955 9984 0FE34C191C4B39AE0003A512 /* AirLogRegisterPressure.cpp in Sources */, 9985 AD4937D31DDD27DE0077C807 /* WebAssemblyFunction.cpp in Sources */, 9956 9986 A1B9E2391B4E0D6700BC7FED /* IntlCollator.cpp in Sources */, 9957 9987 A1B9E23B1B4E0D6700BC7FED /* IntlCollatorConstructor.cpp in Sources */, … … 10102 10132 146AAB380B66A94400E55F16 /* JSStringRefCF.cpp in Sources */, 10103 10133 0F919D0C157EE09F004A4E7D /* JSSymbolTableObject.cpp in Sources */, 10134 AD4937D11DDD27DE0077C807 /* WebAssemblyFunctionCell.cpp in Sources */, 10104 10135 70ECA6051AFDBEA200449739 /* JSTemplateRegistryKey.cpp in Sources */, 10105 10136 0F2B66FA17B6B5AB00A7AE3F /* JSTypedArrayConstructors.cpp in Sources */, … … 10370 10401 86704B8412DBA33700A9FE7B /* YarrInterpreter.cpp in Sources */, 10371 10402 86704B8612DBA33700A9FE7B /* YarrJIT.cpp in Sources */, 10403 AD4937C71DDD0AAE0077C807 /* WebAssemblyModuleRecord.cpp in Sources */, 10372 10404 86704B8912DBA33700A9FE7B /* YarrPattern.cpp in Sources */, 10373 10405 86704B4212DB8A8100A9FE7B /* YarrSyntaxChecker.cpp in Sources */, -
trunk/Source/JavaScriptCore/runtime/AbstractModuleRecord.cpp
r209122 r209123 25 25 26 26 #include "config.h" 27 #include " JSModuleRecord.h"27 #include "AbstractModuleRecord.h" 28 28 29 29 #include "Error.h" … … 37 37 namespace JSC { 38 38 39 const ClassInfo JSModuleRecord::s_info = { "ModuleRecord", &Base::s_info, 0, CREATE_METHOD_TABLE(JSModuleRecord) }; 40 41 void JSModuleRecord::destroy(JSCell* cell) 42 { 43 JSModuleRecord* thisObject = jsCast<JSModuleRecord*>(cell); 44 thisObject->JSModuleRecord::~JSModuleRecord(); 45 } 46 47 void JSModuleRecord::finishCreation(ExecState* exec, VM& vm) 39 const ClassInfo AbstractModuleRecord::s_info = { "AbstractModuleRecord", &Base::s_info, 0, CREATE_METHOD_TABLE(AbstractModuleRecord) }; 40 41 AbstractModuleRecord::AbstractModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables) 42 : Base(vm, structure) 43 , m_moduleKey(moduleKey) 44 , m_sourceCode(sourceCode) 45 , m_declaredVariables(declaredVariables) 46 , m_lexicalVariables(lexicalVariables) 47 { 48 } 49 50 void AbstractModuleRecord::destroy(JSCell* cell) 51 { 52 AbstractModuleRecord* thisObject = jsCast<AbstractModuleRecord*>(cell); 53 thisObject->AbstractModuleRecord::~AbstractModuleRecord(); 54 } 55 56 void AbstractModuleRecord::finishCreation(ExecState* exec, VM& vm) 48 57 { 49 58 Base::finishCreation(vm); … … 59 68 } 60 69 61 void JSModuleRecord::visitChildren(JSCell* cell, SlotVisitor& visitor)62 { 63 JSModuleRecord* thisObject = jsCast<JSModuleRecord*>(cell);70 void AbstractModuleRecord::visitChildren(JSCell* cell, SlotVisitor& visitor) 71 { 72 AbstractModuleRecord* thisObject = jsCast<AbstractModuleRecord*>(cell); 64 73 Base::visitChildren(thisObject, visitor); 65 74 visitor.append(&thisObject->m_moduleEnvironment); 66 75 visitor.append(&thisObject->m_moduleNamespaceObject); 67 visitor.append(&thisObject->m_moduleProgramExecutable);68 76 visitor.append(&thisObject->m_dependenciesMap); 69 77 } 70 78 71 void JSModuleRecord::appendRequestedModule(const Identifier& moduleName)79 void AbstractModuleRecord::appendRequestedModule(const Identifier& moduleName) 72 80 { 73 81 m_requestedModules.add(moduleName.impl()); 74 82 } 75 83 76 void JSModuleRecord::addStarExportEntry(const Identifier& moduleName)84 void AbstractModuleRecord::addStarExportEntry(const Identifier& moduleName) 77 85 { 78 86 m_starExportEntries.add(moduleName.impl()); 79 87 } 80 88 81 void JSModuleRecord::addImportEntry(const ImportEntry& entry)89 void AbstractModuleRecord::addImportEntry(const ImportEntry& entry) 82 90 { 83 91 bool isNewEntry = m_importEntries.add(entry.localName.impl(), entry).isNewEntry; … … 85 93 } 86 94 87 void JSModuleRecord::addExportEntry(const ExportEntry& entry)95 void AbstractModuleRecord::addExportEntry(const ExportEntry& entry) 88 96 { 89 97 bool isNewEntry = m_exportEntries.add(entry.exportName.impl(), entry).isNewEntry; … … 91 99 } 92 100 93 auto JSModuleRecord::tryGetImportEntry(UniquedStringImpl* localName) -> std::optional<ImportEntry>101 auto AbstractModuleRecord::tryGetImportEntry(UniquedStringImpl* localName) -> std::optional<ImportEntry> 94 102 { 95 103 const auto iterator = m_importEntries.find(localName); … … 99 107 } 100 108 101 auto JSModuleRecord::tryGetExportEntry(UniquedStringImpl* exportName) -> std::optional<ExportEntry>109 auto AbstractModuleRecord::tryGetExportEntry(UniquedStringImpl* exportName) -> std::optional<ExportEntry> 102 110 { 103 111 const auto iterator = m_exportEntries.find(exportName); … … 107 115 } 108 116 109 auto JSModuleRecord::ExportEntry::createLocal(const Identifier& exportName, const Identifier& localName) -> ExportEntry117 auto AbstractModuleRecord::ExportEntry::createLocal(const Identifier& exportName, const Identifier& localName) -> ExportEntry 110 118 { 111 119 return ExportEntry { Type::Local, exportName, Identifier(), Identifier(), localName }; 112 120 } 113 121 114 auto JSModuleRecord::ExportEntry::createIndirect(const Identifier& exportName, const Identifier& importName, const Identifier& moduleName) -> ExportEntry122 auto AbstractModuleRecord::ExportEntry::createIndirect(const Identifier& exportName, const Identifier& importName, const Identifier& moduleName) -> ExportEntry 115 123 { 116 124 return ExportEntry { Type::Indirect, exportName, moduleName, importName, Identifier() }; 117 125 } 118 126 119 auto JSModuleRecord::Resolution::notFound() -> Resolution127 auto AbstractModuleRecord::Resolution::notFound() -> Resolution 120 128 { 121 129 return Resolution { Type::NotFound, nullptr, Identifier() }; 122 130 } 123 131 124 auto JSModuleRecord::Resolution::error() -> Resolution132 auto AbstractModuleRecord::Resolution::error() -> Resolution 125 133 { 126 134 return Resolution { Type::Error, nullptr, Identifier() }; 127 135 } 128 136 129 auto JSModuleRecord::Resolution::ambiguous() -> Resolution137 auto AbstractModuleRecord::Resolution::ambiguous() -> Resolution 130 138 { 131 139 return Resolution { Type::Ambiguous, nullptr, Identifier() }; … … 139 147 } 140 148 141 JSModuleRecord* JSModuleRecord::hostResolveImportedModule(ExecState* exec, const Identifier& moduleName)149 AbstractModuleRecord* AbstractModuleRecord::hostResolveImportedModule(ExecState* exec, const Identifier& moduleName) 142 150 { 143 151 JSValue moduleNameValue = identifierToJSValue(exec, moduleName); 144 152 JSValue pair = m_dependenciesMap->JSMap::get(exec, moduleNameValue); 145 return jsCast< JSModuleRecord*>(pair.get(exec, Identifier::fromString(exec, "value")));146 } 147 148 auto JSModuleRecord::resolveImport(ExecState* exec, const Identifier& localName) -> Resolution153 return jsCast<AbstractModuleRecord*>(pair.get(exec, Identifier::fromString(exec, "value"))); 154 } 155 156 auto AbstractModuleRecord::resolveImport(ExecState* exec, const Identifier& localName) -> Resolution 149 157 { 150 158 std::optional<ImportEntry> optionalImportEntry = tryGetImportEntry(localName.impl()); … … 156 164 return Resolution::notFound(); 157 165 158 JSModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest);166 AbstractModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest); 159 167 return importedModule->resolveExport(exec, importEntry.importName); 160 168 } 161 169 162 struct JSModuleRecord::ResolveQuery {170 struct AbstractModuleRecord::ResolveQuery { 163 171 struct Hash { 164 172 static unsigned hash(const ResolveQuery&); … … 167 175 }; 168 176 169 ResolveQuery( JSModuleRecord* moduleRecord, UniquedStringImpl* exportName)177 ResolveQuery(AbstractModuleRecord* moduleRecord, UniquedStringImpl* exportName) 170 178 : moduleRecord(moduleRecord) 171 179 , exportName(exportName) … … 173 181 } 174 182 175 ResolveQuery( JSModuleRecord* moduleRecord, const Identifier& exportName)183 ResolveQuery(AbstractModuleRecord* moduleRecord, const Identifier& exportName) 176 184 : ResolveQuery(moduleRecord, exportName.impl()) 177 185 { … … 202 210 // The module record is not marked from the GC. But these records are reachable from the JSGlobalObject. 203 211 // So we don't care the reachability to this record. 204 JSModuleRecord* moduleRecord;212 AbstractModuleRecord* moduleRecord; 205 213 RefPtr<UniquedStringImpl> exportName; 206 214 }; 207 215 208 inline unsigned JSModuleRecord::ResolveQuery::Hash::hash(const ResolveQuery& query)209 { 210 return WTF::PtrHash< JSModuleRecord*>::hash(query.moduleRecord) + IdentifierRepHash::hash(query.exportName);211 } 212 213 inline bool JSModuleRecord::ResolveQuery::Hash::equal(const ResolveQuery& lhs, const ResolveQuery& rhs)216 inline unsigned AbstractModuleRecord::ResolveQuery::Hash::hash(const ResolveQuery& query) 217 { 218 return WTF::PtrHash<AbstractModuleRecord*>::hash(query.moduleRecord) + IdentifierRepHash::hash(query.exportName); 219 } 220 221 inline bool AbstractModuleRecord::ResolveQuery::Hash::equal(const ResolveQuery& lhs, const ResolveQuery& rhs) 214 222 { 215 223 return lhs.moduleRecord == rhs.moduleRecord && lhs.exportName == rhs.exportName; 216 224 } 217 225 218 auto JSModuleRecord::tryGetCachedResolution(UniquedStringImpl* exportName) -> std::optional<Resolution>226 auto AbstractModuleRecord::tryGetCachedResolution(UniquedStringImpl* exportName) -> std::optional<Resolution> 219 227 { 220 228 const auto iterator = m_resolutionCache.find(exportName); … … 224 232 } 225 233 226 void JSModuleRecord::cacheResolution(UniquedStringImpl* exportName, const Resolution& resolution)234 void AbstractModuleRecord::cacheResolution(UniquedStringImpl* exportName, const Resolution& resolution) 227 235 { 228 236 m_resolutionCache.add(exportName, resolution); 229 237 } 230 238 231 auto JSModuleRecord::resolveExportImpl(ExecState* exec, const ResolveQuery& root) -> Resolution239 auto AbstractModuleRecord::resolveExportImpl(ExecState* exec, const ResolveQuery& root) -> Resolution 232 240 { 233 241 // http://www.ecma-international.org/ecma-262/6.0/#sec-resolveexport … … 271 279 // If we only hold the global resolution result during the resolveExport operation, [here], 272 280 // we decide the entire result of resolveExport is "Ambiguous", because there are multiple 273 // "Res love" (in module (2) and (5)). However, this should become "Error" because (6) will281 // "Resolve" (in module (2) and (5)). However, this should become "Error" because (6) will 274 282 // propagate "Error" state to the (4), (4) will become "Error" and then, (1) will become 275 283 // "Error". We should aggregate the results at the star exports point ((4) and (1)). … … 293 301 // Here, we attempt to cache the resolution by constructing the map in module records. 294 302 // That means Module -> ExportName -> Maybe<Resolution>. 295 // Technically, all the JSModuleRecords have the Map<ExportName, Resolution> for caching.303 // Technically, all the AbstractModuleRecords have the Map<ExportName, Resolution> for caching. 296 304 // 297 305 // The important observations are that, … … 475 483 Vector<Task, 8> pendingTasks; 476 484 ResolveSet resolveSet; 477 HashSet< JSModuleRecord*> starSet;485 HashSet<AbstractModuleRecord*> starSet; 478 486 479 487 Vector<Resolution, 8> frames; … … 507 515 for (auto iterator = query.moduleRecord->starExportEntries().rbegin(), end = query.moduleRecord->starExportEntries().rend(); iterator != end; ++iterator) { 508 516 const RefPtr<UniquedStringImpl>& starModuleName = *iterator; 509 JSModuleRecord* importedModuleRecord = query.moduleRecord->hostResolveImportedModule(exec, Identifier::fromUid(exec, starModuleName.get()));517 AbstractModuleRecord* importedModuleRecord = query.moduleRecord->hostResolveImportedModule(exec, Identifier::fromUid(exec, starModuleName.get())); 510 518 pendingTasks.append(Task { ResolveQuery(importedModuleRecord, query.exportName.get()), Type::Query }); 511 519 } … … 548 556 switch (task.type) { 549 557 case Type::Query: { 550 JSModuleRecord* moduleRecord = query.moduleRecord;558 AbstractModuleRecord* moduleRecord = query.moduleRecord; 551 559 552 560 if (!resolveSet.add(task.query).isNewEntry) … … 588 596 589 597 case ExportEntry::Type::Indirect: { 590 JSModuleRecord* importedModuleRecord = moduleRecord->hostResolveImportedModule(exec, exportEntry.moduleName);598 AbstractModuleRecord* importedModuleRecord = moduleRecord->hostResolveImportedModule(exec, exportEntry.moduleName); 591 599 592 600 // When the imported module does not produce any resolved binding, we need to look into the stars in the *current* … … 646 654 } 647 655 648 auto JSModuleRecord::resolveExport(ExecState* exec, const Identifier& exportName) -> Resolution656 auto AbstractModuleRecord::resolveExport(ExecState* exec, const Identifier& exportName) -> Resolution 649 657 { 650 658 // Look up the cached resolution first before entering the resolving loop, since the loop setup takes some cost. … … 654 662 } 655 663 656 static void getExportedNames(ExecState* exec, JSModuleRecord* root, IdentifierSet& exportedNames)657 { 658 HashSet< JSModuleRecord*> exportStarSet;659 Vector< JSModuleRecord*, 8> pendingModules;664 static void getExportedNames(ExecState* exec, AbstractModuleRecord* root, IdentifierSet& exportedNames) 665 { 666 HashSet<AbstractModuleRecord*> exportStarSet; 667 Vector<AbstractModuleRecord*, 8> pendingModules; 660 668 661 669 pendingModules.append(root); 662 670 663 671 while (!pendingModules.isEmpty()) { 664 JSModuleRecord* moduleRecord = pendingModules.takeLast();672 AbstractModuleRecord* moduleRecord = pendingModules.takeLast(); 665 673 if (exportStarSet.contains(moduleRecord)) 666 674 continue; … … 668 676 669 677 for (const auto& pair : moduleRecord->exportEntries()) { 670 const JSModuleRecord::ExportEntry& exportEntry = pair.value;678 const AbstractModuleRecord::ExportEntry& exportEntry = pair.value; 671 679 if (moduleRecord == root || exec->propertyNames().defaultKeyword != exportEntry.exportName) 672 680 exportedNames.add(exportEntry.exportName.impl()); … … 674 682 675 683 for (const auto& starModuleName : moduleRecord->starExportEntries()) { 676 JSModuleRecord* requestedModuleRecord = moduleRecord->hostResolveImportedModule(exec, Identifier::fromUid(exec, starModuleName.get()));684 AbstractModuleRecord* requestedModuleRecord = moduleRecord->hostResolveImportedModule(exec, Identifier::fromUid(exec, starModuleName.get())); 677 685 pendingModules.append(requestedModuleRecord); 678 686 } … … 680 688 } 681 689 682 JSModuleNamespaceObject* JSModuleRecord::getModuleNamespace(ExecState* exec)690 JSModuleNamespaceObject* AbstractModuleRecord::getModuleNamespace(ExecState* exec) 683 691 { 684 692 VM& vm = exec->vm(); … … 695 703 IdentifierSet unambiguousNames; 696 704 for (auto& name : exportedNames) { 697 const JSModuleRecord::Resolution resolution = resolveExport(exec, Identifier::fromUid(exec, name.get()));705 const AbstractModuleRecord::Resolution resolution = resolveExport(exec, Identifier::fromUid(exec, name.get())); 698 706 switch (resolution.type) { 699 707 case Resolution::Type::NotFound: … … 718 726 } 719 727 720 void JSModuleRecord::link(ExecState* exec)721 {722 VM& vm = exec->vm();723 auto scope = DECLARE_THROW_SCOPE(vm);724 725 ModuleProgramExecutable* executable = ModuleProgramExecutable::create(exec, sourceCode());726 if (!executable) {727 throwSyntaxError(exec, scope);728 return;729 }730 m_moduleProgramExecutable.set(vm, this, executable);731 instantiateDeclarations(exec, executable);732 }733 734 void JSModuleRecord::instantiateDeclarations(ExecState* exec, ModuleProgramExecutable* moduleProgramExecutable)735 {736 VM& vm = exec->vm();737 auto scope = DECLARE_THROW_SCOPE(vm);738 739 // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation740 741 SymbolTable* symbolTable = moduleProgramExecutable->moduleEnvironmentSymbolTable();742 JSModuleEnvironment* moduleEnvironment = JSModuleEnvironment::create(vm, exec->lexicalGlobalObject(), exec->lexicalGlobalObject(), symbolTable, jsTDZValue(), this);743 744 // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation745 // section 15.2.1.16.4 step 9.746 // Ensure all the indirect exports are correctly resolved to unique bindings.747 // Even if we avoided duplicate exports in the parser, still ambiguous exports occur due to the star export (`export * from "mod"`).748 // When we see this type of ambiguity for the indirect exports here, throw a syntax error.749 for (const auto& pair : m_exportEntries) {750 const ExportEntry& exportEntry = pair.value;751 if (exportEntry.type == JSModuleRecord::ExportEntry::Type::Indirect) {752 Resolution resolution = resolveExport(exec, exportEntry.exportName);753 switch (resolution.type) {754 case Resolution::Type::NotFound:755 throwSyntaxError(exec, scope, makeString("Indirectly exported binding name '", String(exportEntry.exportName.impl()), "' is not found."));756 return;757 758 case Resolution::Type::Ambiguous:759 throwSyntaxError(exec, scope, makeString("Indirectly exported binding name '", String(exportEntry.exportName.impl()), "' cannot be resolved due to ambiguous multiple bindings."));760 return;761 762 case Resolution::Type::Error:763 throwSyntaxError(exec, scope, makeString("Indirectly exported binding name 'default' cannot be resolved by star export entries."));764 return;765 766 case Resolution::Type::Resolved:767 break;768 }769 }770 }771 772 // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation773 // section 15.2.1.16.4 step 12.774 // Instantiate namespace objects and initialize the bindings with them if required.775 // And ensure that all the imports correctly resolved to unique bindings.776 for (const auto& pair : m_importEntries) {777 const ImportEntry& importEntry = pair.value;778 JSModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest);779 if (importEntry.isNamespace(vm)) {780 JSModuleNamespaceObject* namespaceObject = importedModule->getModuleNamespace(exec);781 RETURN_IF_EXCEPTION(scope, void());782 bool putResult = false;783 symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, importEntry.localName, namespaceObject, /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true, putResult);784 } else {785 Resolution resolution = importedModule->resolveExport(exec, importEntry.importName);786 switch (resolution.type) {787 case Resolution::Type::NotFound:788 throwSyntaxError(exec, scope, makeString("Importing binding name '", String(importEntry.importName.impl()), "' is not found."));789 return;790 791 case Resolution::Type::Ambiguous:792 throwSyntaxError(exec, scope, makeString("Importing binding name '", String(importEntry.importName.impl()), "' cannot be resolved due to ambiguous multiple bindings."));793 return;794 795 case Resolution::Type::Error:796 throwSyntaxError(exec, scope, makeString("Importing binding name 'default' cannot be resolved by star export entries."));797 return;798 799 case Resolution::Type::Resolved:800 break;801 }802 }803 }804 805 // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation806 // section 15.2.1.16.4 step 14.807 // Module environment contains the heap allocated "var", "function", "let", "const", and "class".808 // When creating the environment, we initialized all the slots with empty, it's ok for lexical values.809 // But for "var" and "function", we should initialize it with undefined. They are contained in the declared variables.810 for (const auto& variable : m_declaredVariables) {811 SymbolTableEntry entry = symbolTable->get(variable.key.get());812 VarOffset offset = entry.varOffset();813 if (!offset.isStack()) {814 bool putResult = false;815 symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, Identifier::fromUid(exec, variable.key.get()), jsUndefined(), /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true, putResult);816 }817 }818 819 // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation820 // section 15.2.1.16.4 step 16-a-iv.821 // Initialize heap allocated function declarations.822 // They can be called before the body of the module is executed under circular dependencies.823 UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock = moduleProgramExecutable->unlinkedModuleProgramCodeBlock();824 for (size_t i = 0, numberOfFunctions = unlinkedCodeBlock->numberOfFunctionDecls(); i < numberOfFunctions; ++i) {825 UnlinkedFunctionExecutable* unlinkedFunctionExecutable = unlinkedCodeBlock->functionDecl(i);826 SymbolTableEntry entry = symbolTable->get(unlinkedFunctionExecutable->name().impl());827 VarOffset offset = entry.varOffset();828 if (!offset.isStack()) {829 ASSERT(!unlinkedFunctionExecutable->name().isEmpty());830 if (vm.typeProfiler() || vm.controlFlowProfiler()) {831 vm.functionHasExecutedCache()->insertUnexecutedRange(moduleProgramExecutable->sourceID(),832 unlinkedFunctionExecutable->typeProfilingStartOffset(),833 unlinkedFunctionExecutable->typeProfilingEndOffset());834 }835 JSFunction* function = JSFunction::create(vm, unlinkedFunctionExecutable->link(vm, moduleProgramExecutable->source()), moduleEnvironment);836 bool putResult = false;837 symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, unlinkedFunctionExecutable->name(), function, /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true, putResult);838 }839 }840 841 m_moduleEnvironment.set(vm, this, moduleEnvironment);842 }843 844 JSValue JSModuleRecord::evaluate(ExecState* exec)845 {846 if (!m_moduleProgramExecutable)847 return jsUndefined();848 JSValue result = exec->interpreter()->execute(m_moduleProgramExecutable.get(), exec, m_moduleEnvironment.get());849 m_moduleProgramExecutable.clear();850 return result;851 }852 853 728 static String printableName(const RefPtr<UniquedStringImpl>& uid) 854 729 { … … 863 738 } 864 739 865 void JSModuleRecord::dump()740 void AbstractModuleRecord::dump() 866 741 { 867 742 dataLog("\nAnalyzing ModuleRecord key(", printableName(m_moduleKey), ")\n"); -
trunk/Source/JavaScriptCore/runtime/AbstractModuleRecord.h
r209122 r209123 36 36 namespace JSC { 37 37 38 class JSModuleEnvironment; 38 39 class JSModuleNamespaceObject; 39 class JSModuleEnvironment;40 40 class JSMap; 41 class ModuleProgramExecutable;42 41 43 42 // Based on the Source Text Module Record 44 43 // http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records 45 class JSModuleRecord : public JSDestructibleObject {44 class AbstractModuleRecord : public JSDestructibleObject { 46 45 friend class LLIntOffsetsExtractor; 47 46 public: … … 82 81 DECLARE_EXPORT_INFO; 83 82 84 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)85 {86 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());87 }88 89 static JSModuleRecord* create(ExecState* exec, VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)90 {91 JSModuleRecord* instance = new (NotNull, allocateCell<JSModuleRecord>(vm.heap)) JSModuleRecord(vm, structure, moduleKey, sourceCode, declaredVariables, lexicalVariables);92 instance->finishCreation(exec, vm);93 return instance;94 }95 96 83 void appendRequestedModule(const Identifier&); 97 84 void addStarExportEntry(const Identifier&); … … 114 101 void dump(); 115 102 116 JSModuleEnvironment* moduleEnvironment()117 {118 ASSERT(m_moduleEnvironment);119 return m_moduleEnvironment.get();120 }121 122 void link(ExecState*);123 JS_EXPORT_PRIVATE JSValue evaluate(ExecState*);124 125 ModuleProgramExecutable* moduleProgramExecutable() const { return m_moduleProgramExecutable.get(); }126 127 103 struct Resolution { 128 104 enum class Type { Resolved, NotFound, Ambiguous, Error }; … … 133 109 134 110 Type type; 135 JSModuleRecord* moduleRecord;111 AbstractModuleRecord* moduleRecord; 136 112 Identifier localName; 137 113 }; … … 140 116 Resolution resolveImport(ExecState*, const Identifier& localName); 141 117 142 JSModuleRecord* hostResolveImportedModule(ExecState*, const Identifier& moduleName);118 AbstractModuleRecord* hostResolveImportedModule(ExecState*, const Identifier& moduleName); 143 119 144 private: 145 JSModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables) 146 : Base(vm, structure) 147 , m_moduleKey(moduleKey) 148 , m_sourceCode(sourceCode) 149 , m_declaredVariables(declaredVariables) 150 , m_lexicalVariables(lexicalVariables) 120 JSModuleNamespaceObject* getModuleNamespace(ExecState*); 121 122 JSModuleEnvironment* moduleEnvironment() 151 123 { 124 ASSERT(m_moduleEnvironment); 125 return m_moduleEnvironment.get(); 152 126 } 153 127 128 protected: 129 AbstractModuleRecord(VM&, Structure*, const Identifier&, const SourceCode&, const VariableEnvironment&, const VariableEnvironment&); 154 130 void finishCreation(ExecState*, VM&); 155 156 JSModuleNamespaceObject* getModuleNamespace(ExecState*);157 131 158 132 static void visitChildren(JSCell*, SlotVisitor&); 159 133 static void destroy(JSCell*); 160 134 161 void instantiateDeclarations(ExecState*, ModuleProgramExecutable*);135 WriteBarrier<JSModuleEnvironment> m_moduleEnvironment; 162 136 137 private: 163 138 struct ResolveQuery; 164 139 static Resolution resolveExportImpl(ExecState*, const ResolveQuery&); … … 201 176 202 177 WriteBarrier<JSMap> m_dependenciesMap; 203 204 WriteBarrier<ModuleProgramExecutable> m_moduleProgramExecutable; 205 WriteBarrier<JSModuleEnvironment> m_moduleEnvironment; 178 206 179 WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject; 207 180 208 // We assume that all the JSModuleRecord are retained by JSModuleLoader's registry.181 // We assume that all the AbstractModuleRecord are retained by JSModuleLoader's registry. 209 182 // So here, we don't visit each object for GC. The resolution cache map caches the once 210 183 // looked up correctly resolved resolution, since (1) we rarely looked up the non-resolved one, -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r208953 r209123 877 877 auto* webAssemblyPrototype = WebAssemblyPrototype::create(vm, this, WebAssemblyPrototype::createStructure(vm, this, m_objectPrototype.get())); 878 878 m_webAssemblyStructure.set(vm, this, JSWebAssembly::createStructure(vm, this, webAssemblyPrototype)); 879 m_webAssemblyModuleRecordStructure.set(vm, this, WebAssemblyModuleRecord::createStructure(vm, this, m_objectPrototype.get())); 880 m_webAssemblyFunctionStructure.set(vm, this, WebAssemblyFunction::createStructure(vm, this, m_objectPrototype.get())); 879 881 auto* webAssembly = JSWebAssembly::create(vm, this, m_webAssemblyStructure.get()); 880 882 putDirectWithoutTransition(vm, Identifier::fromString(exec, "WebAssembly"), webAssembly, DontEnum); … … 1254 1256 #if ENABLE(WEBASSEMBLY) 1255 1257 visitor.append(&thisObject->m_webAssemblyStructure); 1258 visitor.append(&thisObject->m_webAssemblyModuleRecordStructure); 1259 visitor.append(&thisObject->m_webAssemblyFunctionStructure); 1256 1260 FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(VISIT_SIMPLE_TYPE) 1257 1261 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h
r208712 r209123 343 343 #if ENABLE(WEBASSEMBLY) 344 344 WriteBarrier<Structure> m_webAssemblyStructure; 345 WriteBarrier<Structure> m_webAssemblyModuleRecordStructure; 346 WriteBarrier<Structure> m_webAssemblyFunctionStructure; 345 347 FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(DEFINE_STORAGE_FOR_SIMPLE_TYPE) 346 348 #endif // ENABLE(WEBASSEMBLY) … … 626 628 Structure* moduleLoaderStructure() const { return m_moduleLoaderStructure.get(); } 627 629 Structure* restParameterStructure() const { return arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous); } 630 #if ENABLE(WEBASSEMBLY) 631 Structure* webAssemblyModuleRecordStructure() const { return m_webAssemblyModuleRecordStructure.get(); } 632 Structure* webAssemblyFunctionStructure() const { return m_webAssemblyFunctionStructure.get(); } 633 #endif // ENABLE(WEBASSEMBLY) 628 634 629 635 JS_EXPORT_PRIVATE void setRemoteDebuggingEnabled(bool); -
trunk/Source/JavaScriptCore/runtime/JSModuleEnvironment.cpp
r207023 r209123 30 30 #include "JSModuleEnvironment.h" 31 31 32 #include "AbstractModuleRecord.h" 32 33 #include "Interpreter.h" 33 34 #include "JSCInlines.h" … … 41 42 42 43 JSModuleEnvironment* JSModuleEnvironment::create( 43 VM& vm, Structure* structure, JSScope* currentScope, SymbolTable* symbolTable, JSValue initialValue, JSModuleRecord* moduleRecord)44 VM& vm, Structure* structure, JSScope* currentScope, SymbolTable* symbolTable, JSValue initialValue, AbstractModuleRecord* moduleRecord) 44 45 { 45 46 // JSLexicalEnvironment (precisely, JSEnvironmentRecord) has the storage to store the variable slots after the its class storage. 46 47 // Because the offset of the variable slots are fixed in the JSEnvironmentRecord, inheritting these class and adding new member field is not allowed, 47 48 // the new member will overlap the variable slots. 48 // To keep the JSModuleEnvironment compatible to the JSLexicalEnvironment but add the new member to store the JSModuleRecord, we additionally allocate49 // To keep the JSModuleEnvironment compatible to the JSLexicalEnvironment but add the new member to store the AbstractModuleRecord, we additionally allocate 49 50 // the storage after the variable slots. 50 51 // … … 63 64 } 64 65 65 void JSModuleEnvironment::finishCreation(VM& vm, JSValue initialValue, JSModuleRecord* moduleRecord)66 void JSModuleEnvironment::finishCreation(VM& vm, JSValue initialValue, AbstractModuleRecord* moduleRecord) 66 67 { 67 68 Base::finishCreation(vm, initialValue); … … 82 83 auto scope = DECLARE_THROW_SCOPE(vm); 83 84 JSModuleEnvironment* thisObject = jsCast<JSModuleEnvironment*>(cell); 84 JSModuleRecord::Resolution resolution = thisObject->moduleRecord()->resolveImport(exec, Identifier::fromUid(exec, propertyName.uid()));85 if (resolution.type == JSModuleRecord::Resolution::Type::Resolved) {85 AbstractModuleRecord::Resolution resolution = thisObject->moduleRecord()->resolveImport(exec, Identifier::fromUid(exec, propertyName.uid())); 86 if (resolution.type == AbstractModuleRecord::Resolution::Type::Resolved) { 86 87 // When resolveImport resolves the resolution, the imported module environment must have the binding. 87 88 JSModuleEnvironment* importedModuleEnvironment = resolution.moduleRecord->moduleEnvironment(); … … 103 104 if (propertyNamesArray.includeStringProperties()) { 104 105 for (const auto& pair : thisObject->moduleRecord()->importEntries()) { 105 const JSModuleRecord::ImportEntry& importEntry = pair.value;106 const AbstractModuleRecord::ImportEntry& importEntry = pair.value; 106 107 if (!importEntry.isNamespace(exec->vm())) 107 108 propertyNamesArray.add(importEntry.localName); … … 118 119 JSModuleEnvironment* thisObject = jsCast<JSModuleEnvironment*>(cell); 119 120 // All imported bindings are immutable. 120 JSModuleRecord::Resolution resolution = thisObject->moduleRecord()->resolveImport(exec, Identifier::fromUid(exec, propertyName.uid()));121 if (resolution.type == JSModuleRecord::Resolution::Type::Resolved) {121 AbstractModuleRecord::Resolution resolution = thisObject->moduleRecord()->resolveImport(exec, Identifier::fromUid(exec, propertyName.uid())); 122 if (resolution.type == AbstractModuleRecord::Resolution::Type::Resolved) { 122 123 throwTypeError(exec, scope, ASCIILiteral(ReadonlyPropertyWriteError)); 123 124 return false; … … 130 131 JSModuleEnvironment* thisObject = jsCast<JSModuleEnvironment*>(cell); 131 132 // All imported bindings are immutable. 132 JSModuleRecord::Resolution resolution = thisObject->moduleRecord()->resolveImport(exec, Identifier::fromUid(exec, propertyName.uid()));133 if (resolution.type == JSModuleRecord::Resolution::Type::Resolved)133 AbstractModuleRecord::Resolution resolution = thisObject->moduleRecord()->resolveImport(exec, Identifier::fromUid(exec, propertyName.uid())); 134 if (resolution.type == AbstractModuleRecord::Resolution::Type::Resolved) 134 135 return false; 135 136 return Base::deleteProperty(thisObject, exec, propertyName); -
trunk/Source/JavaScriptCore/runtime/JSModuleEnvironment.h
r206525 r209123 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 30 30 31 31 #include "JSLexicalEnvironment.h" 32 #include "JSModuleRecord.h"33 32 34 33 namespace JSC { 35 34 35 class AbstractModuleRecord; 36 36 class Register; 37 37 … … 43 43 static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames; 44 44 45 static JSModuleEnvironment* create(VM&, Structure*, JSScope*, SymbolTable*, JSValue initialValue, JSModuleRecord*);45 static JSModuleEnvironment* create(VM&, Structure*, JSScope*, SymbolTable*, JSValue initialValue, AbstractModuleRecord*); 46 46 47 static JSModuleEnvironment* create(VM& vm, JSGlobalObject* globalObject, JSScope* currentScope, SymbolTable* symbolTable, JSValue initialValue, JSModuleRecord* moduleRecord)47 static JSModuleEnvironment* create(VM& vm, JSGlobalObject* globalObject, JSScope* currentScope, SymbolTable* symbolTable, JSValue initialValue, AbstractModuleRecord* moduleRecord) 48 48 { 49 49 Structure* structure = globalObject->moduleEnvironmentStructure(); … … 61 61 { 62 62 size_t offset = Base::allocationSize(symbolTable); 63 ASSERT(WTF::roundUpToMultipleOf<sizeof(WriteBarrier< JSModuleRecord>)>(offset) == offset);63 ASSERT(WTF::roundUpToMultipleOf<sizeof(WriteBarrier<AbstractModuleRecord>)>(offset) == offset); 64 64 return offset; 65 65 } … … 67 67 static size_t allocationSize(SymbolTable* symbolTable) 68 68 { 69 return offsetOfModuleRecord(symbolTable) + sizeof(WriteBarrier< JSModuleRecord>);69 return offsetOfModuleRecord(symbolTable) + sizeof(WriteBarrier<AbstractModuleRecord>); 70 70 } 71 71 72 JSModuleRecord* moduleRecord()72 AbstractModuleRecord* moduleRecord() 73 73 { 74 74 return moduleRecordSlot().get(); … … 83 83 JSModuleEnvironment(VM&, Structure*, JSScope*, SymbolTable*); 84 84 85 void finishCreation(VM&, JSValue initialValue, JSModuleRecord*);85 void finishCreation(VM&, JSValue initialValue, AbstractModuleRecord*); 86 86 87 WriteBarrierBase< JSModuleRecord>& moduleRecordSlot()87 WriteBarrierBase<AbstractModuleRecord>& moduleRecordSlot() 88 88 { 89 return *bitwise_cast<WriteBarrierBase< JSModuleRecord>*>(bitwise_cast<char*>(this) + offsetOfModuleRecord(symbolTable()));89 return *bitwise_cast<WriteBarrierBase<AbstractModuleRecord>*>(bitwise_cast<char*>(this) + offsetOfModuleRecord(symbolTable())); 90 90 } 91 91 -
trunk/Source/JavaScriptCore/runtime/JSModuleNamespaceObject.cpp
r207411 r209123 27 27 #include "JSModuleNamespaceObject.h" 28 28 29 #include "AbstractModuleRecord.h" 29 30 #include "Error.h" 30 31 #include "JSCInlines.h" 31 32 #include "JSModuleEnvironment.h" 32 #include "JSModuleRecord.h"33 33 #include "JSPropertyNameIterator.h" 34 34 … … 46 46 } 47 47 48 void JSModuleNamespaceObject::finishCreation(ExecState* exec, JSGlobalObject* globalObject, JSModuleRecord* moduleRecord, const IdentifierSet& exports)48 void JSModuleNamespaceObject::finishCreation(ExecState* exec, JSGlobalObject* globalObject, AbstractModuleRecord* moduleRecord, const IdentifierSet& exports) 49 49 { 50 50 VM& vm = exec->vm(); … … 121 121 case PropertySlot::InternalMethodType::Get: 122 122 case PropertySlot::InternalMethodType::GetOwnProperty: { 123 JSModuleRecord* moduleRecord = thisObject->moduleRecord();124 125 JSModuleRecord::Resolution resolution = moduleRecord->resolveExport(exec, Identifier::fromUid(exec, propertyName.uid()));126 ASSERT(resolution.type != JSModuleRecord::Resolution::Type::NotFound && resolution.type != JSModuleRecord::Resolution::Type::Ambiguous);127 128 JSModuleRecord* targetModule = resolution.moduleRecord;123 AbstractModuleRecord* moduleRecord = thisObject->moduleRecord(); 124 125 AbstractModuleRecord::Resolution resolution = moduleRecord->resolveExport(exec, Identifier::fromUid(exec, propertyName.uid())); 126 ASSERT(resolution.type != AbstractModuleRecord::Resolution::Type::NotFound && resolution.type != AbstractModuleRecord::Resolution::Type::Ambiguous); 127 128 AbstractModuleRecord* targetModule = resolution.moduleRecord; 129 129 JSModuleEnvironment* targetEnvironment = targetModule->moduleEnvironment(); 130 130 -
trunk/Source/JavaScriptCore/runtime/JSModuleNamespaceObject.h
r206525 r209123 31 31 namespace JSC { 32 32 33 class JSModuleRecord;33 class AbstractModuleRecord; 34 34 35 35 class JSModuleNamespaceObject : public JSDestructibleObject { … … 38 38 static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames | GetOwnPropertySlotIsImpureForPropertyAbsence; 39 39 40 static JSModuleNamespaceObject* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, JSModuleRecord* moduleRecord, const IdentifierSet& exports)40 static JSModuleNamespaceObject* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, AbstractModuleRecord* moduleRecord, const IdentifierSet& exports) 41 41 { 42 42 JSModuleNamespaceObject* object = new (NotNull, allocateCell<JSModuleNamespaceObject>(exec->vm().heap)) JSModuleNamespaceObject(exec->vm(), structure); … … 59 59 } 60 60 61 JSModuleRecord* moduleRecord() { return m_moduleRecord.get(); }61 AbstractModuleRecord* moduleRecord() { return m_moduleRecord.get(); } 62 62 63 63 protected: 64 JS_EXPORT_PRIVATE void finishCreation(ExecState*, JSGlobalObject*, JSModuleRecord*, const IdentifierSet& exports);64 JS_EXPORT_PRIVATE void finishCreation(ExecState*, JSGlobalObject*, AbstractModuleRecord*, const IdentifierSet& exports); 65 65 JS_EXPORT_PRIVATE JSModuleNamespaceObject(VM&, Structure*); 66 66 … … 72 72 73 73 OrderedIdentifierSet m_exports; 74 WriteBarrier< JSModuleRecord> m_moduleRecord;74 WriteBarrier<AbstractModuleRecord> m_moduleRecord; 75 75 }; 76 76 -
trunk/Source/JavaScriptCore/runtime/JSModuleRecord.cpp
r208985 r209123 30 30 #include "Interpreter.h" 31 31 #include "JSCInlines.h" 32 #include "JSMap.h"33 32 #include "JSModuleEnvironment.h" 34 33 #include "JSModuleNamespaceObject.h" … … 39 38 const ClassInfo JSModuleRecord::s_info = { "ModuleRecord", &Base::s_info, 0, CREATE_METHOD_TABLE(JSModuleRecord) }; 40 39 40 41 Structure* JSModuleRecord::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 42 { 43 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); 44 } 45 46 JSModuleRecord* JSModuleRecord::create(ExecState* exec, VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables) 47 { 48 JSModuleRecord* instance = new (NotNull, allocateCell<JSModuleRecord>(vm.heap)) JSModuleRecord(vm, structure, moduleKey, sourceCode, declaredVariables, lexicalVariables); 49 instance->finishCreation(exec, vm); 50 return instance; 51 } 52 JSModuleRecord::JSModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables) 53 : Base(vm, structure, moduleKey, sourceCode, declaredVariables, lexicalVariables) 54 { 55 } 56 41 57 void JSModuleRecord::destroy(JSCell* cell) 42 58 { … … 47 63 void JSModuleRecord::finishCreation(ExecState* exec, VM& vm) 48 64 { 49 Base::finishCreation( vm);65 Base::finishCreation(exec, vm); 50 66 ASSERT(inherits(info())); 51 putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("registryEntry")), jsUndefined());52 putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("evaluated")), jsBoolean(false));53 54 auto scope = DECLARE_THROW_SCOPE(vm);55 JSMap* map = JSMap::create(exec, vm, globalObject()->mapStructure());56 RELEASE_ASSERT(!scope.exception());57 m_dependenciesMap.set(vm, this, map);58 putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("dependenciesMap")), m_dependenciesMap.get());59 67 } 60 68 … … 63 71 JSModuleRecord* thisObject = jsCast<JSModuleRecord*>(cell); 64 72 Base::visitChildren(thisObject, visitor); 65 visitor.append(&thisObject->m_moduleEnvironment);66 visitor.append(&thisObject->m_moduleNamespaceObject);67 73 visitor.append(&thisObject->m_moduleProgramExecutable); 68 visitor.append(&thisObject->m_dependenciesMap);69 }70 71 void JSModuleRecord::appendRequestedModule(const Identifier& moduleName)72 {73 m_requestedModules.add(moduleName.impl());74 }75 76 void JSModuleRecord::addStarExportEntry(const Identifier& moduleName)77 {78 m_starExportEntries.add(moduleName.impl());79 }80 81 void JSModuleRecord::addImportEntry(const ImportEntry& entry)82 {83 bool isNewEntry = m_importEntries.add(entry.localName.impl(), entry).isNewEntry;84 ASSERT_UNUSED(isNewEntry, isNewEntry); // This is guaranteed by the parser.85 }86 87 void JSModuleRecord::addExportEntry(const ExportEntry& entry)88 {89 bool isNewEntry = m_exportEntries.add(entry.exportName.impl(), entry).isNewEntry;90 ASSERT_UNUSED(isNewEntry, isNewEntry); // This is guaranteed by the parser.91 }92 93 auto JSModuleRecord::tryGetImportEntry(UniquedStringImpl* localName) -> std::optional<ImportEntry>94 {95 const auto iterator = m_importEntries.find(localName);96 if (iterator == m_importEntries.end())97 return std::nullopt;98 return std::optional<ImportEntry>(iterator->value);99 }100 101 auto JSModuleRecord::tryGetExportEntry(UniquedStringImpl* exportName) -> std::optional<ExportEntry>102 {103 const auto iterator = m_exportEntries.find(exportName);104 if (iterator == m_exportEntries.end())105 return std::nullopt;106 return std::optional<ExportEntry>(iterator->value);107 }108 109 auto JSModuleRecord::ExportEntry::createLocal(const Identifier& exportName, const Identifier& localName) -> ExportEntry110 {111 return ExportEntry { Type::Local, exportName, Identifier(), Identifier(), localName };112 }113 114 auto JSModuleRecord::ExportEntry::createIndirect(const Identifier& exportName, const Identifier& importName, const Identifier& moduleName) -> ExportEntry115 {116 return ExportEntry { Type::Indirect, exportName, moduleName, importName, Identifier() };117 }118 119 auto JSModuleRecord::Resolution::notFound() -> Resolution120 {121 return Resolution { Type::NotFound, nullptr, Identifier() };122 }123 124 auto JSModuleRecord::Resolution::error() -> Resolution125 {126 return Resolution { Type::Error, nullptr, Identifier() };127 }128 129 auto JSModuleRecord::Resolution::ambiguous() -> Resolution130 {131 return Resolution { Type::Ambiguous, nullptr, Identifier() };132 }133 134 static JSValue identifierToJSValue(ExecState* exec, const Identifier& identifier)135 {136 if (identifier.isSymbol())137 return Symbol::create(exec->vm(), static_cast<SymbolImpl&>(*identifier.impl()));138 return jsString(&exec->vm(), identifier.impl());139 }140 141 JSModuleRecord* JSModuleRecord::hostResolveImportedModule(ExecState* exec, const Identifier& moduleName)142 {143 JSValue moduleNameValue = identifierToJSValue(exec, moduleName);144 JSValue pair = m_dependenciesMap->JSMap::get(exec, moduleNameValue);145 return jsCast<JSModuleRecord*>(pair.get(exec, Identifier::fromString(exec, "value")));146 }147 148 auto JSModuleRecord::resolveImport(ExecState* exec, const Identifier& localName) -> Resolution149 {150 std::optional<ImportEntry> optionalImportEntry = tryGetImportEntry(localName.impl());151 if (!optionalImportEntry)152 return Resolution::notFound();153 154 const ImportEntry& importEntry = *optionalImportEntry;155 if (importEntry.isNamespace(exec->vm()))156 return Resolution::notFound();157 158 JSModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest);159 return importedModule->resolveExport(exec, importEntry.importName);160 }161 162 struct JSModuleRecord::ResolveQuery {163 struct Hash {164 static unsigned hash(const ResolveQuery&);165 static bool equal(const ResolveQuery&, const ResolveQuery&);166 static const bool safeToCompareToEmptyOrDeleted = true;167 };168 169 ResolveQuery(JSModuleRecord* moduleRecord, UniquedStringImpl* exportName)170 : moduleRecord(moduleRecord)171 , exportName(exportName)172 {173 }174 175 ResolveQuery(JSModuleRecord* moduleRecord, const Identifier& exportName)176 : ResolveQuery(moduleRecord, exportName.impl())177 {178 }179 180 enum EmptyValueTag { EmptyValue };181 ResolveQuery(EmptyValueTag)182 {183 }184 185 enum DeletedValueTag { DeletedValue };186 ResolveQuery(DeletedValueTag)187 : moduleRecord(nullptr)188 , exportName(WTF::HashTableDeletedValue)189 {190 }191 192 bool isEmptyValue() const193 {194 return !exportName;195 }196 197 bool isDeletedValue() const198 {199 return exportName.isHashTableDeletedValue();200 }201 202 // The module record is not marked from the GC. But these records are reachable from the JSGlobalObject.203 // So we don't care the reachability to this record.204 JSModuleRecord* moduleRecord;205 RefPtr<UniquedStringImpl> exportName;206 };207 208 inline unsigned JSModuleRecord::ResolveQuery::Hash::hash(const ResolveQuery& query)209 {210 return WTF::PtrHash<JSModuleRecord*>::hash(query.moduleRecord) + IdentifierRepHash::hash(query.exportName);211 }212 213 inline bool JSModuleRecord::ResolveQuery::Hash::equal(const ResolveQuery& lhs, const ResolveQuery& rhs)214 {215 return lhs.moduleRecord == rhs.moduleRecord && lhs.exportName == rhs.exportName;216 }217 218 auto JSModuleRecord::tryGetCachedResolution(UniquedStringImpl* exportName) -> std::optional<Resolution>219 {220 const auto iterator = m_resolutionCache.find(exportName);221 if (iterator == m_resolutionCache.end())222 return std::nullopt;223 return std::optional<Resolution>(iterator->value);224 }225 226 void JSModuleRecord::cacheResolution(UniquedStringImpl* exportName, const Resolution& resolution)227 {228 m_resolutionCache.add(exportName, resolution);229 }230 231 auto JSModuleRecord::resolveExportImpl(ExecState* exec, const ResolveQuery& root) -> Resolution232 {233 // http://www.ecma-international.org/ecma-262/6.0/#sec-resolveexport234 235 // How to avoid C++ recursion in this function:236 // This function avoids C++ recursion of the naive ResolveExport implementation.237 // Flatten the recursion to the loop with the task queue and frames.238 //239 // 1. pendingTasks240 // We enqueue the recursive resolveExport call to this queue to avoid recursive calls in C++.241 // The task has 3 types. (1) Query, (2) IndirectFallback and (3) GatherStars.242 // (1) Query243 // Querying the resolution to the current module.244 // (2) IndirectFallback245 // Examine the result of the indirect export resolution. Only when the indirect export resolution fails,246 // we look into the star exports. (step 5-a-vi).247 // (3) GatherStars248 // Examine the result of the star export resolutions.249 //250 // 2. frames251 // When the spec calls the resolveExport recursively, instead we append the frame252 // (that holds the result resolution) to the frames and enqueue the task to the pendingTasks.253 // The entry in the frames means the *local* resolution result of the specific recursive resolveExport.254 //255 // We should maintain the local resolution result instead of holding the global resolution result only.256 // For example,257 //258 // star259 // (1) ---> (2) "Resolve"260 // |261 // |262 // +-> (3) "NotFound"263 // |264 // | star265 // +-> (4) ---> (5) "Resolve" [here]266 // |267 // |268 // +-> (6) "Error"269 //270 // Consider the above graph. The numbers represents the modules. Now we are [here].271 // If we only hold the global resolution result during the resolveExport operation, [here],272 // we decide the entire result of resolveExport is "Ambiguous", because there are multiple273 // "Reslove" (in module (2) and (5)). However, this should become "Error" because (6) will274 // propagate "Error" state to the (4), (4) will become "Error" and then, (1) will become275 // "Error". We should aggregate the results at the star exports point ((4) and (1)).276 //277 // Usually, both "Error" and "Ambiguous" states will throw the syntax error. So except for the content of the278 // error message, there are no difference. (And if we fix the (6) that raises "Error", next, it will produce279 // the "Ambiguous" error due to (5). Anyway, user need to fix the both. So which error should be raised at first280 // doesn't matter so much.281 //282 // However, this may become the problem under the module namespace creation.283 // http://www.ecma-international.org/ecma-262/6.0/#sec-getmodulenamespace284 // section 15.2.1.18, step 3-d-ii285 // Here, we distinguish "Ambiguous" and "Error". When "Error" state is produced, we need to throw the propagated error.286 // But if "Ambiguous" state comes, we just ignore the result.287 // To follow the requirement strictly, in this implementation, we keep the local resolution result to produce the288 // correct result under the above complex cases.289 290 // Caching strategy:291 // The resolveExport operation is frequently called. So caching results is important.292 // We observe the following aspects and based on them construct the caching strategy.293 // Here, we attempt to cache the resolution by constructing the map in module records.294 // That means Module -> ExportName -> Maybe<Resolution>.295 // Technically, all the JSModuleRecords have the Map<ExportName, Resolution> for caching.296 //297 // The important observations are that,298 //299 // - *cacheable* means that traversing to this node from a path will produce the same results as starting from this node.300 //301 // Here, we define the resovling route. We represent [?] as the module that has the local binding.302 // And (?) as the module without the local binding.303 //304 // @ -> (A) -> (B) -> [C]305 //306 // We list the resolving route for each node.307 //308 // (A): (A) -> (B) -> [C]309 // (B): (B) -> [C]310 // [C]: [C]311 //312 // In this case, if we start the tracing from (B), the resolving route becomes (B) -> [C].313 // So this is the same. At that time, we can say (B) is cacheable in the first tracing.314 //315 // - The cache ability of a node depends on the resolving route from this node.316 //317 // 1. The starting point is always cacheable.318 //319 // 2. A module that has resolved a local binding is always cacheable.320 //321 // @ -> (A) -> [B]322 //323 // In the above case, we can see the [B] as cacheable.324 // This is because when starting from [B] node, we immediately resolve with the local binding.325 // So the resolving route from [B] does not depend on the starting point.326 //327 // 3. If we don't follow any star links during the resolution, we can see all the traced nodes are cacheable.328 //329 // If there are non star links, it means that there is *no branch* in the module dependency graph.330 // This *no branch* feature makes all the modules cachable.331 //332 // I.e, if we traverse one star link (even if we successfully resolve that star link),333 // we must still traverse all other star links. I would also explain we don't run into334 // this when resolving a local/indirect link. When resolving a local/indirect link,335 // we won't traverse any star links.336 // And since the module can hold only one local/indirect link for the specific export name (if there337 // are multiple local/indirect links that has the same export name, it should be syntax error in the338 // parsing phase.), there is no multiple outgoing links from a module.339 //340 // @ -> (A) --> (B) -> [C] -> (D) -> (E) -+341 // ^ |342 // | |343 // +------------------------+344 //345 // When starting from @, [C] will be found as the module resolving the given binding.346 // In this case, (B) can cache this resolution. Since the resolving route is the same to the one when347 // starting from (B). After caching the above result, we attempt to resolve the same binding from (D).348 //349 // @350 // |351 // v352 // @ -> (A) --> (B) -> [C] -> (D) -> (E) -+353 // ^ |354 // | |355 // +------------------------+356 //357 // In this case, we can use the (B)'s cached result. And (E) can be cached.358 //359 // (E): The resolving route is now (E) -> (B) -> [C]. That is the same when starting from (E).360 //361 // No branching makes that the problematic *once-visited* node cannot be seen.362 // The *once-visited* node makes the resolving route changed since when we see the *once-visited* node,363 // we stop tracing this.364 //365 // If there is no star links and if we look *once-visited* node under no branching graph, *once-visited*366 // node cannot resolve the requested binding. If the *once-visited* node can resolve the binding, we367 // should have already finished the resolution before reaching this *once-visited* node.368 //369 // 4. Once we follow star links, we should not retrieve the result from the cache and should not cache.370 //371 // Star links are only the way to introduce branch.372 // Once we follow the star links during the resolution, we cannot cache naively.373 // This is because the cacheability depends on the resolving route. And branching produces the problematic *once-visited*374 // nodes. Since we don't follow the *once-visited* node, the resolving route from the node becomes different from375 // the resolving route when starting from this node.376 //377 // The following example explains when we should not retrieve the cache and cache the result.378 //379 // +----> (D) ------+380 // | |381 // | v382 // (A) *----+----> (B) ---> [C]383 // ^384 // |385 // @386 //387 // When starting from (B), we find [C]. In this resolving route, we don't find any star link.388 // And by definition, (B) and [C] are cachable. (B) is the starting point. And [C] has the local binding.389 //390 // +----> (D) ------+391 // | |392 // | v393 // @-> (A) *----+----> (B) ---> [C]394 //395 // But when starting from (A), we should not get the value from the cache. Because,396 //397 // 1. When looking (D), we reach [C] and make both resolved.398 // 2. When looking (B), if we retrieved the last cache from (B), (B) becomes resolved.399 // 3. But actually, (B) is not-found in this trial because (C) is already *once-visited*.400 // 4. If we accidentally make (B) resolved, (A) becomes ambiguous. But the correct answer is resolved.401 //402 // Why is this problem caused? This is because the *once-visited* node makes the result not-found.403 // In the second trial, (B) -> [C] result is changed from resolved to not-found.404 //405 // When does this become a problem? If the status of the *once-visited* node group is resolved,406 // changing the result to not-found makes the result changed.407 //408 // This problem does not happen when we don't see any star link yet. Now, consider the minimum case.409 //410 // @-> (A) -> [ some graph ]411 // ^ |412 // | |413 // +------------+414 //415 // In (A), we don't see any star link yet. So we can say that all the visited nodes does not have any local416 // resolution. Because if they had a local/indirect resolution, we should have already finished the tracing.417 //418 // And even if the some graph will see the *once-visited* node (in this case, (A)), that does not affect the419 // result of the resolution. Because even if we follow the link to (A) or not follow the link to (A), the status420 // of the link is always not-found since (A) does not have any local resolution.421 // In the above case, we can use the result of the [some graph].422 //423 // 5. Once we see star links, even if we have not yet traversed that star link path, we should disable caching.424 //425 // Here is the reason why:426 //427 // +-------------+428 // | |429 // v |430 // (A) -> (B) -> (C) *-> [E]431 // * ^432 // | |433 // v @434 // [D]435 //436 // In the above case, (C) will be resolved with [D].437 // (C) will see (A) and (A) gives up in (A) -> (B) -> (C) route. So, (A) will fallback to [D].438 //439 // +-------------+440 // | |441 // v |442 // @-> (A) -> (B) -> (C) *-> [E]443 // *444 // |445 // v446 // [D]447 //448 // But in this case, (A) will be resolved with [E] (not [D]).449 // (C) will attempt to follow the link to (A), but it fails.450 // So (C) will fallback to the star link and found [E]. In this senario,451 // (C) is now resolved with [E]'s result.452 //453 // The cause of this problem is also the same to 4.454 // In the latter case, when looking (C), we cannot use the cached result in (C).455 // Because the cached result of (C) depends on the *once-visited* node (A) and456 // (A) has the fallback system with the star link.457 // In the latter trial, we now assume that (A)'s status is not-found.458 // But, actually, in the former trial, (A)'s status becomes resolved due to the fallback to the [D].459 //460 // To summarize the observations.461 //462 // 1. The starting point is always cacheable.463 // 2. A module that has resolved a local binding is always cacheable.464 // 3. If we don't follow any star links during the resolution, we can see all the traced nodes are cacheable.465 // 4. Once we follow star links, we should not retrieve the result from the cache and should not cache the result.466 // 5. Once we see star links, even if we have not yet traversed that star link path, we should disable caching.467 468 typedef WTF::HashSet<ResolveQuery, ResolveQuery::Hash, WTF::CustomHashTraits<ResolveQuery>> ResolveSet;469 enum class Type { Query, IndirectFallback, GatherStars };470 struct Task {471 ResolveQuery query;472 Type type;473 };474 475 Vector<Task, 8> pendingTasks;476 ResolveSet resolveSet;477 HashSet<JSModuleRecord*> starSet;478 479 Vector<Resolution, 8> frames;480 481 bool foundStarLinks = false;482 483 frames.append(Resolution::notFound());484 485 // Call when the query is not resolved in the current module.486 // It will enqueue the star resolution requests. Return "false" if the error occurs.487 auto resolveNonLocal = [&](const ResolveQuery& query) -> bool {488 // http://www.ecma-international.org/ecma-262/6.0/#sec-resolveexport489 // section 15.2.1.16.3, step 6490 // If the "default" name is not resolved in the current module, we need to throw an error and stop resolution immediately,491 // Rationale to this error: A default export cannot be provided by an export *.492 if (query.exportName == exec->propertyNames().defaultKeyword.impl())493 return false;494 495 // step 7, If exportStarSet contains module, then return null.496 if (!starSet.add(query.moduleRecord).isNewEntry)497 return true;498 499 // Enqueue the task to gather the results of the stars.500 // And append the new Resolution frame to gather the local result of the stars.501 pendingTasks.append(Task { query, Type::GatherStars });502 foundStarLinks = true;503 frames.append(Resolution::notFound());504 505 506 // Enqueue the tasks in reverse order.507 for (auto iterator = query.moduleRecord->starExportEntries().rbegin(), end = query.moduleRecord->starExportEntries().rend(); iterator != end; ++iterator) {508 const RefPtr<UniquedStringImpl>& starModuleName = *iterator;509 JSModuleRecord* importedModuleRecord = query.moduleRecord->hostResolveImportedModule(exec, Identifier::fromUid(exec, starModuleName.get()));510 pendingTasks.append(Task { ResolveQuery(importedModuleRecord, query.exportName.get()), Type::Query });511 }512 return true;513 };514 515 // Return the current resolution value of the top frame.516 auto currentTop = [&] () -> Resolution& {517 ASSERT(!frames.isEmpty());518 return frames.last();519 };520 521 // Merge the given resolution to the current resolution value of the top frame.522 // If there is ambiguity, return "false". When the "false" is returned, we should make the result "ambiguous".523 auto mergeToCurrentTop = [&] (const Resolution& resolution) -> bool {524 if (resolution.type == Resolution::Type::NotFound)525 return true;526 527 if (currentTop().type == Resolution::Type::NotFound) {528 currentTop() = resolution;529 return true;530 }531 532 if (currentTop().moduleRecord != resolution.moduleRecord || currentTop().localName != resolution.localName)533 return false;534 535 return true;536 };537 538 auto cacheResolutionForQuery = [] (const ResolveQuery& query, const Resolution& resolution) {539 ASSERT(resolution.type == Resolution::Type::Resolved);540 query.moduleRecord->cacheResolution(query.exportName.get(), resolution);541 };542 543 pendingTasks.append(Task { root, Type::Query });544 while (!pendingTasks.isEmpty()) {545 const Task task = pendingTasks.takeLast();546 const ResolveQuery& query = task.query;547 548 switch (task.type) {549 case Type::Query: {550 JSModuleRecord* moduleRecord = query.moduleRecord;551 552 if (!resolveSet.add(task.query).isNewEntry)553 continue;554 555 // 5. Once we see star links, even if we have not yet traversed that star link path, we should disable caching.556 if (!moduleRecord->starExportEntries().isEmpty())557 foundStarLinks = true;558 559 // 4. Once we follow star links, we should not retrieve the result from the cache and should not cache the result.560 if (!foundStarLinks) {561 if (std::optional<Resolution> cachedResolution = moduleRecord->tryGetCachedResolution(query.exportName.get())) {562 if (!mergeToCurrentTop(*cachedResolution))563 return Resolution::ambiguous();564 continue;565 }566 }567 568 const std::optional<ExportEntry> optionalExportEntry = moduleRecord->tryGetExportEntry(query.exportName.get());569 if (!optionalExportEntry) {570 // If there is no matched exported binding in the current module,571 // we need to look into the stars.572 if (!resolveNonLocal(task.query))573 return Resolution::error();574 continue;575 }576 577 const ExportEntry& exportEntry = *optionalExportEntry;578 switch (exportEntry.type) {579 case ExportEntry::Type::Local: {580 ASSERT(!exportEntry.localName.isNull());581 Resolution resolution { Resolution::Type::Resolved, moduleRecord, exportEntry.localName };582 // 2. A module that has resolved a local binding is always cacheable.583 cacheResolutionForQuery(query, resolution);584 if (!mergeToCurrentTop(resolution))585 return Resolution::ambiguous();586 continue;587 }588 589 case ExportEntry::Type::Indirect: {590 JSModuleRecord* importedModuleRecord = moduleRecord->hostResolveImportedModule(exec, exportEntry.moduleName);591 592 // When the imported module does not produce any resolved binding, we need to look into the stars in the *current*593 // module. To do this, we append the `IndirectFallback` task to the task queue.594 pendingTasks.append(Task { query, Type::IndirectFallback });595 // And append the new Resolution frame to check the indirect export will be resolved or not.596 frames.append(Resolution::notFound());597 pendingTasks.append(Task { ResolveQuery(importedModuleRecord, exportEntry.importName), Type::Query });598 continue;599 }600 }601 break;602 }603 604 case Type::IndirectFallback: {605 Resolution resolution = frames.takeLast();606 607 if (resolution.type == Resolution::Type::NotFound) {608 // Indirect export entry does not produce any resolved binding.609 // So we will investigate the stars.610 if (!resolveNonLocal(task.query))611 return Resolution::error();612 continue;613 }614 615 ASSERT_WITH_MESSAGE(resolution.type == Resolution::Type::Resolved, "When we see Error and Ambiguous, we immediately return from this loop. So here, only Resolved comes.");616 617 // 3. If we don't follow any star links during the resolution, we can see all the traced nodes are cacheable.618 // 4. Once we follow star links, we should not retrieve the result from the cache and should not cache the result.619 if (!foundStarLinks)620 cacheResolutionForQuery(query, resolution);621 622 // If indirect export entry produces Resolved, we should merge it to the upper frame.623 // And do not investigate the stars of the current module.624 if (!mergeToCurrentTop(resolution))625 return Resolution::ambiguous();626 break;627 }628 629 case Type::GatherStars: {630 Resolution resolution = frames.takeLast();631 ASSERT_WITH_MESSAGE(resolution.type == Resolution::Type::Resolved || resolution.type == Resolution::Type::NotFound, "When we see Error and Ambiguous, we immediately return from this loop. So here, only Resolved and NotFound comes.");632 633 // Merge the star resolution to the upper frame.634 if (!mergeToCurrentTop(resolution))635 return Resolution::ambiguous();636 break;637 }638 }639 }640 641 ASSERT(frames.size() == 1);642 // 1. The starting point is always cacheable.643 if (frames[0].type == Resolution::Type::Resolved)644 cacheResolutionForQuery(root, frames[0]);645 return frames[0];646 }647 648 auto JSModuleRecord::resolveExport(ExecState* exec, const Identifier& exportName) -> Resolution649 {650 // Look up the cached resolution first before entering the resolving loop, since the loop setup takes some cost.651 if (std::optional<Resolution> cachedResolution = tryGetCachedResolution(exportName.impl()))652 return *cachedResolution;653 return resolveExportImpl(exec, ResolveQuery(this, exportName.impl()));654 }655 656 static void getExportedNames(ExecState* exec, JSModuleRecord* root, IdentifierSet& exportedNames)657 {658 HashSet<JSModuleRecord*> exportStarSet;659 Vector<JSModuleRecord*, 8> pendingModules;660 661 pendingModules.append(root);662 663 while (!pendingModules.isEmpty()) {664 JSModuleRecord* moduleRecord = pendingModules.takeLast();665 if (exportStarSet.contains(moduleRecord))666 continue;667 exportStarSet.add(moduleRecord);668 669 for (const auto& pair : moduleRecord->exportEntries()) {670 const JSModuleRecord::ExportEntry& exportEntry = pair.value;671 if (moduleRecord == root || exec->propertyNames().defaultKeyword != exportEntry.exportName)672 exportedNames.add(exportEntry.exportName.impl());673 }674 675 for (const auto& starModuleName : moduleRecord->starExportEntries()) {676 JSModuleRecord* requestedModuleRecord = moduleRecord->hostResolveImportedModule(exec, Identifier::fromUid(exec, starModuleName.get()));677 pendingModules.append(requestedModuleRecord);678 }679 }680 }681 682 JSModuleNamespaceObject* JSModuleRecord::getModuleNamespace(ExecState* exec)683 {684 VM& vm = exec->vm();685 auto scope = DECLARE_THROW_SCOPE(vm);686 687 // http://www.ecma-international.org/ecma-262/6.0/#sec-getmodulenamespace688 if (m_moduleNamespaceObject)689 return m_moduleNamespaceObject.get();690 691 JSGlobalObject* globalObject = exec->lexicalGlobalObject();692 IdentifierSet exportedNames;693 getExportedNames(exec, this, exportedNames);694 695 IdentifierSet unambiguousNames;696 for (auto& name : exportedNames) {697 const JSModuleRecord::Resolution resolution = resolveExport(exec, Identifier::fromUid(exec, name.get()));698 switch (resolution.type) {699 case Resolution::Type::NotFound:700 throwSyntaxError(exec, scope, makeString("Exported binding name '", String(name.get()), "' is not found."));701 return nullptr;702 703 case Resolution::Type::Error:704 throwSyntaxError(exec, scope, makeString("Exported binding name 'default' cannot be resolved by star export entries."));705 return nullptr;706 707 case Resolution::Type::Ambiguous:708 break;709 710 case Resolution::Type::Resolved:711 unambiguousNames.add(name);712 break;713 }714 }715 716 m_moduleNamespaceObject.set(vm, this, JSModuleNamespaceObject::create(exec, globalObject, globalObject->moduleNamespaceObjectStructure(), this, unambiguousNames));717 return m_moduleNamespaceObject.get();718 74 } 719 75 … … 747 103 // Even if we avoided duplicate exports in the parser, still ambiguous exports occur due to the star export (`export * from "mod"`). 748 104 // When we see this type of ambiguity for the indirect exports here, throw a syntax error. 749 for (const auto& pair : m_exportEntries) {105 for (const auto& pair : exportEntries()) { 750 106 const ExportEntry& exportEntry = pair.value; 751 107 if (exportEntry.type == JSModuleRecord::ExportEntry::Type::Indirect) { … … 774 130 // Instantiate namespace objects and initialize the bindings with them if required. 775 131 // And ensure that all the imports correctly resolved to unique bindings. 776 for (const auto& pair : m_importEntries) {132 for (const auto& pair : importEntries()) { 777 133 const ImportEntry& importEntry = pair.value; 778 JSModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest);134 AbstractModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest); 779 135 if (importEntry.isNamespace(vm)) { 780 136 JSModuleNamespaceObject* namespaceObject = importedModule->getModuleNamespace(exec); … … 808 164 // When creating the environment, we initialized all the slots with empty, it's ok for lexical values. 809 165 // But for "var" and "function", we should initialize it with undefined. They are contained in the declared variables. 810 for (const auto& variable : m_declaredVariables) {166 for (const auto& variable : declaredVariables()) { 811 167 SymbolTableEntry entry = symbolTable->get(variable.key.get()); 812 168 VarOffset offset = entry.varOffset(); … … 851 207 } 852 208 853 static String printableName(const RefPtr<UniquedStringImpl>& uid)854 {855 if (uid->isSymbol())856 return uid.get();857 return WTF::makeString("'", String(uid.get()), "'");858 }859 860 static String printableName(const Identifier& ident)861 {862 return printableName(ident.impl());863 }864 865 void JSModuleRecord::dump()866 {867 dataLog("\nAnalyzing ModuleRecord key(", printableName(m_moduleKey), ")\n");868 869 dataLog(" Dependencies: ", m_requestedModules.size(), " modules\n");870 for (const auto& moduleName : m_requestedModules)871 dataLog(" module(", printableName(moduleName), ")\n");872 873 dataLog(" Import: ", m_importEntries.size(), " entries\n");874 for (const auto& pair : m_importEntries) {875 const ImportEntry& importEntry = pair.value;876 dataLog(" import(", printableName(importEntry.importName), "), local(", printableName(importEntry.localName), "), module(", printableName(importEntry.moduleRequest), ")\n");877 }878 879 dataLog(" Export: ", m_exportEntries.size(), " entries\n");880 for (const auto& pair : m_exportEntries) {881 const ExportEntry& exportEntry = pair.value;882 switch (exportEntry.type) {883 case ExportEntry::Type::Local:884 dataLog(" [Local] ", "export(", printableName(exportEntry.exportName), "), local(", printableName(exportEntry.localName), ")\n");885 break;886 887 case ExportEntry::Type::Indirect:888 dataLog(" [Indirect] ", "export(", printableName(exportEntry.exportName), "), import(", printableName(exportEntry.importName), "), module(", printableName(exportEntry.moduleName), ")\n");889 break;890 }891 }892 for (const auto& moduleName : m_starExportEntries)893 dataLog(" [Star] module(", printableName(moduleName.get()), ")\n");894 }895 896 209 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/JSModuleRecord.h
r208985 r209123 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 26 26 #pragma once 27 27 28 #include "Identifier.h" 29 #include "JSDestructibleObject.h" 30 #include "SourceCode.h" 31 #include "VariableEnvironment.h" 32 #include <wtf/HashMap.h> 33 #include <wtf/ListHashSet.h> 34 #include <wtf/Optional.h> 28 #include "AbstractModuleRecord.h" 35 29 36 30 namespace JSC { 37 31 38 class JSModuleNamespaceObject;39 class JSModuleEnvironment;40 class JSMap;41 32 class ModuleProgramExecutable; 42 33 43 34 // Based on the Source Text Module Record 44 35 // http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records 45 class JSModuleRecord : public JSDestructibleObject{36 class JSModuleRecord : public AbstractModuleRecord { 46 37 friend class LLIntOffsetsExtractor; 47 38 public: 48 typedef JSDestructibleObject Base; 49 50 // https://tc39.github.io/ecma262/#sec-source-text-module-records 51 struct ExportEntry { 52 enum class Type { 53 Local, 54 Indirect 55 }; 56 57 static ExportEntry createLocal(const Identifier& exportName, const Identifier& localName); 58 static ExportEntry createIndirect(const Identifier& exportName, const Identifier& importName, const Identifier& moduleName); 59 60 Type type; 61 Identifier exportName; 62 Identifier moduleName; 63 Identifier importName; 64 Identifier localName; 65 }; 66 67 struct ImportEntry { 68 Identifier moduleRequest; 69 Identifier importName; 70 Identifier localName; 71 72 bool isNamespace(VM& vm) const 73 { 74 return importName == vm.propertyNames->timesIdentifier; 75 } 76 }; 77 78 typedef WTF::ListHashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> OrderedIdentifierSet; 79 typedef HashMap<RefPtr<UniquedStringImpl>, ImportEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> ImportEntries; 80 typedef HashMap<RefPtr<UniquedStringImpl>, ExportEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> ExportEntries; 39 typedef AbstractModuleRecord Base; 81 40 82 41 DECLARE_EXPORT_INFO; 83 84 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)85 {86 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());87 }88 89 static JSModuleRecord* create(ExecState* exec, VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)90 {91 JSModuleRecord* instance = new (NotNull, allocateCell<JSModuleRecord>(vm.heap)) JSModuleRecord(vm, structure, moduleKey, sourceCode, declaredVariables, lexicalVariables);92 instance->finishCreation(exec, vm);93 return instance;94 }95 96 void appendRequestedModule(const Identifier&);97 void addStarExportEntry(const Identifier&);98 void addImportEntry(const ImportEntry&);99 void addExportEntry(const ExportEntry&);100 101 std::optional<ImportEntry> tryGetImportEntry(UniquedStringImpl* localName);102 std::optional<ExportEntry> tryGetExportEntry(UniquedStringImpl* exportName);103 104 const SourceCode& sourceCode() const { return m_sourceCode; }105 const Identifier& moduleKey() const { return m_moduleKey; }106 const OrderedIdentifierSet& requestedModules() const { return m_requestedModules; }107 const ExportEntries& exportEntries() const { return m_exportEntries; }108 const ImportEntries& importEntries() const { return m_importEntries; }109 const OrderedIdentifierSet& starExportEntries() const { return m_starExportEntries; }110 111 const VariableEnvironment& declaredVariables() const { return m_declaredVariables; }112 const VariableEnvironment& lexicalVariables() const { return m_lexicalVariables; }113 114 void dump();115 42 116 43 JSModuleEnvironment* moduleEnvironment() … … 119 46 return m_moduleEnvironment.get(); 120 47 } 48 static Structure* createStructure(VM&, JSGlobalObject*, JSValue); 49 static JSModuleRecord* create(ExecState*, VM&, Structure*, const Identifier&, const SourceCode&, const VariableEnvironment&, const VariableEnvironment&); 121 50 122 51 void link(ExecState*); … … 125 54 ModuleProgramExecutable* moduleProgramExecutable() const { return m_moduleProgramExecutable.get(); } 126 55 127 struct Resolution {128 enum class Type { Resolved, NotFound, Ambiguous, Error };129 130 static Resolution notFound();131 static Resolution error();132 static Resolution ambiguous();133 134 Type type;135 JSModuleRecord* moduleRecord;136 Identifier localName;137 };138 139 Resolution resolveExport(ExecState*, const Identifier& exportName);140 Resolution resolveImport(ExecState*, const Identifier& localName);141 142 JSModuleRecord* hostResolveImportedModule(ExecState*, const Identifier& moduleName);143 144 56 private: 145 JSModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables) 146 : Base(vm, structure) 147 , m_moduleKey(moduleKey) 148 , m_sourceCode(sourceCode) 149 , m_declaredVariables(declaredVariables) 150 , m_lexicalVariables(lexicalVariables) 151 { 152 } 57 JSModuleRecord(VM&, Structure*, const Identifier&, const SourceCode&, const VariableEnvironment&, const VariableEnvironment&); 153 58 154 59 void finishCreation(ExecState*, VM&); 155 156 JSModuleNamespaceObject* getModuleNamespace(ExecState*);157 60 158 61 static void visitChildren(JSCell*, SlotVisitor&); … … 161 64 void instantiateDeclarations(ExecState*, ModuleProgramExecutable*); 162 65 163 struct ResolveQuery;164 static Resolution resolveExportImpl(ExecState*, const ResolveQuery&);165 std::optional<Resolution> tryGetCachedResolution(UniquedStringImpl* exportName);166 void cacheResolution(UniquedStringImpl* exportName, const Resolution&);167 168 // The loader resolves the given module name to the module key. The module key is the unique value to represent this module.169 Identifier m_moduleKey;170 171 SourceCode m_sourceCode;172 173 VariableEnvironment m_declaredVariables;174 VariableEnvironment m_lexicalVariables;175 176 // Currently, we don't keep the occurrence order of the import / export entries.177 // So, we does not guarantee the order of the errors.178 // e.g. The import declaration that occurr later than the another import declaration may179 // throw the error even if the former import declaration also has the invalid content.180 //181 // import ... // (1) this has some invalid content.182 // import ... // (2) this also has some invalid content.183 //184 // In the above case, (2) may throw the error earlier than (1)185 //186 // But, in all the cases, we will throw the syntax error. So except for the content of the syntax error,187 // there are no difference.188 189 // Map localName -> ImportEntry.190 ImportEntries m_importEntries;191 192 // Map exportName -> ExportEntry.193 ExportEntries m_exportEntries;194 195 // Save the occurrence order since resolveExport requires it.196 OrderedIdentifierSet m_starExportEntries;197 198 // Save the occurrence order since the module loader loads and runs the modules in this order.199 // http://www.ecma-international.org/ecma-262/6.0/#sec-moduleevaluation200 OrderedIdentifierSet m_requestedModules;201 202 WriteBarrier<JSMap> m_dependenciesMap;203 204 66 WriteBarrier<ModuleProgramExecutable> m_moduleProgramExecutable; 205 WriteBarrier<JSModuleEnvironment> m_moduleEnvironment;206 WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject;207 208 // We assume that all the JSModuleRecord are retained by JSModuleLoader's registry.209 // So here, we don't visit each object for GC. The resolution cache map caches the once210 // looked up correctly resolved resolution, since (1) we rarely looked up the non-resolved one,211 // and (2) if we cache all the attempts the size of the map becomes infinitely large.212 typedef HashMap<RefPtr<UniquedStringImpl>, Resolution, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> Resolutions;213 Resolutions m_resolutionCache;214 67 }; 215 68 -
trunk/Source/JavaScriptCore/runtime/JSScope.cpp
r209028 r209123 27 27 #include "JSScope.h" 28 28 29 #include "AbstractModuleRecord.h" 29 30 #include "Exception.h" 30 31 #include "JSGlobalObject.h" 31 32 #include "JSLexicalEnvironment.h" 32 33 #include "JSModuleEnvironment.h" 33 #include "JSModuleRecord.h"34 34 #include "JSWithScope.h" 35 35 #include "JSCInlines.h" … … 79 79 if (scope->type() == ModuleEnvironmentType) { 80 80 JSModuleEnvironment* moduleEnvironment = jsCast<JSModuleEnvironment*>(scope); 81 JSModuleRecord* moduleRecord = moduleEnvironment->moduleRecord();82 JSModuleRecord::Resolution resolution = moduleRecord->resolveImport(exec, ident);83 if (resolution.type == JSModuleRecord::Resolution::Type::Resolved) {84 JSModuleRecord* importedRecord = resolution.moduleRecord;81 AbstractModuleRecord* moduleRecord = moduleEnvironment->moduleRecord(); 82 AbstractModuleRecord::Resolution resolution = moduleRecord->resolveImport(exec, ident); 83 if (resolution.type == AbstractModuleRecord::Resolution::Type::Resolved) { 84 AbstractModuleRecord* importedRecord = resolution.moduleRecord; 85 85 JSModuleEnvironment* importedEnvironment = importedRecord->moduleEnvironment(); 86 86 SymbolTable* symbolTable = importedEnvironment->symbolTable(); … … 279 279 280 280 if (scope->isModuleScope()) { 281 JSModuleRecord* moduleRecord = jsCast<JSModuleEnvironment*>(scope)->moduleRecord();281 AbstractModuleRecord* moduleRecord = jsCast<JSModuleEnvironment*>(scope)->moduleRecord(); 282 282 for (const auto& pair : moduleRecord->importEntries()) 283 283 result.add(pair.key); -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r208637 r209123 73 73 #include "JSPropertyNameEnumerator.h" 74 74 #include "JSTemplateRegistryKey.h" 75 #include "JSWebAssembly.h" 75 76 #include "JSWithScope.h" 76 77 #include "LLIntData.h" … … 260 261 #if ENABLE(WEBASSEMBLY) 261 262 webAssemblyCodeBlockStructure.set(*this, WebAssemblyCodeBlock::createStructure(*this, 0, jsNull())); 263 webAssemblyFunctionCellStructure.set(*this, WebAssemblyFunctionCell::createStructure(*this, 0, jsNull())); 262 264 #endif 263 265 hashMapBucketSetStructure.set(*this, HashMapBucket<HashMapBucketDataKey>::createStructure(*this, 0, jsNull())); -
trunk/Source/JavaScriptCore/runtime/VM.h
r208953 r209123 311 311 #if ENABLE(WEBASSEMBLY) 312 312 Strong<Structure> webAssemblyExecutableStructure; 313 Strong<Structure> webAssemblyFunctionCellStructure; 313 314 #endif 314 315 Strong<Structure> moduleProgramExecutableStructure; -
trunk/Source/JavaScriptCore/wasm/JSWebAssembly.h
r207650 r209123 37 37 #include "js/WebAssemblyCompileErrorConstructor.h" 38 38 #include "js/WebAssemblyCompileErrorPrototype.h" 39 #include "js/WebAssemblyFunction.h" 40 #include "js/WebAssemblyFunctionCell.h" 39 41 #include "js/WebAssemblyInstanceConstructor.h" 40 42 #include "js/WebAssemblyInstancePrototype.h" … … 43 45 #include "js/WebAssemblyModuleConstructor.h" 44 46 #include "js/WebAssemblyModulePrototype.h" 47 #include "js/WebAssemblyModuleRecord.h" 45 48 #include "js/WebAssemblyPrototype.h" 46 49 #include "js/WebAssemblyRuntimeErrorConstructor.h" -
trunk/Source/JavaScriptCore/wasm/WasmFormat.h
r208401 r209123 31 31 #include "B3Type.h" 32 32 #include "CodeLocation.h" 33 #include "Identifier.h" 33 34 #include <wtf/Vector.h> 34 #include <wtf/text/WTFString.h>35 35 36 36 namespace JSC { … … 116 116 117 117 struct Import { 118 Stringmodule;119 Stringfield;118 Identifier module; 119 Identifier field; 120 120 External::Kind kind; 121 121 union { … … 136 136 137 137 struct Export { 138 Stringfield;138 Identifier field; 139 139 External::Kind kind; 140 140 union { 141 Signature* functionSignature;141 uint32_t functionIndex; 142 142 // FIXME implement Table https://bugs.webkit.org/show_bug.cgi?id=164135 143 143 // FIXME implement Memory https://bugs.webkit.org/show_bug.cgi?id=164134 … … 156 156 }; 157 157 158 struct FunctionCompilation;159 typedef Vector<std::unique_ptr<FunctionCompilation>> CompiledFunctions;160 161 158 struct UnlinkedCall { 162 159 CodeLocationCall callLocation; … … 170 167 }; 171 168 169 typedef Vector<std::unique_ptr<FunctionCompilation>> CompiledFunctions; 170 172 171 } } // namespace JSC::Wasm 173 172 -
trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp
r209083 r209123 29 29 #if ENABLE(WEBASSEMBLY) 30 30 31 #include "IdentifierInlines.h" 31 32 #include "WasmFormat.h" 32 33 #include "WasmMemory.h" … … 124 125 return false; \ 125 126 } \ 126 } break; 127 break; \ 128 } 127 129 FOR_EACH_WASM_SECTION(WASM_SECTION_PARSE) 128 130 #undef WASM_SECTION_PARSE … … 168 170 if (!parseInt7(type)) 169 171 return false; 170 if (type != -0x20) // Function type constant. 172 if (type != -0x20) // Function type constant. FIXME auto-generate from JSON file. 171 173 return false; 172 174 … … 222 224 223 225 for (uint32_t importNumber = 0; importNumber != importCount; ++importNumber) { 224 Import i ;226 Import imp; 225 227 uint32_t moduleLen; 226 228 uint32_t fieldLen; 227 229 if (!parseVarUInt32(moduleLen)) 228 230 return false; 229 if (!consumeUTF8String(i.module, moduleLen)) 230 return false; 231 String moduleString; 232 if (!consumeUTF8String(moduleString, moduleLen)) 233 return false; 234 imp.module = Identifier::fromString(m_vm, moduleString); 231 235 if (!parseVarUInt32(fieldLen)) 232 236 return false; 233 if (!consumeUTF8String(i.field, fieldLen)) 234 return false; 235 if (!parseExternalKind(i.kind)) 236 return false; 237 switch (i.kind) { 237 String fieldString; 238 if (!consumeUTF8String(fieldString, fieldLen)) 239 return false; 240 imp.field = Identifier::fromString(m_vm, fieldString); 241 if (!parseExternalKind(imp.kind)) 242 return false; 243 switch (imp.kind) { 238 244 case External::Function: { 239 245 uint32_t functionSignatureIndex; 240 246 if (!parseVarUInt32(functionSignatureIndex)) 241 247 return false; 242 if (functionSignatureIndex > m_module->signatures.size()) 243 return false; 244 i.functionSignature = &m_module->signatures[functionSignatureIndex]; 245 } break; 246 case External::Table: 248 if (functionSignatureIndex >= m_module->signatures.size()) 249 return false; 250 imp.functionSignature = &m_module->signatures[functionSignatureIndex]; 251 break; 252 } 253 case External::Table: { 247 254 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164135 248 255 break; 249 case External::Memory: 256 } 257 case External::Memory: { 250 258 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164134 251 259 break; 252 case External::Global: 260 } 261 case External::Global: { 253 262 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133 254 263 // In the MVP, only immutable global variables can be imported. 255 264 break; 256 265 } 257 258 m_module->imports.uncheckedAppend(i); 266 } 267 268 m_module->imports.uncheckedAppend(imp); 259 269 } 260 270 … … 278 288 return false; 279 289 280 m_module->functions.uncheckedAppend({ &m_module->signatures[typeNumber], 0, 0 }); 290 // The Code section fixes up start and end. 291 size_t start = 0; 292 size_t end = 0; 293 m_module->functions.uncheckedAppend({ &m_module->signatures[typeNumber], start, end }); 281 294 } 282 295 … … 340 353 341 354 for (uint32_t exportNumber = 0; exportNumber != exportCount; ++exportNumber) { 342 Export e ;355 Export exp; 343 356 uint32_t fieldLen; 344 357 if (!parseVarUInt32(fieldLen)) 345 358 return false; 346 if (!consumeUTF8String(e.field, fieldLen)) 347 return false; 348 if (!parseExternalKind(e.kind)) 349 return false; 350 switch (e.kind) { 359 String fieldString; 360 if (!consumeUTF8String(fieldString, fieldLen)) 361 return false; 362 exp.field = Identifier::fromString(m_vm, fieldString); 363 if (!parseExternalKind(exp.kind)) 364 return false; 365 switch (exp.kind) { 351 366 case External::Function: { 352 uint32_t functionSignatureIndex; 353 if (!parseVarUInt32(functionSignatureIndex)) 354 return false; 355 if (functionSignatureIndex >= m_module->signatures.size()) 356 return false; 357 e.functionSignature = &m_module->signatures[functionSignatureIndex]; 358 } break; 359 case External::Table: 367 if (!parseVarUInt32(exp.functionIndex)) 368 return false; 369 if (exp.functionIndex >= m_module->functions.size()) 370 return false; 371 break; 372 } 373 case External::Table: { 360 374 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164135 361 375 break; 362 case External::Memory: 376 } 377 case External::Memory: { 363 378 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164134 364 379 break; 365 case External::Global: 380 } 381 case External::Global: { 366 382 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133 367 383 // In the MVP, only immutable global variables can be exported. 368 384 break; 369 385 } 370 371 m_module->exports.uncheckedAppend(e); 386 } 387 388 m_module->exports.uncheckedAppend(exp); 372 389 } 373 390 -
trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h
r208401 r209123 40 40 static const unsigned magicNumber = 0xc; 41 41 42 ModuleParser( const uint8_t* sourceBuffer, size_t sourceLength)42 ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength) 43 43 : Parser(sourceBuffer, sourceLength) 44 , m_vm(vm) 44 45 { 45 46 } 46 ModuleParser( const Vector<uint8_t>& sourceBuffer)47 : Parser(sourceBuffer.data(), sourceBuffer.size())47 ModuleParser(VM* vm, const Vector<uint8_t>& sourceBuffer) 48 : ModuleParser(vm, sourceBuffer.data(), sourceBuffer.size()) 48 49 { 49 50 } … … 68 69 #undef WASM_SECTION_DECLARE_PARSER 69 70 71 VM* m_vm; 70 72 std::unique_ptr<ModuleInformation> m_module; 71 73 bool m_failed { true }; -
trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp
r208627 r209123 59 59 dataLogLn("Starting plan."); 60 60 { 61 ModuleParser moduleParser(m_ source, m_sourceLength);61 ModuleParser moduleParser(m_vm, m_source, m_sourceLength); 62 62 if (!moduleParser.parse()) { 63 63 if (verbose) -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
r207929 r209123 29 29 #if ENABLE(WEBASSEMBLY) 30 30 31 #include "AbstractModuleRecord.h" 31 32 #include "JSCInlines.h" 33 #include "JSModuleEnvironment.h" 32 34 #include "JSModuleNamespaceObject.h" 35 #include "JSWebAssemblyModule.h" 33 36 34 37 namespace JSC { 35 38 36 JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, Structure* structure, JS ModuleNamespaceObject* moduleNamespaceObject)39 JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, Structure* structure, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject) 37 40 { 38 41 auto* instance = new (NotNull, allocateCell<JSWebAssemblyInstance>(vm.heap)) JSWebAssemblyInstance(vm, structure); 39 instance->finishCreation(vm, module NamespaceObject);42 instance->finishCreation(vm, module, moduleNamespaceObject); 40 43 return instance; 41 44 } … … 51 54 } 52 55 53 void JSWebAssemblyInstance::finishCreation(VM& vm, JS ModuleNamespaceObject* moduleNamespaceObject)56 void JSWebAssemblyInstance::finishCreation(VM& vm, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject) 54 57 { 55 58 Base::finishCreation(vm); 59 m_module.set(vm, this, module); 56 60 m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject); 57 putDirectWithoutTransition(vm, Identifier::fromString(&vm, "exports"), m_moduleNamespaceObject.get(), None);61 // FIXME this should put the module namespace object onto the exports object, instead of moduleEnvironment in WebAssemblyInstanceConstructor. https://bugs.webkit.org/show_bug.cgi?id=165121 58 62 ASSERT(inherits(info())); 59 63 } … … 70 74 71 75 Base::visitChildren(thisObject, visitor); 76 visitor.append(&thisObject->m_module); 72 77 visitor.append(&thisObject->m_moduleNamespaceObject); 73 78 } -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h
r207929 r209123 32 32 33 33 namespace JSC { 34 34 35 35 class JSModuleNamespaceObject; 36 class JSWebAssemblyModule; 36 37 37 38 class JSWebAssemblyInstance : public JSDestructibleObject { … … 39 40 typedef JSDestructibleObject Base; 40 41 41 static JSWebAssemblyInstance* create(VM&, Structure*, JSModuleNamespaceObject*); 42 43 static JSWebAssemblyInstance* create(VM&, Structure*, JSWebAssemblyModule*, JSModuleNamespaceObject*); 42 44 static Structure* createStructure(VM&, JSGlobalObject*, JSValue); 43 45 44 46 DECLARE_INFO; 45 47 48 JSWebAssemblyModule* module() 49 { 50 ASSERT(m_module); 51 return m_module.get(); 52 } 53 46 54 protected: 47 55 JSWebAssemblyInstance(VM&, Structure*); 48 void finishCreation(VM&, JS ModuleNamespaceObject*);56 void finishCreation(VM&, JSWebAssemblyModule*, JSModuleNamespaceObject*); 49 57 static void destroy(JSCell*); 50 58 static void visitChildren(JSCell*, SlotVisitor&); 51 59 52 60 private: 61 WriteBarrier<JSWebAssemblyModule> m_module; 53 62 WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject; 54 63 }; -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp
r208401 r209123 36 36 namespace JSC { 37 37 38 JSWebAssemblyModule* JSWebAssemblyModule::create(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>& moduleInformation, Wasm::CompiledFunctions& compiledFunctions )38 JSWebAssemblyModule* JSWebAssemblyModule::create(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>& moduleInformation, Wasm::CompiledFunctions& compiledFunctions, SymbolTable* exportSymbolTable) 39 39 { 40 40 auto* instance = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap)) JSWebAssemblyModule(vm, structure, moduleInformation, compiledFunctions); 41 instance->finishCreation(vm );41 instance->finishCreation(vm, exportSymbolTable); 42 42 return instance; 43 43 } … … 55 55 } 56 56 57 void JSWebAssemblyModule::finishCreation(VM& vm )57 void JSWebAssemblyModule::finishCreation(VM& vm, SymbolTable* exportSymbolTable) 58 58 { 59 59 Base::finishCreation(vm); 60 60 ASSERT(inherits(info())); 61 m_exportSymbolTable.set(vm, this, exportSymbolTable); 61 62 } 62 63 … … 72 73 73 74 Base::visitChildren(thisObject, visitor); 75 visitor.append(&thisObject->m_exportSymbolTable); 74 76 } 75 77 -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h
r208401 r209123 34 34 namespace JSC { 35 35 36 class SymbolTable; 37 36 38 class JSWebAssemblyModule : public JSDestructibleObject { 37 39 public: 38 40 typedef JSDestructibleObject Base; 39 41 40 static JSWebAssemblyModule* create(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&, Wasm::CompiledFunctions& );42 static JSWebAssemblyModule* create(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&, Wasm::CompiledFunctions&, SymbolTable*); 41 43 static Structure* createStructure(VM&, JSGlobalObject*, JSValue); 42 44 43 45 DECLARE_INFO; 44 46 45 const Wasm::ModuleInformation* moduleInformation() const 46 { 47 return m_moduleInformation.get(); 48 } 47 const Wasm::ModuleInformation& moduleInformation() const { return *m_moduleInformation.get(); } 48 const Wasm::CompiledFunctions& compiledFunctions() const { return m_compiledFunctions; } 49 SymbolTable* exportSymbolTable() const { return m_exportSymbolTable.get(); } 49 50 50 51 protected: 51 52 JSWebAssemblyModule(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&, Wasm::CompiledFunctions&); 52 void finishCreation(VM& );53 void finishCreation(VM&, SymbolTable*); 53 54 static void destroy(JSCell*); 54 55 static void visitChildren(JSCell*, SlotVisitor&); … … 56 57 std::unique_ptr<Wasm::ModuleInformation> m_moduleInformation; 57 58 Wasm::CompiledFunctions m_compiledFunctions; 59 WriteBarrier<SymbolTable> m_exportSymbolTable; 58 60 }; 59 61 -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.h
r209122 r209123 28 28 #if ENABLE(WEBASSEMBLY) 29 29 30 #include "JSDestructibleObject.h" 31 #include "JSObject.h" 32 #include "WasmFormat.h" 30 #include "JSFunction.h" 31 #include <wtf/Noncopyable.h> 33 32 34 33 namespace JSC { 35 34 36 class JSWebAssemblyModule : public JSDestructibleObject { 35 class JSGlobalObject; 36 class WebAssemblyFunctionCell; 37 class WebAssemblyInstance; 38 39 namespace B3 { 40 class Compilation; 41 } 42 43 namespace Wasm { 44 struct Signature; 45 } 46 47 class CallableWebAssemblyFunction { 48 WTF_MAKE_NONCOPYABLE(CallableWebAssemblyFunction); 49 CallableWebAssemblyFunction() = delete; 50 37 51 public: 38 typedef JSDestructibleObject Base;52 CallableWebAssemblyFunction(CallableWebAssemblyFunction&&) = default; 39 53 40 static JSWebAssemblyModule* create(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&, Wasm::CompiledFunctions&); 54 const B3::Compilation* jsEntryPoint; 55 const Wasm::Signature* signature; 56 CallableWebAssemblyFunction(const B3::Compilation* jsEntryPoint, const Wasm::Signature* signature) 57 : jsEntryPoint(jsEntryPoint) 58 , signature(signature) 59 { 60 } 61 }; 62 63 class WebAssemblyFunction : public JSFunction { 64 public: 65 typedef JSFunction Base; 66 67 const static unsigned StructureFlags = Base::StructureFlags; 68 69 DECLARE_EXPORT_INFO; 70 71 JS_EXPORT_PRIVATE static WebAssemblyFunction* create(VM&, JSGlobalObject*, int, const String&, JSWebAssemblyInstance*, CallableWebAssemblyFunction&&); 41 72 static Structure* createStructure(VM&, JSGlobalObject*, JSValue); 42 73 43 DECLARE_INFO; 44 45 const Wasm::ModuleInformation* moduleInformation() const 46 { 47 return m_moduleInformation.get(); 48 } 74 const WebAssemblyFunctionCell* webAssemblyFunctionCell() const { return m_functionCell.get(); } 49 75 50 76 protected: 51 JSWebAssemblyModule(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&, Wasm::CompiledFunctions&);52 void finishCreation(VM&);53 static void destroy(JSCell*);54 77 static void visitChildren(JSCell*, SlotVisitor&); 78 79 void finishCreation(VM&, NativeExecutable*, int length, const String& name, JSWebAssemblyInstance*, WebAssemblyFunctionCell*); 80 55 81 private: 56 std::unique_ptr<Wasm::ModuleInformation> m_moduleInformation; 57 Wasm::CompiledFunctions m_compiledFunctions; 82 WebAssemblyFunction(VM&, JSGlobalObject*, Structure*); 83 84 WriteBarrier<JSWebAssemblyInstance> m_instance; 85 WriteBarrier<WebAssemblyFunctionCell> m_functionCell; 58 86 }; 59 87 -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionCell.cpp
r209122 r209123 24 24 */ 25 25 26 #pragma once 26 #include "config.h" 27 #include "WebAssemblyFunctionCell.h" 27 28 28 29 #if ENABLE(WEBASSEMBLY) 29 30 30 #include "JSDestructibleObject.h" 31 #include "JSObject.h" 31 #include "JSCInlines.h" 32 32 33 33 namespace JSC { 34 35 class JSModuleNamespaceObject;36 34 37 class JSWebAssemblyInstance : public JSDestructibleObject { 38 public: 39 typedef JSDestructibleObject Base; 35 const ClassInfo WebAssemblyFunctionCell::s_info = { "WebAssemblyFunctionCell", nullptr, nullptr, CREATE_METHOD_TABLE(WebAssemblyFunctionCell) }; 40 36 41 static JSWebAssemblyInstance* create(VM&, Structure*, JSModuleNamespaceObject*); 42 static Structure* createStructure(VM&, JSGlobalObject*, JSValue); 37 WebAssemblyFunctionCell* WebAssemblyFunctionCell::create(VM& vm, CallableWebAssemblyFunction&& callable) 38 { 39 WebAssemblyFunctionCell* nativeFunction = new (NotNull, allocateCell<WebAssemblyFunctionCell>(vm.heap)) WebAssemblyFunctionCell(vm, WTFMove(callable)); 40 nativeFunction->finishCreation(vm); 41 return nativeFunction; 42 } 43 43 44 DECLARE_INFO; 44 WebAssemblyFunctionCell::WebAssemblyFunctionCell(VM& vm, CallableWebAssemblyFunction&& callable) 45 : Base(vm, vm.webAssemblyFunctionCellStructure.get()) 46 , m_function(WTFMove(callable)) 47 { 48 } 45 49 46 protected: 47 JSWebAssemblyInstance(VM&, Structure*); 48 void finishCreation(VM&, JSModuleNamespaceObject*);49 static void destroy(JSCell*);50 static void visitChildren(JSCell*, SlotVisitor&); 50 void WebAssemblyFunctionCell::destroy(JSCell* cell) 51 { 52 WebAssemblyFunctionCell* nativeFunction = static_cast<WebAssemblyFunctionCell*>(cell); 53 nativeFunction->WebAssemblyFunctionCell::~WebAssemblyFunctionCell(); 54 } 51 55 52 private: 53 WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject; 54 }; 56 Structure* WebAssemblyFunctionCell::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 57 { 58 return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info()); 59 } 55 60 56 } // namespace JSC61 } 57 62 58 63 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionCell.h
r209122 r209123 28 28 #if ENABLE(WEBASSEMBLY) 29 29 30 #include "JS DestructibleObject.h"31 #include " JSObject.h"30 #include "JSCell.h" 31 #include "WebAssemblyFunction.h" 32 32 33 33 namespace JSC { 34 35 class JSModuleNamespaceObject;36 34 37 class JSWebAssemblyInstance : public JSDestructibleObject{35 class WebAssemblyFunctionCell : public JSCell { 38 36 public: 39 typedef JSDestructibleObject Base; 37 typedef JSCell Base; 38 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; 39 static const bool needsDestruction = true; 40 40 41 static JSWebAssemblyInstance* create(VM&, Structure*, JSModuleNamespaceObject*); 41 static WebAssemblyFunctionCell* create(VM&, CallableWebAssemblyFunction&&); 42 static void destroy(JSCell*); 42 43 static Structure* createStructure(VM&, JSGlobalObject*, JSValue); 43 44 44 45 DECLARE_INFO; 45 46 46 protected: 47 JSWebAssemblyInstance(VM&, Structure*); 48 void finishCreation(VM&, JSModuleNamespaceObject*); 49 static void destroy(JSCell*); 50 static void visitChildren(JSCell*, SlotVisitor&); 47 const CallableWebAssemblyFunction& function() const { return m_function; } 51 48 52 49 private: 53 WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject; 50 WebAssemblyFunctionCell(VM&, CallableWebAssemblyFunction&&); 51 52 CallableWebAssemblyFunction m_function; 54 53 }; 55 54 -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp
r209025 r209123 31 31 #include "FunctionPrototype.h" 32 32 #include "JSCInlines.h" 33 #include "JSModuleNamespaceObject.h" 34 #include "JSModuleRecord.h" 33 #include "JSModuleEnvironment.h" 35 34 #include "JSWebAssemblyInstance.h" 36 35 #include "JSWebAssemblyModule.h" 37 36 #include "WebAssemblyInstancePrototype.h" 37 #include "WebAssemblyModuleRecord.h" 38 38 39 39 #include "WebAssemblyInstanceConstructor.lut.h" 40 40 41 41 namespace JSC { 42 43 static const bool verbose = false; 42 44 43 45 const ClassInfo WebAssemblyInstanceConstructor::s_info = { "Function", &Base::s_info, &constructorTableWebAssemblyInstance, CREATE_METHOD_TABLE(WebAssemblyInstanceConstructor) }; … … 55 57 56 58 // If moduleObject is not a WebAssembly.Module instance, a TypeError is thrown. 57 JSWebAssemblyModule* module = jsDynamicCast<JSWebAssemblyModule*>(state->argument(0));58 if (! module)59 JSWebAssemblyModule* jsModule = jsDynamicCast<JSWebAssemblyModule*>(state->argument(0)); 60 if (!jsModule) 59 61 return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("first argument to WebAssembly.Instance must be a WebAssembly.Module"), defaultSourceAppender, runtimeTypeForValue(state->argument(0))))); 62 const Wasm::ModuleInformation& moduleInformation = jsModule->moduleInformation(); 60 63 61 64 // If the importObject parameter is not undefined and Type(importObject) is not Object, a TypeError is thrown. … … 66 69 67 70 // If the list of module.imports is not empty and Type(importObject) is not Object, a TypeError is thrown. 68 if (module ->moduleInformation()->imports.size() && !importObject)71 if (moduleInformation.imports.size() && !importObject) 69 72 return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("second argument to WebAssembly.Instance must be Object because the WebAssembly.Module has imports"), defaultSourceAppender, runtimeTypeForValue(importArgument)))); 70 73 71 // FIXME String things from https://bugs.webkit.org/show_bug.cgi?id=164023 72 // Let exports be a list of (string, JS value) pairs that is mapped from each external value e in instance.exports as follows: 73 IdentifierSet instanceExports; 74 for (const auto& name : instanceExports) { 75 // FIXME validate according to Module.Instance spec. 76 (void)name; 77 } 78 Identifier moduleKey; 74 Identifier moduleKey = Identifier::fromUid(PrivateName(PrivateName::Description, "WebAssemblyInstance")); 79 75 SourceCode sourceCode; 80 76 VariableEnvironment declaredVariables; 81 77 VariableEnvironment lexicalVariables; 82 auto* moduleRecord = JSModuleRecord::create(state, vm, globalObject->moduleRecordStructure(), moduleKey, sourceCode, declaredVariables, lexicalVariables); 83 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 84 auto* moduleNamespaceObject = JSModuleNamespaceObject::create(state, globalObject, globalObject->moduleNamespaceObjectStructure(), moduleRecord, instanceExports); 78 WebAssemblyModuleRecord* moduleRecord = WebAssemblyModuleRecord::create(state, vm, globalObject->webAssemblyModuleRecordStructure(), moduleKey, sourceCode, declaredVariables, lexicalVariables); 85 79 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 86 80 87 auto* structure = InternalFunction::createSubclassStructure(state, state->newTarget(), globalObject->WebAssemblyInstanceStructure());81 Structure* instanceStructure = InternalFunction::createSubclassStructure(state, state->newTarget(), globalObject->WebAssemblyInstanceStructure()); 88 82 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 89 83 90 return JSValue::encode(JSWebAssemblyInstance::create(vm, structure, moduleNamespaceObject)); 84 JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, instanceStructure, jsModule, moduleRecord->getModuleNamespace(state)); 85 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 86 87 moduleRecord->link(state, instance); 88 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 89 if (verbose) 90 moduleRecord->dump(); 91 // FIXME the following should be in JSWebAssemblyInstance instead of here. https://bugs.webkit.org/show_bug.cgi?id=165121 92 instance->putDirect(vm, Identifier::fromString(&vm, "exports"), JSValue(moduleRecord->moduleEnvironment()), None); 93 JSValue startResult = moduleRecord->evaluate(state); 94 UNUSED_PARAM(startResult); 95 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 96 97 return JSValue::encode(instance); 91 98 } 92 99 -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp
r208627 r209123 36 36 #include "JSWebAssemblyCompileError.h" 37 37 #include "JSWebAssemblyModule.h" 38 #include "SymbolTable.h" 38 39 #include "WasmPlan.h" 39 40 #include "WebAssemblyModulePrototype.h" 41 #include <wtf/StdLibExtras.h> 40 42 41 43 #include "WebAssemblyModuleConstructor.lut.h" … … 79 81 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 80 82 81 return JSValue::encode(JSWebAssemblyModule::create(vm, structure, plan.getModuleInformation(), plan.getCompiledFunctions())); 83 // The export symbol table is the same for all Instances of a Module. 84 SymbolTable* exportSymbolTable = SymbolTable::create(vm); 85 for (auto& exp : plan.getModuleInformation()->exports) { 86 auto offset = exportSymbolTable->takeNextScopeOffset(NoLockingNecessary); 87 exportSymbolTable->set(NoLockingNecessary, exp.field.impl(), SymbolTableEntry(VarOffset(offset))); 88 } 89 90 return JSValue::encode(JSWebAssemblyModule::create(vm, structure, plan.getModuleInformation(), plan.getCompiledFunctions(), exportSymbolTable)); 82 91 } 83 92 -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h
r209122 r209123 28 28 #if ENABLE(WEBASSEMBLY) 29 29 30 #include "JSDestructibleObject.h" 31 #include "JSObject.h" 32 #include "WasmFormat.h" 30 #include "AbstractModuleRecord.h" 33 31 34 32 namespace JSC { 35 33 36 class JSWebAssemblyModule : public JSDestructibleObject { 34 class JSWebAssemblyInstance; 35 36 // Based on the WebAssembly.Instance specification 37 // https://github.com/WebAssembly/design/blob/master/JS.md#webassemblyinstance-constructor 38 class WebAssemblyModuleRecord : public AbstractModuleRecord { 39 friend class LLIntOffsetsExtractor; 37 40 public: 38 typedef JSDestructibleObjectBase;41 typedef AbstractModuleRecord Base; 39 42 40 static JSWebAssemblyModule* create(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&, Wasm::CompiledFunctions&); 43 DECLARE_EXPORT_INFO; 44 41 45 static Structure* createStructure(VM&, JSGlobalObject*, JSValue); 46 static WebAssemblyModuleRecord* create(ExecState*, VM&, Structure*, const Identifier&, const SourceCode&, const VariableEnvironment&, const VariableEnvironment&); 42 47 43 DECLARE_INFO; 48 void link(ExecState*, JSWebAssemblyInstance*); 49 JS_EXPORT_PRIVATE JSValue evaluate(ExecState*); 44 50 45 const Wasm::ModuleInformation* moduleInformation() const 46 { 47 return m_moduleInformation.get(); 48 } 51 private: 52 WebAssemblyModuleRecord(VM&, Structure*, const Identifier&, const SourceCode&, const VariableEnvironment&, const VariableEnvironment&); 49 53 50 protected: 51 JSWebAssemblyModule(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&, Wasm::CompiledFunctions&); 52 void finishCreation(VM&); 54 void finishCreation(ExecState*, VM&); 53 55 static void destroy(JSCell*); 56 54 57 static void visitChildren(JSCell*, SlotVisitor&); 55 private: 56 std::unique_ptr<Wasm::ModuleInformation> m_moduleInformation; 57 Wasm::CompiledFunctions m_compiledFunctions; 58 59 WriteBarrier<JSWebAssemblyInstance> m_instance; 58 60 }; 59 61 -
trunk/Source/WTF/ChangeLog
r209120 r209123 1 2016-11-29 JF Bastien <jfbastien@apple.com> 2 3 WebAssembly JS API: improve Instance 4 https://bugs.webkit.org/show_bug.cgi?id=164757 5 6 Reviewed by Keith Miller. 7 8 * wtf/Expected.h: 9 (WTF::ExpectedDetail::destroy): silence a warning 10 1 11 2016-11-29 Commit Queue <commit-queue@webkit.org> 2 12 -
trunk/Source/WTF/wtf/Expected.h
r208985 r209123 76 76 static constexpr enum class ErrorTagType { } ErrorTag { }; 77 77 78 template<class T, std::enable_if_t<std::is_trivially_destructible<T>::value>* = nullptr> void destroy(T& t) { }78 template<class T, std::enable_if_t<std::is_trivially_destructible<T>::value>* = nullptr> void destroy(T&) { } 79 79 template<class T, std::enable_if_t<!std::is_trivially_destructible<T>::value && (std::is_class<T>::value || std::is_union<T>::value)>* = nullptr> void destroy(T& t) { t.~T(); } 80 80
Note: See TracChangeset
for help on using the changeset viewer.