https://bugs.webkit.org/show_bug.cgi?id=183071
Reviewed by Mark Lam.
JSTests:
* stress/dead-fiat-value-to-int52-then-exit-not-double.js:
(foo):
* stress/dead-fiat-value-to-int52-then-exit-not-int52.js:
(foo):
* stress/dead-fiat-value-to-int52.js:
(foo):
* stress/dead-osr-entry-value.js:
(foo):
* stress/fiat-value-to-int52-then-exit-not-double.js:
(foo):
* stress/fiat-value-to-int52-then-exit-not-int52.js:
(foo):
* stress/fiat-value-to-int52-then-fail-to-fold.js:
(foo):
* stress/fiat-value-to-int52-then-fold.js:
(foo):
* stress/fiat-value-to-int52.js:
(foo):
* stress/fold-based-on-int32-proof-mul-branch.js:
(foo):
* stress/fold-profiled-call-to-call.js:
(foo):
* stress/fold-to-double-constant-then-exit.js:
(foo):
* stress/fold-to-int52-constant-then-exit.js:
(foo):
* stress/fold-to-primitive-in-cfa.js:
(foo):
* stress/fold-to-primitive-to-identity-in-cfa.js:
(foo):
* stress/has-indexed-property-array-storage-ftl.js: Added.
(shouldBe):
(test1):
(test2):
* stress/has-indexed-property-slow-put-array-storage-ftl.js: Added.
(shouldBe):
(test1):
(test2):
* stress/int52-ai-add-then-filter-int32.js:
(foo):
* stress/int52-ai-mul-and-clean-neg-zero-then-filter-int32.js:
(foo):
* stress/int52-ai-mul-then-filter-int32.js:
(foo):
* stress/int52-ai-neg-then-filter-int32.js:
(foo):
* stress/int52-ai-sub-then-filter-int32.js:
(foo):
* stress/licm-pre-header-cannot-exit-nested.js:
(foo):
* stress/licm-pre-header-cannot-exit.js:
(foo):
* stress/sparse-array-entry-update-144067.js:
(useMemoryToTriggerGCs):
* stress/test-spec-misc.js:
(foo):
* stress/tricky-array-bounds-checks.js:
(foo):
Source/JavaScriptCore:
Add $vm.ftlTrue, which becomes true if the caller is compiled in FTL.
This is useful for testing whether the caller function is compiled in FTL.
We also remove duplicate DFGTrue function in jsc.cpp. We have $vm.dfgTrue.
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
* jsc.cpp:
(GlobalObject::finishCreation):
(functionFalse1):
(functionFalse2): Deleted.
* runtime/Intrinsic.cpp:
(JSC::intrinsicName):
* runtime/Intrinsic.h:
* tools/JSDollarVM.cpp:
(JSC::functionFTLTrue):
(JSC::JSDollarVM::finishCreation):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@228950
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2018-02-23 Yusuke Suzuki <utatane.tea@gmail.com>
+
+ [JSC] Implement $vm.ftlTrue function for FTL testing
+ https://bugs.webkit.org/show_bug.cgi?id=183071
+
+ Reviewed by Mark Lam.
+
+ * stress/dead-fiat-value-to-int52-then-exit-not-double.js:
+ (foo):
+ * stress/dead-fiat-value-to-int52-then-exit-not-int52.js:
+ (foo):
+ * stress/dead-fiat-value-to-int52.js:
+ (foo):
+ * stress/dead-osr-entry-value.js:
+ (foo):
+ * stress/fiat-value-to-int52-then-exit-not-double.js:
+ (foo):
+ * stress/fiat-value-to-int52-then-exit-not-int52.js:
+ (foo):
+ * stress/fiat-value-to-int52-then-fail-to-fold.js:
+ (foo):
+ * stress/fiat-value-to-int52-then-fold.js:
+ (foo):
+ * stress/fiat-value-to-int52.js:
+ (foo):
+ * stress/fold-based-on-int32-proof-mul-branch.js:
+ (foo):
+ * stress/fold-profiled-call-to-call.js:
+ (foo):
+ * stress/fold-to-double-constant-then-exit.js:
+ (foo):
+ * stress/fold-to-int52-constant-then-exit.js:
+ (foo):
+ * stress/fold-to-primitive-in-cfa.js:
+ (foo):
+ * stress/fold-to-primitive-to-identity-in-cfa.js:
+ (foo):
+ * stress/has-indexed-property-array-storage-ftl.js: Added.
+ (shouldBe):
+ (test1):
+ (test2):
+ * stress/has-indexed-property-slow-put-array-storage-ftl.js: Added.
+ (shouldBe):
+ (test1):
+ (test2):
+ * stress/int52-ai-add-then-filter-int32.js:
+ (foo):
+ * stress/int52-ai-mul-and-clean-neg-zero-then-filter-int32.js:
+ (foo):
+ * stress/int52-ai-mul-then-filter-int32.js:
+ (foo):
+ * stress/int52-ai-neg-then-filter-int32.js:
+ (foo):
+ * stress/int52-ai-sub-then-filter-int32.js:
+ (foo):
+ * stress/licm-pre-header-cannot-exit-nested.js:
+ (foo):
+ * stress/licm-pre-header-cannot-exit.js:
+ (foo):
+ * stress/sparse-array-entry-update-144067.js:
+ (useMemoryToTriggerGCs):
+ * stress/test-spec-misc.js:
+ (foo):
+ * stress/tricky-array-bounds-checks.js:
+ (foo):
+
2018-02-22 Yusuke Suzuki <utatane.tea@gmail.com>
[FTL] Support HasIndexedProperty for ArrayStorage and SlowPutArrayStorage
function foo() {
- var value = bar(DFGTrue());
+ var value = bar($vm.dfgTrue());
fiatInt52(value);
fiatInt52(value);
}
function foo() {
- var value = bar(DFGTrue());
+ var value = bar($vm.dfgTrue());
fiatInt52(value);
fiatInt52(value);
}
function foo() {
- var value = bar(DFGTrue());
+ var value = bar($vm.dfgTrue());
fiatInt52(value);
fiatInt52(value);
}
var result = 0;
OSRExit();
for (var i = 0; i < 10000; ++i) {
- if (!DFGTrue())
+ if (!$vm.dfgTrue())
result += o.f;
}
return result;
function foo() {
- return fiatInt52(bar(DFGTrue())) + 1;
+ return fiatInt52(bar($vm.dfgTrue())) + 1;
}
var thingy = false;
function foo() {
- return fiatInt52(bar(DFGTrue())) + 1;
+ return fiatInt52(bar($vm.dfgTrue())) + 1;
}
var thingy = false;
function foo() {
- return fiatInt52(DFGTrue() ? 5.5 : 42) + 1;
+ return fiatInt52($vm.dfgTrue() ? 5.5 : 42) + 1;
}
noInline(foo);
function foo() {
- return fiatInt52(DFGTrue() ? 42 : 5.5) + 1;
+ return fiatInt52($vm.dfgTrue() ? 42 : 5.5) + 1;
}
noInline(foo);
function foo() {
- return fiatInt52(bar(DFGTrue())) + 1;
+ return fiatInt52(bar($vm.dfgTrue())) + 1;
}
function bar(p) {
function foo(a, b) {
- var value = DFGTrue() ? -0 : "foo";
+ var value = $vm.dfgTrue() ? -0 : "foo";
if (a * b == value)
- return [DFGTrue(), true];
- return [DFGTrue(), false];
+ return [$vm.dfgTrue(), true];
+ return [$vm.dfgTrue(), false];
}
noInline(foo);
function foo(f) {
- if (DFGTrue())
+ if ($vm.dfgTrue())
f = bar;
return f().f;
}
function foo(a, b) {
- if (DFGTrue())
+ if ($vm.dfgTrue())
a = b = 5.4;
var c = a + b;
if (isFinalTier())
function foo(a, b) {
- if (DFGTrue())
+ if ($vm.dfgTrue())
a = b = 2000000000;
var c = a + b;
if (isFinalTier())
function foo(x) {
- if (DFGTrue())
+ if ($vm.dfgTrue())
x = "hello";
return x + " world";
}
function foo(x, p) {
- if (DFGTrue())
+ if ($vm.dfgTrue())
x = p ? "hello" : "bar";
return x + " world";
}
--- /dev/null
+//@ runFTLNoCJIT
+
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+var didFTLCompile = false;
+var ftlTrue = $vm.ftlTrue;
+function test1(array)
+{
+ didFTLCompile = ftlTrue();
+ return 2 in array;
+}
+noInline(test1);
+
+var array = [1, 2, 3, 4];
+ensureArrayStorage(array);
+didFTLCompile = false;
+for (var i = 0; i < 1e5; ++i)
+ shouldBe(test1(array), true);
+shouldBe(didFTLCompile, true);
+
+var array = [1, 2, , 4];
+ensureArrayStorage(array);
+shouldBe(test1(array), false);
+
+var array = [];
+ensureArrayStorage(array);
+shouldBe(test1(array), false);
+
+function test2(array)
+{
+ didFTLCompile = ftlTrue();
+ return 2 in array;
+}
+noInline(test2);
+
+var array1 = [1, 2, 3, 4];
+ensureArrayStorage(array1);
+var array2 = [1, 2];
+ensureArrayStorage(array2);
+didFTLCompile = false;
+for (var i = 0; i < 1e5; ++i)
+ shouldBe(test2(array2), false);
+shouldBe(didFTLCompile, true);
+shouldBe(test2(array2), false);
+shouldBe(test2(array1), true);
--- /dev/null
+//@ runFTLNoCJIT
+
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+var didFTLCompile = false;
+var ftlTrue = $vm.ftlTrue;
+function test1(array)
+{
+ didFTLCompile = ftlTrue();
+ return 2 in array;
+}
+noInline(test1);
+
+var object = { a: 10 };
+Object.defineProperties(object, {
+ "0": {
+ get: function() { return this.a; },
+ set: function(x) { this.a = x; },
+ },
+});
+
+var array = [1, 2, 3, 4];
+array.__proto__ = object;
+ensureArrayStorage(array);
+didFTLCompile = false;
+for (var i = 0; i < 1e5; ++i)
+ shouldBe(test1(array), true);
+shouldBe(didFTLCompile, true);
+
+var array = [1, 2, , 4];
+array.__proto__ = object;
+ensureArrayStorage(array);
+shouldBe(test1(array), false);
+
+var array = [];
+array.__proto__ = object;
+ensureArrayStorage(array);
+shouldBe(test1(array), false);
+
+function test2(array)
+{
+ didFTLCompile = ftlTrue();
+ return 2 in array;
+}
+noInline(test2);
+
+var array1 = [1, 2, 3, 4];
+array1.__proto__ = object;
+ensureArrayStorage(array1);
+var array2 = [1, 2];
+array2.__proto__ = object;
+ensureArrayStorage(array2);
+didFTLCompile = false;
+for (var i = 0; i < 1e5; ++i)
+ shouldBe(test2(array2), false);
+shouldBe(didFTLCompile, true);
+shouldBe(test2(array2), false);
+shouldBe(test2(array1), true);
function foo(a, b, c) {
var o = {f:42};
- if (DFGTrue())
+ if ($vm.dfgTrue())
o.f = a + b + c;
return o.f | 0;
}
function foo(a, b, c) {
var o = {f:42};
- if (DFGTrue())
+ if ($vm.dfgTrue())
o.f = (a * b + 5) * c + 5;
return o.f | 0;
}
function foo(a, b, c) {
var o = {f:42};
- if (DFGTrue())
+ if ($vm.dfgTrue())
o.f = a * b * c;
return o.f | 0;
}
function foo(a, b) {
var o = {f:42};
- if (DFGTrue())
+ if ($vm.dfgTrue())
o.f = -(a + b);
return o.f | 0;
}
function foo(a, b) {
var o = {f:42};
- if (DFGTrue())
+ if ($vm.dfgTrue())
o.f = a - b - 2000000000;
return o.f | 0;
}
for (var j = 0; j < 10; ++j) {
var result = 0;
var i = 0;
- if (DFGTrue())
+ if ($vm.dfgTrue())
predicate = 42;
while (predicate >= 42) {
result += object.array[i++];
function foo(object, predicate) {
var result = 0;
var i = 0;
- if (DFGTrue())
+ if ($vm.dfgTrue())
predicate = 42;
while (predicate >= 42) {
result += object.array[i++];
function useMemoryToTriggerGCs() {
var arr = [];
- var limit = DFGTrue() ? 10000 : 100;
+ var limit = $vm.dfgTrue() ? 10000 : 100;
for (var i = 0; i < limit; i++)
arr[i] = { a: "using" + i, b: "up" + i, c: "memory" + i };
return arr;
function foo(index) {
var result = false;
- var x = getX(DFGTrue());
+ var x = getX($vm.dfgTrue());
x * 2;
function foo(a, i, p) {
- if (p || !DFGTrue())
- return [DFGTrue(), a[(i - (DFGTrue() ? 2147483646 : 0)) | 0], a[i], a[(i + (DFGTrue() ? 2147483646 : 0)) | 0], DFGTrue()];
+ if (p || !$vm.dfgTrue())
+ return [$vm.dfgTrue(), a[(i - ($vm.dfgTrue() ? 2147483646 : 0)) | 0], a[i], a[(i + ($vm.dfgTrue() ? 2147483646 : 0)) | 0], $vm.dfgTrue()];
return [12];
}
+2018-02-23 Yusuke Suzuki <utatane.tea@gmail.com>
+
+ [JSC] Implement $vm.ftlTrue function for FTL testing
+ https://bugs.webkit.org/show_bug.cgi?id=183071
+
+ Reviewed by Mark Lam.
+
+ Add $vm.ftlTrue, which becomes true if the caller is compiled in FTL.
+ This is useful for testing whether the caller function is compiled in FTL.
+
+ We also remove duplicate DFGTrue function in jsc.cpp. We have $vm.dfgTrue.
+
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+ * jsc.cpp:
+ (GlobalObject::finishCreation):
+ (functionFalse1):
+ (functionFalse2): Deleted.
+ * runtime/Intrinsic.cpp:
+ (JSC::intrinsicName):
+ * runtime/Intrinsic.h:
+ * tools/JSDollarVM.cpp:
+ (JSC::functionFTLTrue):
+ (JSC::JSDollarVM::finishCreation):
+
2018-02-22 Yusuke Suzuki <utatane.tea@gmail.com>
[FTL] Support HasIndexedProperty for ArrayStorage and SlowPutArrayStorage
set(VirtualRegister(resultOperand), jsConstant(jsBoolean(true)));
return true;
}
+
+ case FTLTrueIntrinsic: {
+ insertChecks();
+ set(VirtualRegister(resultOperand), jsConstant(jsBoolean(isFTL(m_graph.m_plan.mode))));
+ return true;
+ }
case OSRExitIntrinsic: {
insertChecks();
static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState*);
static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
-static EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*);
-static EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionFalse(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState*);
addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
#endif
- putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "DFGTrue"), 0, functionFalse1, DFGTrueIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "OSRExit"), 0, functionUndefined1, OSRExitIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
- putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isFinalTier"), 0, functionFalse2, IsFinalTierIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
+ putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isFinalTier"), 0, functionFalse, IsFinalTierIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isInt32"), 0, functionIsInt32, CheckInt32Intrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
#endif
}
-EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*) { return JSValue::encode(jsBoolean(false)); }
-EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*) { return JSValue::encode(jsBoolean(false)); }
+EncodedJSValue JSC_HOST_CALL functionFalse(ExecState*) { return JSValue::encode(jsBoolean(false)); }
EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*) { return JSValue::encode(jsUndefined()); }
EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*) { return JSValue::encode(jsUndefined()); }
return "UnderscoreProtoIntrinsic";
case DFGTrueIntrinsic:
return "DFGTrueIntrinsic";
+ case FTLTrueIntrinsic:
+ return "FTLTrueIntrinsic";
case OSRExitIntrinsic:
return "OSRExitIntrinsic";
case IsFinalTierIntrinsic:
// Debugging intrinsics. These are meant to be used as testing hacks within
// jsc.cpp and should never be exposed to users.
DFGTrueIntrinsic,
+ FTLTrueIntrinsic,
OSRExitIntrinsic,
IsFinalTierIntrinsic,
SetInt32HeapPredictionIntrinsic,
return JSValue::encode(jsBoolean(false));
}
+// Returns true if the current frame is a FTL frame.
+// Usage: isFTL = $vm.ftlTrue()
+static EncodedJSValue JSC_HOST_CALL functionFTLTrue(ExecState*)
+{
+ return JSValue::encode(jsBoolean(false));
+}
+
static EncodedJSValue JSC_HOST_CALL functionCpuMfence(ExecState*)
{
#if CPU(X86_64) && !OS(WINDOWS)
addFunction(vm, "crash", functionCrash, 0);
putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "dfgTrue"), 0, functionDFGTrue, DFGTrueIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
+ putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "ftlTrue"), 0, functionFTLTrue, FTLTrueIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "cpuMfence"), 0, functionCpuMfence, CPUMfenceIntrinsic, 0);
putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "cpuRdtsc"), 0, functionCpuRdtsc, CPURdtscIntrinsic, 0);