Diff
Modified: releases/WebKitGTK/webkit-2.16/JSTests/ChangeLog (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/JSTests/ChangeLog 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/JSTests/ChangeLog 2017-02-27 13:44:03 UTC (rev 213049)
@@ -1,3 +1,40 @@
+2017-02-22 Yusuke Suzuki <[email protected]>
+
+ JSModuleNamespace object should have IC
+ https://bugs.webkit.org/show_bug.cgi?id=160590
+
+ Reviewed by Saam Barati.
+
+ * modules/module-assert-access-binding.js: Added.
+ * modules/module-assert-access-namespace.js: Added.
+ * modules/namespace-empty.js: Added.
+ (from.string_appeared_here.access):
+ (i.shouldThrow):
+ * stress/module-namespace-access-change.js: Added.
+ (shouldBe):
+ (access):
+ (import.string_appeared_here.then):
+ * stress/module-namespace-access-non-constant.js: Added.
+ (shouldBe):
+ (import.string_appeared_here.then):
+ * stress/module-namespace-access-poly.js: Added.
+ (shouldBe):
+ (access):
+ (import.string_appeared_here.then):
+ * stress/module-namespace-access-transitive-exports.js: Added.
+ (shouldBe):
+ (import.string_appeared_here.then):
+ * stress/module-namespace-access.js: Added.
+ (shouldBe):
+ (import.string_appeared_here.then):
+ * stress/resources/module-namespace-access-transitive-exports-2.js: Added.
+ (export.cocoa):
+ (export.change):
+ * stress/resources/module-namespace-access-transitive-exports.js: Added.
+ * stress/resources/module-namespace-access.js: Added.
+ (export.cocoa):
+ (export.change):
+
2017-02-20 Filip Pizlo <[email protected]>
The collector thread should only start when the mutator doesn't have heap access
Added: releases/WebKitGTK/webkit-2.16/JSTests/modules/module-assert-access-binding.js (0 => 213049)
--- releases/WebKitGTK/webkit-2.16/JSTests/modules/module-assert-access-binding.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/modules/module-assert-access-binding.js 2017-02-27 13:44:03 UTC (rev 213049)
@@ -0,0 +1,10 @@
+import {shouldBe} from "./resources/assert.js";
+
+let array = [];
+for (let i = 0; i < 4000000; i++) {
+ array.push(i);
+}
+
+for (let i = 0; i < 4000000; i++) {
+ shouldBe(array[i], i);
+}
Added: releases/WebKitGTK/webkit-2.16/JSTests/modules/module-assert-access-namespace.js (0 => 213049)
--- releases/WebKitGTK/webkit-2.16/JSTests/modules/module-assert-access-namespace.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/modules/module-assert-access-namespace.js 2017-02-27 13:44:03 UTC (rev 213049)
@@ -0,0 +1,10 @@
+import * as assert from "./resources/assert.js";
+
+let array = [];
+for (let i = 0; i < 4000000; i++) {
+ array.push(i);
+}
+
+for (let i = 0; i < 4000000; i++) {
+ assert.shouldBe(array[i], i);
+}
Added: releases/WebKitGTK/webkit-2.16/JSTests/modules/namespace-empty.js (0 => 213049)
--- releases/WebKitGTK/webkit-2.16/JSTests/modules/namespace-empty.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/modules/namespace-empty.js 2017-02-27 13:44:03 UTC (rev 213049)
@@ -0,0 +1,17 @@
+import * as ns from "./namespace-empty.js"
+import {shouldThrow} from "./resources/assert.js"
+
+function access(ns)
+{
+ return ns.test;
+}
+noInline(access);
+
+for (var i = 0; i < 1e3; ++i) {
+ shouldThrow(() => {
+ access(ns);
+ }, `ReferenceError: Cannot access uninitialized variable.`);
+}
+
+
+export let test = 42;
Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access-change.js (0 => 213049)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access-change.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access-change.js 2017-02-27 13:44:03 UTC (rev 213049)
@@ -0,0 +1,19 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+function access(namespace)
+{
+ return namespace.test;
+}
+noInline(access);
+
+import("./resources/module-namespace-access.js").then((ns) => {
+ for (var i = 0; i < 1e4; ++i)
+ shouldBe(access(ns), 42)
+ ns.change();
+ for (var i = 0; i < 1e4; ++i)
+ shouldBe(access(ns), 55)
+});
+drainMicrotasks();
Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access-non-constant.js (0 => 213049)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access-non-constant.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access-non-constant.js 2017-02-27 13:44:03 UTC (rev 213049)
@@ -0,0 +1,13 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+import("./resources/module-namespace-access.js").then((ns) => {
+ ns.change();
+ for (var i = 0; i < 1e6; ++i) {
+ shouldBe(ns.test, 55);
+ shouldBe(ns.cocoa(), 55);
+ }
+});
+drainMicrotasks();
Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access-poly.js (0 => 213049)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access-poly.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access-poly.js 2017-02-27 13:44:03 UTC (rev 213049)
@@ -0,0 +1,24 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+function access(ns)
+{
+ return ns.test;
+}
+noInline(access);
+
+import("./resources/module-namespace-access.js").then((ns) => {
+ for (var i = 0; i < 1e4; ++i) {
+ shouldBe(access(ns), 42);
+ }
+ let nonNS = { test: 50 };
+ let nonNS2 = { ok: 22, test: 52 };
+ for (var i = 0; i < 1e4; ++i) {
+ shouldBe(access(ns), 42);
+ shouldBe(access(nonNS), 50);
+ shouldBe(access(nonNS2), 52);
+ }
+});
+drainMicrotasks();
Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access-transitive-exports.js (0 => 213049)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access-transitive-exports.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access-transitive-exports.js 2017-02-27 13:44:03 UTC (rev 213049)
@@ -0,0 +1,12 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+import("./resources/module-namespace-access-transitive-exports.js").then((ns) => {
+ for (var i = 0; i < 1e6; ++i) {
+ shouldBe(ns.test, 42);
+ shouldBe(ns.cocoa(), 42);
+ }
+});
+drainMicrotasks();
Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access.js (0 => 213049)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/module-namespace-access.js 2017-02-27 13:44:03 UTC (rev 213049)
@@ -0,0 +1,12 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+import("./resources/module-namespace-access.js").then((ns) => {
+ for (var i = 0; i < 1e6; ++i) {
+ shouldBe(ns.test, 42);
+ shouldBe(ns.cocoa(), 42);
+ }
+});
+drainMicrotasks();
Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/resources/module-namespace-access-transitive-exports-2.js (0 => 213049)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/resources/module-namespace-access-transitive-exports-2.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/resources/module-namespace-access-transitive-exports-2.js 2017-02-27 13:44:03 UTC (rev 213049)
@@ -0,0 +1,10 @@
+export let test = 42;
+export function cocoa()
+{
+ return test;
+}
+
+export function change()
+{
+ test = 55;
+}
Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/resources/module-namespace-access-transitive-exports.js (0 => 213049)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/resources/module-namespace-access-transitive-exports.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/resources/module-namespace-access-transitive-exports.js 2017-02-27 13:44:03 UTC (rev 213049)
@@ -0,0 +1 @@
+export * from "./module-namespace-access-transitive-exports-2.js"
Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/resources/module-namespace-access.js (0 => 213049)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/resources/module-namespace-access.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/resources/module-namespace-access.js 2017-02-27 13:44:03 UTC (rev 213049)
@@ -0,0 +1,10 @@
+export let test = 42;
+export function cocoa()
+{
+ return test;
+}
+
+export function change()
+{
+ test = 55;
+}
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/CMakeLists.txt (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/CMakeLists.txt 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/CMakeLists.txt 2017-02-27 13:44:03 UTC (rev 213049)
@@ -228,6 +228,7 @@
bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp
bytecode/LazyOperandValueProfile.cpp
bytecode/MethodOfGettingAValueProfile.cpp
+ bytecode/ModuleNamespaceAccessCase.cpp
bytecode/ModuleProgramCodeBlock.cpp
bytecode/ObjectPropertyCondition.cpp
bytecode/ObjectPropertyConditionSet.cpp
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ChangeLog (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ChangeLog 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ChangeLog 2017-02-27 13:44:03 UTC (rev 213049)
@@ -1,3 +1,107 @@
+2017-02-22 Yusuke Suzuki <[email protected]>
+
+ JSModuleNamespace object should have IC
+ https://bugs.webkit.org/show_bug.cgi?id=160590
+
+ Reviewed by Saam Barati.
+
+ This patch optimizes accesses to module namespace objects.
+
+ 1. Cache the resolutions for module namespace objects.
+
+ When constructing the module namespace object, we already resolves all the exports.
+ The module namespace object caches this result and leverage it in the later access in
+ getOwnPropertySlot. This avoids resolving bindings through resolveExport.
+
+ 2. Introduce ModuleNamespaceLoad IC.
+
+ This patch adds new IC for module namespace objects. The mechanism is simple, getOwnPropertySlot
+ tells us about module namespace object resolution. The IC first checks whether the given object
+ is an expected module namespace object. If this check succeeds, we load the value from the module
+ environment.
+
+ 3. Introduce DFG/FTL optimization.
+
+ After exploiting module namespace object accesses in (2), DFG can recognize this in ByteCodeParser.
+ DFG will convert it to CheckCell with the namespace object and GetClosureVar from the cached environment.
+ At that time, we have a chance to fold it to the constant.
+
+ This optimization improves the performance of accessing to module namespace objects.
+
+ Before
+ $ time ../../WebKitBuild/module-ic-tot/Release/bin/jsc -m module-assert-access-namespace.js
+ ../../WebKitBuild/module-ic-tot/Release/bin/jsc -m 0.43s user 0.03s system 101% cpu 0.451 total
+ $ time ../../WebKitBuild/module-ic-tot/Release/bin/jsc -m module-assert-access-binding.js
+ ../../WebKitBuild/module-ic-tot/Release/bin/jsc -m 0.08s user 0.02s system 103% cpu 0.104 total
+
+ After
+ $ time ../../WebKitBuild/module-ic/Release/bin/jsc -m module-assert-access-namespace.js
+ ../../WebKitBuild/module-ic/Release/bin/jsc -m 0.11s user 0.01s system 106% cpu 0.109 total
+ $ time ../../WebKitBuild/module-ic/Release/bin/jsc -m module-assert-access-binding.js
+ ../../WebKitBuild/module-ic/Release/bin/jsc -m module-assert-access-binding.j 0.08s user 0.02s system 102% cpu 0.105 total
+
+ * CMakeLists.txt:
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * bytecode/AccessCase.cpp:
+ (JSC::AccessCase::create):
+ (JSC::AccessCase::guardedByStructureCheck):
+ (JSC::AccessCase::canReplace):
+ (JSC::AccessCase::visitWeak):
+ (JSC::AccessCase::generateWithGuard):
+ (JSC::AccessCase::generateImpl):
+ * bytecode/AccessCase.h:
+ * bytecode/GetByIdStatus.cpp:
+ (JSC::GetByIdStatus::GetByIdStatus):
+ (JSC::GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback):
+ (JSC::GetByIdStatus::makesCalls):
+ (JSC::GetByIdStatus::dump):
+ * bytecode/GetByIdStatus.h:
+ (JSC::GetByIdStatus::isModuleNamespace):
+ (JSC::GetByIdStatus::takesSlowPath):
+ (JSC::GetByIdStatus::moduleNamespaceObject):
+ (JSC::GetByIdStatus::moduleEnvironment):
+ (JSC::GetByIdStatus::scopeOffset):
+ * bytecode/ModuleNamespaceAccessCase.cpp: Added.
+ (JSC::ModuleNamespaceAccessCase::ModuleNamespaceAccessCase):
+ (JSC::ModuleNamespaceAccessCase::create):
+ (JSC::ModuleNamespaceAccessCase::~ModuleNamespaceAccessCase):
+ (JSC::ModuleNamespaceAccessCase::clone):
+ (JSC::ModuleNamespaceAccessCase::emit):
+ * bytecode/ModuleNamespaceAccessCase.h: Added.
+ (JSC::ModuleNamespaceAccessCase::moduleNamespaceObject):
+ (JSC::ModuleNamespaceAccessCase::moduleEnvironment):
+ (JSC::ModuleNamespaceAccessCase::scopeOffset):
+ * bytecode/PolymorphicAccess.cpp:
+ (WTF::printInternal):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleModuleNamespaceLoad):
+ (JSC::DFG::ByteCodeParser::handleGetById):
+ * jit/AssemblyHelpers.h:
+ (JSC::AssemblyHelpers::loadValue):
+ * jit/Repatch.cpp:
+ (JSC::tryCacheGetByID):
+ * runtime/AbstractModuleRecord.cpp:
+ (JSC::AbstractModuleRecord::getModuleNamespace):
+ * runtime/JSModuleNamespaceObject.cpp:
+ (JSC::JSModuleNamespaceObject::finishCreation):
+ (JSC::JSModuleNamespaceObject::visitChildren):
+ (JSC::getValue):
+ (JSC::JSModuleNamespaceObject::getOwnPropertySlot):
+ (JSC::JSModuleNamespaceObject::getOwnPropertyNames):
+ * runtime/JSModuleNamespaceObject.h:
+ (JSC::isJSModuleNamespaceObject):
+ (JSC::JSModuleNamespaceObject::create): Deleted.
+ (JSC::JSModuleNamespaceObject::createStructure): Deleted.
+ (JSC::JSModuleNamespaceObject::moduleRecord): Deleted.
+ * runtime/JSModuleRecord.h:
+ (JSC::JSModuleRecord::moduleEnvironment): Deleted.
+ * runtime/PropertySlot.h:
+ (JSC::PropertySlot::PropertySlot):
+ (JSC::PropertySlot::domJIT):
+ (JSC::PropertySlot::moduleNamespaceSlot):
+ (JSC::PropertySlot::setValueModuleNamespace):
+ (JSC::PropertySlot::setCacheableCustom):
+
2017-02-21 Mark Lam <[email protected]>
Add more missing exception checks detected by running marathon.js.
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2017-02-27 13:44:03 UTC (rev 213049)
@@ -2410,6 +2410,8 @@
FED94F2F171E3E2300BE77A4 /* Watchdog.h in Headers */ = {isa = PBXBuildFile; fileRef = FED94F2C171E3E2300BE77A4 /* Watchdog.h */; settings = {ATTRIBUTES = (Private, ); }; };
FEF040511AAE662D00BD28B0 /* CompareAndSwapTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */; };
FEFD6FC61D5E7992008F2F0B /* JSStringInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 321D9E4CFB67423A97F191A7 /* ModuleNamespaceAccessCase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 20ECB15EFC524624BC2F02D5 /* ModuleNamespaceAccessCase.cpp */; };
+ 9F63434577274FAFB9336C38 /* ModuleNamespaceAccessCase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CE978E385A8498199052153 /* ModuleNamespaceAccessCase.h */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -4976,6 +4978,8 @@
FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompareAndSwapTest.cpp; path = API/tests/CompareAndSwapTest.cpp; sourceTree = "<group>"; };
FEF040521AAEC4ED00BD28B0 /* CompareAndSwapTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompareAndSwapTest.h; path = API/tests/CompareAndSwapTest.h; sourceTree = "<group>"; };
FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringInlines.h; sourceTree = "<group>"; };
+ 20ECB15EFC524624BC2F02D5 /* ModuleNamespaceAccessCase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleNamespaceAccessCase.cpp; path = ModuleNamespaceAccessCase.cpp; sourceTree = "<group>"; };
+ 4CE978E385A8498199052153 /* ModuleNamespaceAccessCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ModuleNamespaceAccessCase.h; path = ModuleNamespaceAccessCase.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -7514,6 +7518,8 @@
0F426A461460CBAB00131F8F /* VirtualRegister.h */,
0F919D2215853CDE004A4E7D /* Watchpoint.cpp */,
0F919D2315853CDE004A4E7D /* Watchpoint.h */,
+ 20ECB15EFC524624BC2F02D5 /* ModuleNamespaceAccessCase.cpp */,
+ 4CE978E385A8498199052153 /* ModuleNamespaceAccessCase.h */,
);
path = bytecode;
sourceTree = "<group>";
@@ -9267,6 +9273,7 @@
86704B8812DBA33700A9FE7B /* YarrParser.h in Headers */,
86704B8A12DBA33700A9FE7B /* YarrPattern.h in Headers */,
86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */,
+ 9F63434577274FAFB9336C38 /* ModuleNamespaceAccessCase.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -10670,6 +10677,7 @@
86704B8612DBA33700A9FE7B /* YarrJIT.cpp in Sources */,
86704B8912DBA33700A9FE7B /* YarrPattern.cpp in Sources */,
86704B4212DB8A8100A9FE7B /* YarrSyntaxChecker.cpp in Sources */,
+ 321D9E4CFB67423A97F191A7 /* ModuleNamespaceAccessCase.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/AccessCase.cpp (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/AccessCase.cpp 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/AccessCase.cpp 2017-02-27 13:44:03 UTC (rev 213049)
@@ -37,7 +37,10 @@
#include "HeapInlines.h"
#include "IntrinsicGetterAccessCase.h"
#include "JSCJSValueInlines.h"
+#include "JSModuleEnvironment.h"
+#include "JSModuleNamespaceObject.h"
#include "LinkBuffer.h"
+#include "ModuleNamespaceAccessCase.h"
#include "PolymorphicAccess.h"
#include "ScopedArguments.h"
#include "ScratchRegisterAllocator.h"
@@ -65,6 +68,7 @@
case StringLength:
case DirectArgumentsLength:
case ScopedArgumentsLength:
+ case ModuleNamespaceLoad:
case Replace:
break;
default:
@@ -148,6 +152,7 @@
case StringLength:
case DirectArgumentsLength:
case ScopedArgumentsLength:
+ case ModuleNamespaceLoad:
return false;
default:
return true;
@@ -193,6 +198,13 @@
case DirectArgumentsLength:
case ScopedArgumentsLength:
return other.type() == type();
+ case ModuleNamespaceLoad: {
+ if (other.type() != type())
+ return false;
+ auto& thisCase = this->as<ModuleNamespaceAccessCase>();
+ auto& otherCase = this->as<ModuleNamespaceAccessCase>();
+ return thisCase.moduleNamespaceObject() == otherCase.moduleNamespaceObject();
+ }
default:
if (!guardedByStructureCheck() || !other.guardedByStructureCheck())
return false;
@@ -239,6 +251,12 @@
auto& intrinsic = this->as<IntrinsicGetterAccessCase>();
if (intrinsic.intrinsicFunction() && !Heap::isMarked(intrinsic.intrinsicFunction()))
return false;
+ } else if (type() == ModuleNamespaceLoad) {
+ auto& accessCase = this->as<ModuleNamespaceAccessCase>();
+ if (accessCase.moduleNamespaceObject() && !Heap::isMarked(accessCase.moduleNamespaceObject()))
+ return false;
+ if (accessCase.moduleEnvironment() && !Heap::isMarked(accessCase.moduleEnvironment()))
+ return false;
}
return true;
@@ -344,6 +362,11 @@
return;
}
+ case ModuleNamespaceLoad: {
+ this->as<ModuleNamespaceAccessCase>().emit(state, fallThrough);
+ return;
+ }
+
default: {
if (viaProxy()) {
fallThrough.append(
@@ -991,6 +1014,7 @@
case DirectArgumentsLength:
case ScopedArgumentsLength:
+ case ModuleNamespaceLoad:
// These need to be handled by generateWithGuard(), since the guard is part of the
// algorithm. We can be sure that nobody will call generate() directly for these since they
// are not guarded by structure checks.
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/AccessCase.h (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/AccessCase.h 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/AccessCase.h 2017-02-27 13:44:03 UTC (rev 213049)
@@ -95,7 +95,8 @@
ArrayLength,
StringLength,
DirectArgumentsLength,
- ScopedArgumentsLength
+ ScopedArgumentsLength,
+ ModuleNamespaceLoad,
};
enum State : uint8_t {
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/GetByIdStatus.cpp (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/GetByIdStatus.cpp 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/GetByIdStatus.cpp 2017-02-27 13:44:03 UTC (rev 213049)
@@ -34,6 +34,7 @@
#include "JSScope.h"
#include "LLIntData.h"
#include "LowLevelInterpreter.h"
+#include "ModuleNamespaceAccessCase.h"
#include "PolymorphicAccess.h"
#include "StructureStubInfo.h"
#include <wtf/ListDump.h>
@@ -147,6 +148,15 @@
#endif // ENABLE(DFG_JIT)
#if ENABLE(JIT)
+GetByIdStatus::GetByIdStatus(const ModuleNamespaceAccessCase& accessCase)
+ : m_state(ModuleNamespace)
+ , m_wasSeenInJIT(true)
+ , m_moduleNamespaceObject(accessCase.moduleNamespaceObject())
+ , m_moduleEnvironment(accessCase.moduleEnvironment())
+ , m_scopeOffset(accessCase.scopeOffset())
+{
+}
+
GetByIdStatus GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback(
const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, UniquedStringImpl* uid,
CallLinkStatus::ExitSiteData callExitSiteData)
@@ -195,6 +205,16 @@
}
case CacheType::Stub: {
+ if (list->size() == 1) {
+ const AccessCase& access = list->at(0);
+ switch (access.type()) {
+ case AccessCase::ModuleNamespaceLoad:
+ return GetByIdStatus(access.as<ModuleNamespaceAccessCase>());
+ default:
+ break;
+ }
+ }
+
for (unsigned listIndex = 0; listIndex < list->size(); ++listIndex) {
const AccessCase& access = list->at(listIndex);
if (access.viaProxy())
@@ -376,6 +396,7 @@
case NoInformation:
case TakesSlowPath:
case Custom:
+ case ModuleNamespace:
return false;
case Simple:
for (unsigned i = m_variants.size(); i--;) {
@@ -420,6 +441,9 @@
case Custom:
out.print("Custom");
break;
+ case ModuleNamespace:
+ out.print("ModuleNamespace");
+ break;
case TakesSlowPath:
out.print("TakesSlowPath");
break;
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/GetByIdStatus.h (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/GetByIdStatus.h 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/GetByIdStatus.h 2017-02-27 13:44:03 UTC (rev 213049)
@@ -30,10 +30,15 @@
#include "ConcurrentJSLock.h"
#include "ExitingJITType.h"
#include "GetByIdVariant.h"
+#include "ScopeOffset.h"
namespace JSC {
+class AccessCase;
class CodeBlock;
+class JSModuleEnvironment;
+class JSModuleNamespaceObject;
+class ModuleNamespaceAccessCase;
class StructureStubInfo;
typedef HashMap<CodeOrigin, StructureStubInfo*, CodeOriginApproximateHash> StubInfoMap;
@@ -41,12 +46,19 @@
class GetByIdStatus {
public:
enum State {
- NoInformation, // It's uncached so we have no information.
- Simple, // It's cached for a simple access to a known object property with
- // a possible structure chain and a possible specific value.
- Custom, // It's cached for a custom accessor with a possible structure chain.
- TakesSlowPath, // It's known to often take slow path.
- MakesCalls // It's known to take paths that make calls.
+ // It's uncached so we have no information.
+ NoInformation,
+ // It's cached for a simple access to a known object property with
+ // a possible structure chain and a possible specific value.
+ Simple,
+ // It's cached for a custom accessor with a possible structure chain.
+ Custom,
+ // It's cached for an access to a module namespace object's binding.
+ ModuleNamespace,
+ // It's known to often take slow path.
+ TakesSlowPath,
+ // It's known to take paths that make calls.
+ MakesCalls,
};
GetByIdStatus()
@@ -59,6 +71,7 @@
{
ASSERT(state == NoInformation || state == TakesSlowPath || state == MakesCalls);
}
+
GetByIdStatus(
State state, bool wasSeenInJIT, const GetByIdVariant& variant = GetByIdVariant())
@@ -84,6 +97,7 @@
bool operator!() const { return !isSet(); }
bool isSimple() const { return m_state == Simple; }
bool isCustom() const { return m_state == Custom; }
+ bool isModuleNamespace() const { return m_state == ModuleNamespace; }
size_t numVariants() const { return m_variants.size(); }
const Vector<GetByIdVariant, 1>& variants() const { return m_variants; }
@@ -90,7 +104,7 @@
const GetByIdVariant& at(size_t index) const { return m_variants[index]; }
const GetByIdVariant& operator[](size_t index) const { return at(index); }
- bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls || m_state == Custom; }
+ bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls || m_state == Custom || m_state == ModuleNamespace; }
bool makesCalls() const;
bool wasSeenInJIT() const { return m_wasSeenInJIT; }
@@ -97,6 +111,10 @@
// Attempts to reduce the set of variants to fit the given structure set. This may be approximate.
void filter(const StructureSet&);
+
+ JSModuleNamespaceObject* moduleNamespaceObject() const { return m_moduleNamespaceObject; }
+ JSModuleEnvironment* moduleEnvironment() const { return m_moduleEnvironment; }
+ ScopeOffset scopeOffset() const { return m_scopeOffset; }
void dump(PrintStream&) const;
@@ -105,6 +123,7 @@
static bool hasExitSite(const ConcurrentJSLocker&, CodeBlock*, unsigned bytecodeIndex);
#endif
#if ENABLE(JIT)
+ GetByIdStatus(const ModuleNamespaceAccessCase&);
static GetByIdStatus computeForStubInfoWithoutExitSiteFeedback(
const ConcurrentJSLocker&, CodeBlock* profiledBlock, StructureStubInfo*,
UniquedStringImpl* uid, CallLinkStatus::ExitSiteData);
@@ -116,6 +135,9 @@
State m_state;
Vector<GetByIdVariant, 1> m_variants;
bool m_wasSeenInJIT;
+ JSModuleNamespaceObject* m_moduleNamespaceObject { nullptr };
+ JSModuleEnvironment* m_moduleEnvironment { nullptr };
+ ScopeOffset m_scopeOffset { };
};
} // namespace JSC
Added: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/ModuleNamespaceAccessCase.cpp (0 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/ModuleNamespaceAccessCase.cpp (rev 0)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/ModuleNamespaceAccessCase.cpp 2017-02-27 13:44:03 UTC (rev 213049)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <[email protected]>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ModuleNamespaceAccessCase.h"
+
+#if ENABLE(JIT)
+
+#include "CCallHelpers.h"
+#include "HeapInlines.h"
+#include "JSModuleEnvironment.h"
+#include "JSModuleNamespaceObject.h"
+#include "PolymorphicAccess.h"
+#include "StructureStubInfo.h"
+
+namespace JSC {
+
+ModuleNamespaceAccessCase::ModuleNamespaceAccessCase(VM& vm, JSCell* owner, JSModuleNamespaceObject* moduleNamespaceObject, JSModuleEnvironment* moduleEnvironment, ScopeOffset scopeOffset)
+ : Base(vm, owner, ModuleNamespaceLoad, invalidOffset, nullptr, ObjectPropertyConditionSet())
+ , m_scopeOffset(scopeOffset)
+{
+ m_moduleNamespaceObject.set(vm, owner, moduleNamespaceObject);
+ m_moduleEnvironment.set(vm, owner, moduleEnvironment);
+}
+
+std::unique_ptr<AccessCase> ModuleNamespaceAccessCase::create(VM& vm, JSCell* owner, JSModuleNamespaceObject* moduleNamespaceObject, JSModuleEnvironment* moduleEnvironment, ScopeOffset scopeOffset)
+{
+ return std::unique_ptr<AccessCase>(new ModuleNamespaceAccessCase(vm, owner, moduleNamespaceObject, moduleEnvironment, scopeOffset));
+}
+
+ModuleNamespaceAccessCase::~ModuleNamespaceAccessCase()
+{
+}
+
+std::unique_ptr<AccessCase> ModuleNamespaceAccessCase::clone() const
+{
+ std::unique_ptr<ModuleNamespaceAccessCase> result(new ModuleNamespaceAccessCase(*this));
+ result->resetState();
+ return WTFMove(result);
+}
+
+void ModuleNamespaceAccessCase::emit(AccessGenerationState& state, MacroAssembler::JumpList& fallThrough)
+{
+ CCallHelpers& jit = *state.jit;
+ JSValueRegs valueRegs = state.valueRegs;
+ GPRReg baseGPR = state.baseGPR;
+
+ fallThrough.append(
+ jit.branchPtr(
+ CCallHelpers::NotEqual,
+ baseGPR,
+ CCallHelpers::TrustedImmPtr(m_moduleNamespaceObject.get())));
+
+ jit.loadValue(&m_moduleEnvironment->variableAt(m_scopeOffset), valueRegs);
+ state.failAndIgnore.append(jit.branchIfEmpty(valueRegs));
+ state.succeed();
+}
+
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
Added: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/ModuleNamespaceAccessCase.h (0 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/ModuleNamespaceAccessCase.h (rev 0)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/ModuleNamespaceAccessCase.h 2017-02-27 13:44:03 UTC (rev 213049)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <[email protected]>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(JIT)
+
+#include "AccessCase.h"
+
+namespace JSC {
+
+class JSModuleEnvironment;
+class JSModuleNamespaceObject;
+
+class ModuleNamespaceAccessCase : public AccessCase {
+public:
+ using Base = AccessCase;
+ friend class AccessCase;
+
+ JSModuleNamespaceObject* moduleNamespaceObject() const { return m_moduleNamespaceObject.get(); }
+ JSModuleEnvironment* moduleEnvironment() const { return m_moduleEnvironment.get(); }
+ ScopeOffset scopeOffset() const { return m_scopeOffset; }
+
+ static std::unique_ptr<AccessCase> create(VM&, JSCell* owner, JSModuleNamespaceObject*, JSModuleEnvironment*, ScopeOffset);
+
+ std::unique_ptr<AccessCase> clone() const override;
+
+ void emit(AccessGenerationState&, MacroAssembler::JumpList& fallThrough);
+
+ ~ModuleNamespaceAccessCase();
+
+private:
+ ModuleNamespaceAccessCase(VM&, JSCell* owner, JSModuleNamespaceObject*, JSModuleEnvironment*, ScopeOffset);
+
+ WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject;
+ WriteBarrier<JSModuleEnvironment> m_moduleEnvironment;
+ ScopeOffset m_scopeOffset;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp 2017-02-27 13:44:03 UTC (rev 213049)
@@ -645,6 +645,9 @@
case AccessCase::ScopedArgumentsLength:
out.print("ScopedArgumentsLength");
return;
+ case AccessCase::ModuleNamespaceLoad:
+ out.print("ModuleNamespaceLoad");
+ return;
}
RELEASE_ASSERT_NOT_REACHED();
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-02-27 13:44:03 UTC (rev 213049)
@@ -46,6 +46,7 @@
#include "Heap.h"
#include "JSCInlines.h"
#include "JSModuleEnvironment.h"
+#include "JSModuleNamespaceObject.h"
#include "NumberConstructor.h"
#include "ObjectConstructor.h"
#include "PreciseJumpTargets.h"
@@ -223,6 +224,7 @@
Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, const InferredType::Descriptor&, Node* value);
Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, const InferredType::Descriptor&, NodeType = GetByOffset);
bool handleDOMJITGetter(int resultOperand, const GetByIdVariant&, Node* thisNode, unsigned identifierNumber, SpeculatedType prediction);
+ bool handleModuleNamespaceLoad(int resultOperand, SpeculatedType, Node* base, GetByIdStatus);
// Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not
// check the validity of the condition, but it may return a null one if it encounters a contradiction.
@@ -2844,6 +2846,34 @@
return true;
}
+bool ByteCodeParser::handleModuleNamespaceLoad(int resultOperand, SpeculatedType prediction, Node* base, GetByIdStatus getById)
+{
+ if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
+ return false;
+ addToGraph(CheckCell, OpInfo(m_graph.freeze(getById.moduleNamespaceObject())), Edge(base, CellUse));
+
+ // Ideally we wouldn't have to do this Phantom. But:
+ //
+ // For the constant case: we must do it because otherwise we would have no way of knowing
+ // that the scope is live at OSR here.
+ //
+ // For the non-constant case: GetClosureVar could be DCE'd, but baseline's implementation
+ // won't be able to handle an Undefined scope.
+ addToGraph(Phantom, base);
+
+ // Constant folding in the bytecode parser is important for performance. This may not
+ // have executed yet. If it hasn't, then we won't have a prediction. Lacking a
+ // prediction, we'd otherwise think that it has to exit. Then when it did execute, we
+ // would recompile. But if we can fold it here, we avoid the exit.
+ m_graph.freeze(getById.moduleEnvironment());
+ if (JSValue value = m_graph.tryGetConstantClosureVar(getById.moduleEnvironment(), getById.scopeOffset())) {
+ set(VirtualRegister(resultOperand), weakJSConstant(value));
+ return true;
+ }
+ set(VirtualRegister(resultOperand), addToGraph(GetClosureVar, OpInfo(getById.scopeOffset().offset()), OpInfo(prediction), weakJSConstant(getById.moduleEnvironment())));
+ return true;
+}
+
template<typename ChecksFunctor>
bool ByteCodeParser::handleTypedArrayConstructor(
int resultOperand, InternalFunction* function, int registerOffset,
@@ -3438,6 +3468,14 @@
else
getById = TryGetById;
+ if (getById != TryGetById && getByIdStatus.isModuleNamespace()) {
+ if (handleModuleNamespaceLoad(destinationOperand, prediction, base, getByIdStatus)) {
+ if (m_graph.compilation())
+ m_graph.compilation()->noticeInlinedGetById();
+ return;
+ }
+ }
+
// Special path for custom accessors since custom's offset does not have any meanings.
// So, this is completely different from Simple one. But we have a chance to optimize it when we use DOMJIT.
if (Options::useDOMJIT() && getByIdStatus.isCustom()) {
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/AssemblyHelpers.h (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/AssemblyHelpers.h 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/AssemblyHelpers.h 2017-02-27 13:44:03 UTC (rev 213049)
@@ -158,6 +158,16 @@
}
#endif
}
+
+ void loadValue(void* address, JSValueRegs regs)
+ {
+#if USE(JSVALUE64)
+ load64(address, regs.gpr());
+#else
+ load32(bitwise_cast<void*>(bitwise_cast<uintptr_t>(address) + PayloadOffset), regs.payloadGPR());
+ load32(bitwise_cast<void*>(bitwise_cast<uintptr_t>(address) + TagOffset), regs.tagGPR());
+#endif
+ }
// Note that this clobbers offset.
void loadProperty(GPRReg object, GPRReg offset, JSValueRegs result);
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/Repatch.cpp (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/Repatch.cpp 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/Repatch.cpp 2017-02-27 13:44:03 UTC (rev 213049)
@@ -46,8 +46,10 @@
#include "JIT.h"
#include "JITInlines.h"
#include "JSCInlines.h"
+#include "JSModuleNamespaceObject.h"
#include "JSWebAssembly.h"
#include "LinkBuffer.h"
+#include "ModuleNamespaceAccessCase.h"
#include "PolymorphicAccess.h"
#include "ScopedArguments.h"
#include "ScratchRegisterAllocator.h"
@@ -192,6 +194,11 @@
newCase = AccessCase::create(vm, codeBlock, AccessCase::ScopedArgumentsLength);
}
}
+
+ if (!propertyName.isSymbol() && isJSModuleNamespaceObject(baseValue) && !slot.isUnset()) {
+ if (auto moduleNamespaceSlot = slot.moduleNamespaceSlot())
+ newCase = ModuleNamespaceAccessCase::create(vm, codeBlock, jsCast<JSModuleNamespaceObject*>(baseValue), moduleNamespaceSlot->environment, ScopeOffset(moduleNamespaceSlot->scopeOffset));
+ }
if (!newCase) {
if (!slot.isCacheable() && !slot.isUnset())
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/AbstractModuleRecord.cpp (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/AbstractModuleRecord.cpp 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/AbstractModuleRecord.cpp 2017-02-27 13:44:03 UTC (rev 213049)
@@ -697,9 +697,10 @@
IdentifierSet exportedNames;
getExportedNames(exec, this, exportedNames);
- IdentifierSet unambiguousNames;
+ Vector<std::pair<Identifier, Resolution>> resolutions;
for (auto& name : exportedNames) {
- const AbstractModuleRecord::Resolution resolution = resolveExport(exec, Identifier::fromUid(exec, name.get()));
+ Identifier ident = Identifier::fromUid(exec, name.get());
+ const Resolution resolution = resolveExport(exec, ident);
switch (resolution.type) {
case Resolution::Type::NotFound:
throwSyntaxError(exec, scope, makeString("Exported binding name '", String(name.get()), "' is not found."));
@@ -713,12 +714,12 @@
break;
case Resolution::Type::Resolved:
- unambiguousNames.add(name);
+ resolutions.append({ WTFMove(ident), resolution });
break;
}
}
- m_moduleNamespaceObject.set(vm, this, JSModuleNamespaceObject::create(exec, globalObject, globalObject->moduleNamespaceObjectStructure(), this, unambiguousNames));
+ m_moduleNamespaceObject.set(vm, this, JSModuleNamespaceObject::create(exec, globalObject, globalObject->moduleNamespaceObjectStructure(), this, WTFMove(resolutions)));
return m_moduleNamespaceObject.get();
}
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSModuleNamespaceObject.cpp (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSModuleNamespaceObject.cpp 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSModuleNamespaceObject.cpp 2017-02-27 13:44:03 UTC (rev 213049)
@@ -41,7 +41,7 @@
{
}
-void JSModuleNamespaceObject::finishCreation(ExecState* exec, JSGlobalObject*, AbstractModuleRecord* moduleRecord, const IdentifierSet& exports)
+void JSModuleNamespaceObject::finishCreation(ExecState* exec, JSGlobalObject*, AbstractModuleRecord* moduleRecord, Vector<std::pair<Identifier, AbstractModuleRecord::Resolution>>&& resolutions)
{
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
@@ -54,17 +54,25 @@
// The list is ordered as if an Array of those String values had been sorted using Array.prototype.sort using SortCompare as comparefn.
//
// Sort the exported names by the code point order.
- Vector<UniquedStringImpl*> temporaryVector(exports.size(), nullptr);
- std::transform(exports.begin(), exports.end(), temporaryVector.begin(), [](const RefPtr<WTF::UniquedStringImpl>& ref) {
- return ref.get();
+ std::sort(resolutions.begin(), resolutions.end(), [] (const auto& lhs, const auto& rhs) {
+ return codePointCompare(lhs.first.impl(), rhs.first.impl()) < 0;
});
- std::sort(temporaryVector.begin(), temporaryVector.end(), [] (UniquedStringImpl* lhs, UniquedStringImpl* rhs) {
- return codePointCompare(lhs, rhs) < 0;
- });
- for (auto* identifier : temporaryVector)
- m_exports.add(identifier);
m_moduleRecord.set(vm, this, moduleRecord);
+ {
+ unsigned moduleRecordOffset = 0;
+ m_names.reserveCapacity(resolutions.size());
+ for (const auto& pair : resolutions) {
+ moduleRecordAt(moduleRecordOffset).set(vm, this, pair.second.moduleRecord);
+ m_names.append(pair.first);
+ m_exports.add(pair.first.impl(), ExportEntry {
+ pair.second.localName,
+ moduleRecordOffset
+ });
+ ++moduleRecordOffset;
+ }
+ }
+
putDirect(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Module"), DontEnum | DontDelete | ReadOnly);
// http://www.ecma-international.org/ecma-262/6.0/#sec-module-namespace-exotic-objects-getprototypeof
@@ -87,8 +95,24 @@
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
visitor.append(thisObject->m_moduleRecord);
+ for (unsigned i = 0; i < thisObject->m_names.size(); ++i)
+ visitor.appendHidden(thisObject->moduleRecordAt(i));
}
+static JSValue getValue(JSModuleEnvironment* environment, PropertyName localName, ScopeOffset& scopeOffset)
+{
+ SymbolTable* symbolTable = environment->symbolTable();
+ {
+ ConcurrentJSLocker locker(symbolTable->m_lock);
+ auto iter = symbolTable->find(locker, localName.uid());
+ ASSERT(iter != symbolTable->end(locker));
+ SymbolTableEntry& entry = iter->value;
+ ASSERT(!entry.isNull());
+ scopeOffset = entry.scopeOffset();
+ }
+ return environment->variableAt(scopeOffset).get();
+}
+
bool JSModuleNamespaceObject::getOwnPropertySlot(JSObject* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
{
VM& vm = exec->vm();
@@ -104,31 +128,19 @@
if (propertyName.isSymbol())
return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
- // FIXME: Add IC for module namespace object.
- // https://bugs.webkit.org/show_bug.cgi?id=160590
- slot.disableCaching();
slot.setIsTaintedByOpaqueObject();
- if (!thisObject->m_exports.contains(propertyName.uid()))
+
+ auto iterator = thisObject->m_exports.find(propertyName.uid());
+ if (iterator == thisObject->m_exports.end())
return false;
+ ExportEntry& exportEntry = iterator->value;
switch (slot.internalMethodType()) {
- case PropertySlot::InternalMethodType::Get:
- case PropertySlot::InternalMethodType::GetOwnProperty: {
- AbstractModuleRecord* moduleRecord = thisObject->moduleRecord();
-
- AbstractModuleRecord::Resolution resolution = moduleRecord->resolveExport(exec, Identifier::fromUid(exec, propertyName.uid()));
- ASSERT(resolution.type != AbstractModuleRecord::Resolution::Type::NotFound && resolution.type != AbstractModuleRecord::Resolution::Type::Ambiguous);
-
- AbstractModuleRecord* targetModule = resolution.moduleRecord;
- JSModuleEnvironment* targetEnvironment = targetModule->moduleEnvironment();
-
- PropertySlot trampolineSlot(targetEnvironment, PropertySlot::InternalMethodType::Get);
- bool found = targetEnvironment->methodTable(vm)->getOwnPropertySlot(targetEnvironment, exec, resolution.localName, trampolineSlot);
- ASSERT_UNUSED(found, found);
-
- JSValue value = trampolineSlot.getValue(exec, propertyName);
- ASSERT(!scope.exception());
-
+ case PropertySlot::InternalMethodType::GetOwnProperty:
+ case PropertySlot::InternalMethodType::Get: {
+ JSModuleEnvironment* environment = thisObject->moduleRecordAt(exportEntry.moduleRecordOffset)->moduleEnvironment();
+ ScopeOffset scopeOffset;
+ JSValue value = getValue(environment, exportEntry.localName, scopeOffset);
// If the value is filled with TDZ value, throw a reference error.
if (!value) {
throwVMError(exec, scope, createTDZError(exec));
@@ -135,9 +147,10 @@
return false;
}
- slot.setValue(thisObject, DontDelete, value);
+ slot.setValueModuleNamespace(thisObject, DontDelete, value, environment, scopeOffset);
return true;
}
+
case PropertySlot::InternalMethodType::HasProperty: {
// Do not perform [[Get]] for [[HasProperty]].
// [[Get]] / [[GetOwnProperty]] onto namespace object could throw an error while [[HasProperty]] just returns true here.
@@ -189,8 +202,8 @@
{
// http://www.ecma-international.org/ecma-262/6.0/#sec-module-namespace-exotic-objects-ownpropertykeys
JSModuleNamespaceObject* thisObject = jsCast<JSModuleNamespaceObject*>(cell);
- for (const auto& name : thisObject->m_exports)
- propertyNames.add(name.get());
+ for (const auto& name : thisObject->m_names)
+ propertyNames.add(name.impl());
return JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
}
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSModuleNamespaceObject.h (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSModuleNamespaceObject.h 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSModuleNamespaceObject.h 2017-02-27 13:44:03 UTC (rev 213049)
@@ -25,22 +25,25 @@
#pragma once
+#include "AbstractModuleRecord.h"
#include "JSDestructibleObject.h"
-#include <wtf/ListHashSet.h>
+#include "ScopeOffset.h"
namespace JSC {
-class AbstractModuleRecord;
-
-class JSModuleNamespaceObject : public JSDestructibleObject {
+class JSModuleNamespaceObject final : public JSDestructibleObject {
public:
typedef JSDestructibleObject Base;
static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames | GetOwnPropertySlotIsImpureForPropertyAbsence | IsImmutablePrototypeExoticObject;
- static JSModuleNamespaceObject* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, AbstractModuleRecord* moduleRecord, const IdentifierSet& exports)
+ static JSModuleNamespaceObject* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, AbstractModuleRecord* moduleRecord, Vector<std::pair<Identifier, AbstractModuleRecord::Resolution>>&& resolutions)
{
- JSModuleNamespaceObject* object = new (NotNull, allocateCell<JSModuleNamespaceObject>(exec->vm().heap)) JSModuleNamespaceObject(exec->vm(), structure);
- object->finishCreation(exec, globalObject, moduleRecord, exports);
+ JSModuleNamespaceObject* object =
+ new (
+ NotNull,
+ allocateCell<JSModuleNamespaceObject>(exec->vm().heap, JSModuleNamespaceObject::allocationSize(resolutions.size())))
+ JSModuleNamespaceObject(exec->vm(), structure);
+ object->finishCreation(exec, globalObject, moduleRecord, WTFMove(resolutions));
return object;
}
@@ -61,7 +64,7 @@
AbstractModuleRecord* moduleRecord() { return m_moduleRecord.get(); }
protected:
- JS_EXPORT_PRIVATE void finishCreation(ExecState*, JSGlobalObject*, AbstractModuleRecord*, const IdentifierSet& exports);
+ JS_EXPORT_PRIVATE void finishCreation(ExecState*, JSGlobalObject*, AbstractModuleRecord*, Vector<std::pair<Identifier, AbstractModuleRecord::Resolution>>&&);
JS_EXPORT_PRIVATE JSModuleNamespaceObject(VM&, Structure*);
private:
@@ -68,10 +71,43 @@
static void destroy(JSCell*);
static void visitChildren(JSCell*, SlotVisitor&);
- typedef WTF::ListHashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> OrderedIdentifierSet;
+ WriteBarrierBase<AbstractModuleRecord>& moduleRecordAt(unsigned offset)
+ {
+ return moduleRecords()[offset];
+ }
- OrderedIdentifierSet m_exports;
+ WriteBarrierBase<AbstractModuleRecord>* moduleRecords()
+ {
+ return bitwise_cast<WriteBarrierBase<AbstractModuleRecord>*>(bitwise_cast<char*>(this) + offsetOfModuleRecords());
+ }
+
+ static size_t offsetOfModuleRecords()
+ {
+ return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<AbstractModuleRecord>)>(sizeof(JSModuleNamespaceObject));
+ }
+
+ static size_t allocationSize(unsigned moduleRecords)
+ {
+ return offsetOfModuleRecords() + moduleRecords * sizeof(WriteBarrier<AbstractModuleRecord>);
+ }
+
+ struct ExportEntry {
+ Identifier localName;
+ unsigned moduleRecordOffset;
+ };
+
+ typedef HashMap<RefPtr<UniquedStringImpl>, ExportEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> ExportMap;
+
+ ExportMap m_exports;
+ Vector<Identifier> m_names;
WriteBarrier<AbstractModuleRecord> m_moduleRecord;
};
+inline bool isJSModuleNamespaceObject(JSCell* cell)
+{
+ return cell->classInfo(*cell->vm()) == JSModuleNamespaceObject::info();
+}
+
+inline bool isJSModuleNamespaceObject(JSValue v) { return v.isCell() && isJSModuleNamespaceObject(v.asCell()); }
+
} // namespace JSC
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSModuleRecord.h (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSModuleRecord.h 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSModuleRecord.h 2017-02-27 13:44:03 UTC (rev 213049)
@@ -40,11 +40,6 @@
DECLARE_EXPORT_INFO;
- JSModuleEnvironment* moduleEnvironment()
- {
- ASSERT(m_moduleEnvironment);
- return m_moduleEnvironment.get();
- }
static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
static JSModuleRecord* create(ExecState*, VM&, Structure*, const Identifier&, const SourceCode&, const VariableEnvironment&, const VariableEnvironment&);
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/PropertySlot.h (213048 => 213049)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/PropertySlot.h 2017-02-27 13:25:35 UTC (rev 213048)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/PropertySlot.h 2017-02-27 13:44:03 UTC (rev 213049)
@@ -23,6 +23,7 @@
#include "JSCJSValue.h"
#include "PropertyName.h"
#include "PropertyOffset.h"
+#include "ScopeOffset.h"
#include <wtf/Assertions.h>
namespace JSC {
@@ -32,6 +33,7 @@
class ExecState;
class GetterSetter;
class JSObject;
+class JSModuleEnvironment;
// ECMA 262-3 8.6.1
// Property attributes
@@ -86,6 +88,12 @@
VMInquiry, // Our VM is just poking around. When this is the InternalMethodType, getOwnPropertySlot is not allowed to do user observable actions.
};
+ enum class AdditionalDataType : uint8_t {
+ None,
+ DOMJIT, // Annotated with DOMJIT information.
+ ModuleNamespace, // ModuleNamespaceObject's environment access.
+ };
+
explicit PropertySlot(const JSValue thisValue, InternalMethodType internalMethodType)
: m_offset(invalidOffset)
, m_thisValue(thisValue)
@@ -94,6 +102,7 @@
, m_cacheability(CachingAllowed)
, m_propertyType(TypeUnset)
, m_internalMethodType(internalMethodType)
+ , m_additionalDataType(AdditionalDataType::None)
, m_isTaintedByOpaqueObject(false)
{
}
@@ -163,9 +172,23 @@
DOMJIT::GetterSetter* domJIT() const
{
- return m_domJIT;
+ if (m_additionalDataType == AdditionalDataType::DOMJIT)
+ return m_additionalData.domJIT;
+ return nullptr;
}
+ struct ModuleNamespaceSlot {
+ JSModuleEnvironment* environment;
+ unsigned scopeOffset;
+ };
+
+ std::optional<ModuleNamespaceSlot> moduleNamespaceSlot() const
+ {
+ if (m_additionalDataType == AdditionalDataType::ModuleNamespace)
+ return m_additionalData.moduleNamespaceSlot;
+ return std::nullopt;
+ }
+
void setValue(JSObject* slotBase, unsigned attributes, JSValue value)
{
ASSERT(attributes == attributesForStructure(attributes));
@@ -206,6 +229,14 @@
m_offset = invalidOffset;
}
+ void setValueModuleNamespace(JSObject* slotBase, unsigned attributes, JSValue value, JSModuleEnvironment* environment, ScopeOffset scopeOffset)
+ {
+ setValue(slotBase, attributes, value);
+ m_additionalDataType = AdditionalDataType::ModuleNamespace;
+ m_additionalData.moduleNamespaceSlot.environment = environment;
+ m_additionalData.moduleNamespaceSlot.scopeOffset = scopeOffset.offset();
+ }
+
void setCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue)
{
ASSERT(attributes == attributesForStructure(attributes));
@@ -220,7 +251,7 @@
m_offset = invalidOffset;
}
- void setCacheableCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue, DOMJIT::GetterSetter* domJIT = nullptr)
+ void setCacheableCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue)
{
ASSERT(attributes == attributesForStructure(attributes));
@@ -232,9 +263,17 @@
m_slotBase = slotBase;
m_propertyType = TypeCustom;
m_offset = !invalidOffset;
- m_domJIT = domJIT;
}
+ void setCacheableCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue, DOMJIT::GetterSetter* domJIT)
+ {
+ setCacheableCustom(slotBase, attributes, getValue);
+ if (domJIT) {
+ m_additionalDataType = AdditionalDataType::DOMJIT;
+ m_additionalData.domJIT = domJIT;
+ }
+ }
+
void setCustomGetterSetter(JSObject* slotBase, unsigned attributes, CustomGetterSetter* getterSetter)
{
ASSERT(attributes == attributesForStructure(attributes));
@@ -328,7 +367,11 @@
CacheabilityType m_cacheability;
PropertyType m_propertyType;
InternalMethodType m_internalMethodType;
- DOMJIT::GetterSetter* m_domJIT { nullptr };
+ AdditionalDataType m_additionalDataType;
+ union {
+ DOMJIT::GetterSetter* domJIT;
+ ModuleNamespaceSlot moduleNamespaceSlot;
+ } m_additionalData;
bool m_isTaintedByOpaqueObject;
};