Diff
Modified: branches/jsCStack/LayoutTests/ChangeLog (161391 => 161392)
--- branches/jsCStack/LayoutTests/ChangeLog 2014-01-07 02:04:20 UTC (rev 161391)
+++ branches/jsCStack/LayoutTests/ChangeLog 2014-01-07 03:17:11 UTC (rev 161392)
@@ -1,3 +1,7 @@
+2014-01-06 Filip Pizlo <[email protected]>
+
+ Merge trunk r160242, r160246, r160252, r160257.
+
2013-12-06 Michał Pakuła vel Rutka <[email protected]>
Unreviewed EFL gardening
Added: branches/jsCStack/LayoutTests/js/regress/by-val-generic-expected.txt (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/by-val-generic-expected.txt (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/by-val-generic-expected.txt 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,10 @@
+JSRegress/by-val-generic
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: branches/jsCStack/LayoutTests/js/regress/by-val-generic.html (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/by-val-generic.html (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/by-val-generic.html 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: branches/jsCStack/LayoutTests/js/regress/double-get-by-val-out-of-bounds-expected.txt (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/double-get-by-val-out-of-bounds-expected.txt (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/double-get-by-val-out-of-bounds-expected.txt 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,10 @@
+JSRegress/double-get-by-val-out-of-bounds
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: branches/jsCStack/LayoutTests/js/regress/double-get-by-val-out-of-bounds.html (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/double-get-by-val-out-of-bounds.html (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/double-get-by-val-out-of-bounds.html 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: branches/jsCStack/LayoutTests/js/regress/get-by-val-out-of-bounds-expected.txt (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/get-by-val-out-of-bounds-expected.txt (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/get-by-val-out-of-bounds-expected.txt 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,10 @@
+JSRegress/get-by-val-out-of-bounds
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: branches/jsCStack/LayoutTests/js/regress/get-by-val-out-of-bounds.html (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/get-by-val-out-of-bounds.html (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/get-by-val-out-of-bounds.html 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: branches/jsCStack/LayoutTests/js/regress/logical-not-expected.txt (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/logical-not-expected.txt (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/logical-not-expected.txt 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,10 @@
+JSRegress/logical-not
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: branches/jsCStack/LayoutTests/js/regress/logical-not.html (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/logical-not.html (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/logical-not.html 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: branches/jsCStack/LayoutTests/js/regress/put-by-val-machine-int-expected.txt (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/put-by-val-machine-int-expected.txt (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/put-by-val-machine-int-expected.txt 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,10 @@
+JSRegress/put-by-val-machine-int
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: branches/jsCStack/LayoutTests/js/regress/put-by-val-machine-int.html (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/put-by-val-machine-int.html (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/put-by-val-machine-int.html 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: branches/jsCStack/LayoutTests/js/regress/script-tests/by-val-generic.js (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/script-tests/by-val-generic.js (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/script-tests/by-val-generic.js 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,12 @@
+function foo(a, b, c) {
+ a[b] = c;
+ return a[b];
+}
+
+noInline(foo);
+
+for (var i = 0; i < 100000; ++i) {
+ var result = foo({}, "foo", "bar");
+ if (result !== "bar")
+ throw "Error: bad result: " + result;
+}
Added: branches/jsCStack/LayoutTests/js/regress/script-tests/double-get-by-val-out-of-bounds.js (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/script-tests/double-get-by-val-out-of-bounds.js (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/script-tests/double-get-by-val-out-of-bounds.js 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,11 @@
+function foo(a) {
+ return a[1];
+}
+
+noInline(foo);
+
+for (var i = 0; i < 100000; ++i) {
+ var result = foo([42.5]);
+ if (result !== void 0)
+ throw "Error: bad value: " + result;
+}
Added: branches/jsCStack/LayoutTests/js/regress/script-tests/get-by-val-out-of-bounds.js (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/script-tests/get-by-val-out-of-bounds.js (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/script-tests/get-by-val-out-of-bounds.js 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,11 @@
+function foo(a) {
+ return a[1];
+}
+
+noInline(foo);
+
+for (var i = 0; i < 100000; ++i) {
+ var result = foo([42]);
+ if (result !== void 0)
+ throw "Error: bad value: " + result;
+}
Added: branches/jsCStack/LayoutTests/js/regress/script-tests/logical-not.js (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/script-tests/logical-not.js (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/script-tests/logical-not.js 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,14 @@
+function foo(v) {
+ return !v;
+}
+
+noInline(foo);
+
+var array = ["foo", 42, null, {}, true, false];
+var expected = [false, false, true, false, false, true];
+
+for (var i = 0; i < 200000; ++i) {
+ var result = foo(array[i % array.length]);
+ if (result !== expected[i % array.length])
+ throw "Error: bad result at " + i + ": " + result;
+}
Added: branches/jsCStack/LayoutTests/js/regress/script-tests/put-by-val-machine-int.js (0 => 161392)
--- branches/jsCStack/LayoutTests/js/regress/script-tests/put-by-val-machine-int.js (rev 0)
+++ branches/jsCStack/LayoutTests/js/regress/script-tests/put-by-val-machine-int.js 2014-01-07 03:17:11 UTC (rev 161392)
@@ -0,0 +1,12 @@
+function foo(a, v) {
+ a[0] = v + 2000000000;
+}
+
+noInline(foo);
+
+for (var i = 0; i < 100000; ++i) {
+ var a = new Int32Array(1);
+ foo(a, 2000000000);
+ if (a[0] != -294967296)
+ throw "Error: bad value: " + a[0];
+}
Modified: branches/jsCStack/Source/_javascript_Core/ChangeLog (161391 => 161392)
--- branches/jsCStack/Source/_javascript_Core/ChangeLog 2014-01-07 02:04:20 UTC (rev 161391)
+++ branches/jsCStack/Source/_javascript_Core/ChangeLog 2014-01-07 03:17:11 UTC (rev 161392)
@@ -1,3 +1,7 @@
+2014-01-06 Filip Pizlo <[email protected]>
+
+ Merge trunk r160238, r160242, r160246, r160252, r160257.
+
2014-01-06 Michael Saboff <[email protected]>
CStack Branch: Disable JIT stack alignment check for ARM64
Modified: branches/jsCStack/Source/_javascript_Core/dfg/DFGGraph.h (161391 => 161392)
--- branches/jsCStack/Source/_javascript_Core/dfg/DFGGraph.h 2014-01-07 02:04:20 UTC (rev 161391)
+++ branches/jsCStack/Source/_javascript_Core/dfg/DFGGraph.h 2014-01-07 03:17:11 UTC (rev 161392)
@@ -428,6 +428,18 @@
return baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, m_profiledBlock);
}
+ bool isStrictModeFor(CodeOrigin codeOrigin)
+ {
+ if (!codeOrigin.inlineCallFrame)
+ return m_codeBlock->isStrictMode();
+ return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->isStrictMode();
+ }
+
+ ECMAMode ecmaModeFor(CodeOrigin codeOrigin)
+ {
+ return isStrictModeFor(codeOrigin) ? StrictMode : NotStrictMode;
+ }
+
bool masqueradesAsUndefinedWatchpointIsStillValid(const CodeOrigin& codeOrigin)
{
return m_plan.watchpoints.isStillValid(
Modified: branches/jsCStack/Source/_javascript_Core/ftl/FTLCapabilities.cpp (161391 => 161392)
--- branches/jsCStack/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2014-01-07 02:04:20 UTC (rev 161391)
+++ branches/jsCStack/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2014-01-07 03:17:11 UTC (rev 161392)
@@ -105,6 +105,9 @@
case NotifyWrite:
case Call:
case Construct:
+ case ValueToInt32:
+ case Branch:
+ case LogicalNot:
// These are OK.
break;
case GetById:
@@ -146,8 +149,8 @@
case GetByVal:
switch (node->arrayMode().type()) {
case Array::ForceExit:
+ case Array::Generic:
case Array::String:
- return CanCompileAndOSREnter;
case Array::Int32:
case Array::Double:
case Array::Contiguous:
@@ -157,19 +160,13 @@
return CanCompileAndOSREnter;
return CannotCompile;
}
- switch (node->arrayMode().speculation()) {
- case Array::SaneChain:
- case Array::InBounds:
- break;
- default:
- return CannotCompile;
- }
break;
case PutByVal:
case PutByValAlias:
+ case PutByValDirect:
switch (node->arrayMode().type()) {
case Array::ForceExit:
- return CanCompileAndOSREnter;
+ case Array::Generic:
case Array::Int32:
case Array::Double:
case Array::Contiguous:
@@ -202,19 +199,6 @@
if (node->isBinaryUseKind(NumberUse))
break;
return CannotCompile;
- case Branch:
- case LogicalNot:
- switch (node->child1().useKind()) {
- case BooleanUse:
- case Int32Use:
- case NumberUse:
- case StringUse:
- case ObjectOrOtherUse:
- break;
- default:
- return CannotCompile;
- }
- break;
case Switch:
switch (node->switchData()->kind) {
case SwitchImm:
@@ -224,10 +208,6 @@
return CannotCompile;
}
break;
- case ValueToInt32:
- if (node->child1().useKind() != BooleanUse)
- return CannotCompile;
- break;
default:
// Don't know how to handle anything else.
return CannotCompile;
Modified: branches/jsCStack/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h (161391 => 161392)
--- branches/jsCStack/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h 2014-01-07 02:04:20 UTC (rev 161391)
+++ branches/jsCStack/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h 2014-01-07 03:17:11 UTC (rev 161392)
@@ -55,6 +55,8 @@
macro(C_JITOperation_ESt, functionType(intPtr, intPtr, intPtr)) \
macro(I_JITOperation_EJss, functionType(intPtr, intPtr, intPtr)) \
macro(J_JITOperation_E, functionType(int64, intPtr)) \
+ macro(J_JITOperation_EAZ, functionType(int64, intPtr, intPtr, int32)) \
+ macro(J_JITOperation_EJJ, functionType(int64, intPtr, int64, int64)) \
macro(J_JITOperation_EJssZ, functionType(int64, intPtr, intPtr, int32)) \
macro(J_JITOperation_ESsiJI, functionType(int64, intPtr, intPtr, int64, intPtr)) \
macro(Jss_JITOperation_EZ, functionType(intPtr, intPtr, int32)) \
@@ -65,6 +67,8 @@
macro(P_JITOperation_EStPS, functionType(intPtr, intPtr, intPtr, intPtr, intPtr)) \
macro(P_JITOperation_EStSS, functionType(intPtr, intPtr, intPtr, intPtr, intPtr)) \
macro(P_JITOperation_EStZ, functionType(intPtr, intPtr, intPtr, int32)) \
+ macro(S_JITOperation_EJ, functionType(intPtr, intPtr, int64)) \
+ macro(V_JITOperation_EJJJ, functionType(voidType, intPtr, int64, int64, int64)) \
macro(V_JITOperation_EOZD, functionType(voidType, intPtr, intPtr, int32, doubleType)) \
macro(V_JITOperation_EOZJ, functionType(voidType, intPtr, intPtr, int32, int64)) \
macro(V_JITOperation_EVws, functionType(voidType, intPtr, intPtr)) \
Modified: branches/jsCStack/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (161391 => 161392)
--- branches/jsCStack/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2014-01-07 02:04:20 UTC (rev 161391)
+++ branches/jsCStack/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2014-01-07 03:17:11 UTC (rev 161392)
@@ -387,6 +387,7 @@
break;
case PutByVal:
case PutByValAlias:
+ case PutByValDirect:
compilePutByVal();
break;
case NewObject:
@@ -509,8 +510,96 @@
void compileValueToInt32()
{
- ASSERT(m_node->child1().useKind() == BooleanUse);
- setInt32(m_out.zeroExt(lowBoolean(m_node->child1()), m_out.int32));
+ switch (m_node->child1().useKind()) {
+ case Int32Use:
+ setInt32(lowInt32(m_node->child1()));
+ break;
+
+ case MachineIntUse:
+ setInt32(m_out.castToInt32(lowStrictInt52(m_node->child1())));
+ break;
+
+ case NumberUse:
+ case NotCellUse: {
+ LoweredNodeValue value = m_int32Values.get(m_node->child1().node());
+ if (isValid(value)) {
+ setInt32(value.value());
+ break;
+ }
+
+ value = m_jsValueValues.get(m_node->child1().node());
+ if (isValid(value)) {
+ LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("ValueToInt32 int case"));
+ LBasicBlock notIntCase = FTL_NEW_BLOCK(m_out, ("ValueToInt32 not int case"));
+ LBasicBlock doubleCase = 0;
+ LBasicBlock notNumberCase = 0;
+ if (m_node->child1().useKind() == NotCellUse) {
+ doubleCase = FTL_NEW_BLOCK(m_out, ("ValueToInt32 double case"));
+ notNumberCase = FTL_NEW_BLOCK(m_out, ("ValueToInt32 not number case"));
+ }
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ValueToInt32 continuation"));
+
+ Vector<ValueFromBlock> results;
+
+ m_out.branch(isNotInt32(value.value()), notIntCase, intCase);
+
+ LBasicBlock lastNext = m_out.appendTo(intCase, notIntCase);
+ results.append(m_out.anchor(unboxInt32(value.value())));
+ m_out.jump(continuation);
+
+ if (m_node->child1().useKind() == NumberUse) {
+ m_out.appendTo(notIntCase, continuation);
+ FTL_TYPE_CHECK(
+ jsValueValue(value.value()), m_node->child1(), SpecFullNumber,
+ isCellOrMisc(value.value()));
+ results.append(m_out.anchor(doubleToInt32(unboxDouble(value.value()))));
+ m_out.jump(continuation);
+ } else {
+ m_out.appendTo(notIntCase, doubleCase);
+ m_out.branch(isCellOrMisc(value.value()), notNumberCase, doubleCase);
+
+ m_out.appendTo(doubleCase, notNumberCase);
+ results.append(m_out.anchor(doubleToInt32(unboxDouble(value.value()))));
+ m_out.jump(continuation);
+
+ m_out.appendTo(notNumberCase, continuation);
+
+ FTL_TYPE_CHECK(
+ jsValueValue(value.value()), m_node->child1(), ~SpecCell,
+ isCell(value.value()));
+
+ LValue specialResult = m_out.select(
+ m_out.equal(
+ value.value(),
+ m_out.constInt64(JSValue::encode(jsBoolean(true)))),
+ m_out.int32One, m_out.int32Zero);
+ results.append(m_out.anchor(specialResult));
+ m_out.jump(continuation);
+ }
+
+ m_out.appendTo(continuation, lastNext);
+ setInt32(m_out.phi(m_out.int32, results));
+ break;
+ }
+
+ value = m_doubleValues.get(m_node->child1().node());
+ if (isValid(value)) {
+ setInt32(doubleToInt32(value.value()));
+ break;
+ }
+
+ terminate(Uncountable);
+ break;
+ }
+
+ case BooleanUse:
+ setInt32(m_out.zeroExt(lowBoolean(m_node->child1()), m_out.int32));
+ break;
+
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ break;
+ }
}
void compileInt52ToValue()
@@ -1422,25 +1511,45 @@
LValue index = lowInt32(m_node->child2());
LValue storage = lowStorage(m_node->child3());
+ IndexedAbstractHeap& heap = m_node->arrayMode().type() == Array::Int32 ?
+ m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties;
+
if (m_node->arrayMode().isInBounds()) {
speculate(
OutOfBounds, noValue(), 0,
m_out.aboveOrEqual(
index, m_out.load32(storage, m_heaps.Butterfly_publicLength)));
- LValue result = m_out.load64(m_out.baseIndex(
- m_node->arrayMode().type() == Array::Int32 ?
- m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
- storage, m_out.zeroExt(index, m_out.intPtr),
- m_state.forNode(m_node->child2()).m_value));
+ LValue result = m_out.load64(baseIndex(heap, storage, index, m_node->child2()));
speculate(LoadFromHole, noValue(), 0, m_out.isZero64(result));
setJSValue(result);
return;
}
- // FIXME: Implement hole/OOB loads in the FTL.
- // https://bugs.webkit.org/show_bug.cgi?id=118077
- RELEASE_ASSERT_NOT_REACHED();
+ LValue base = lowCell(m_node->child1());
+
+ LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous fast case"));
+ LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous slow case"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous continuation"));
+
+ m_out.branch(
+ m_out.aboveOrEqual(
+ index, m_out.load32(storage, m_heaps.Butterfly_publicLength)),
+ slowCase, fastCase);
+
+ LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
+
+ ValueFromBlock fastResult = m_out.anchor(
+ m_out.load64(baseIndex(heap, storage, index, m_node->child2())));
+ m_out.branch(m_out.isZero64(fastResult.value()), slowCase, continuation);
+
+ m_out.appendTo(slowCase, continuation);
+ ValueFromBlock slowResult = m_out.anchor(
+ vmCall(m_out.operation(operationGetByValArrayInt), m_callFrame, base, index));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
return;
}
@@ -1448,16 +1557,16 @@
LValue index = lowInt32(m_node->child2());
LValue storage = lowStorage(m_node->child3());
+ IndexedAbstractHeap& heap = m_heaps.indexedDoubleProperties;
+
if (m_node->arrayMode().isInBounds()) {
speculate(
OutOfBounds, noValue(), 0,
m_out.aboveOrEqual(
index, m_out.load32(storage, m_heaps.Butterfly_publicLength)));
- LValue result = m_out.loadDouble(m_out.baseIndex(
- m_heaps.indexedDoubleProperties,
- storage, m_out.zeroExt(index, m_out.intPtr),
- m_state.forNode(m_node->child2()).m_value));
+ LValue result = m_out.loadDouble(
+ baseIndex(heap, storage, index, m_node->child2()));
if (!m_node->arrayMode().isSaneChain()) {
speculate(
@@ -1468,12 +1577,45 @@
break;
}
- // FIXME: Implement hole/OOB loads in the FTL.
- // https://bugs.webkit.org/show_bug.cgi?id=118077
- RELEASE_ASSERT_NOT_REACHED();
+ LValue base = lowCell(m_node->child1());
+
+ LBasicBlock inBounds = FTL_NEW_BLOCK(m_out, ("GetByVal double in bounds"));
+ LBasicBlock boxPath = FTL_NEW_BLOCK(m_out, ("GetByVal double boxing"));
+ LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("GetByVal double slow case"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal double continuation"));
+
+ m_out.branch(
+ m_out.aboveOrEqual(
+ index, m_out.load32(storage, m_heaps.Butterfly_publicLength)),
+ slowCase, inBounds);
+
+ LBasicBlock lastNext = m_out.appendTo(inBounds, boxPath);
+ LValue doubleValue = m_out.loadDouble(
+ baseIndex(heap, storage, index, m_node->child2()));
+ m_out.branch(
+ m_out.doubleNotEqualOrUnordered(doubleValue, doubleValue), slowCase, boxPath);
+
+ m_out.appendTo(boxPath, slowCase);
+ ValueFromBlock fastResult = m_out.anchor(boxDouble(doubleValue));
+ m_out.jump(continuation);
+
+ m_out.appendTo(slowCase, continuation);
+ ValueFromBlock slowResult = m_out.anchor(
+ vmCall(m_out.operation(operationGetByValArrayInt), m_callFrame, base, index));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
return;
}
+ case Array::Generic: {
+ setJSValue(vmCall(
+ m_out.operation(operationGetByVal), m_callFrame,
+ lowJSValue(m_node->child1()), lowJSValue(m_node->child2())));
+ return;
+ }
+
case Array::String: {
compileStringCharAt();
return;
@@ -1572,6 +1714,31 @@
Edge child2 = m_graph.varArgChild(m_node, 1);
Edge child3 = m_graph.varArgChild(m_node, 2);
Edge child4 = m_graph.varArgChild(m_node, 3);
+
+ switch (m_node->arrayMode().type()) {
+ case Array::Generic: {
+ V_JITOperation_EJJJ operation;
+ if (m_node->op() == PutByValDirect) {
+ if (m_graph.isStrictModeFor(m_node->codeOrigin))
+ operation = operationPutByValDirectStrict;
+ else
+ operation = operationPutByValDirectNonStrict;
+ } else {
+ if (m_graph.isStrictModeFor(m_node->codeOrigin))
+ operation = operationPutByValStrict;
+ else
+ operation = operationPutByValNonStrict;
+ }
+
+ vmCall(
+ m_out.operation(operation), m_callFrame,
+ lowJSValue(child1), lowJSValue(child2), lowJSValue(child3));
+ return;
+ }
+
+ default:
+ break;
+ }
LValue base = lowCell(child1);
LValue index = lowInt32(child2);
@@ -1653,7 +1820,7 @@
TypedArrayType type = m_node->arrayMode().typedArrayType();
if (isTypedView(type)) {
- if (m_node->op() == PutByVal) {
+ if (m_node->op() != PutByValAlias) {
speculate(
OutOfBounds, noValue(), 0,
m_out.aboveOrEqual(
@@ -1677,7 +1844,7 @@
if (child3.useKind() == Int32Use)
intValue = lowInt32(child3);
else
- intValue = m_out.castToInt32(lowInt52(child3));
+ intValue = m_out.castToInt32(lowStrictInt52(child3));
if (isClamped(type)) {
ASSERT(elementSize(type) == 1);
@@ -1733,10 +1900,8 @@
m_out.appendTo(continuation, lastNext);
intValue = m_out.phi(m_out.int32, intValues);
- } else if (isSigned(type))
+ } else
intValue = doubleToInt32(doubleValue);
- else
- intValue = doubleToUInt32(doubleValue);
break;
}
@@ -2659,6 +2824,13 @@
info.m_isInvalidationPoint = true;
}
+ TypedPointer baseIndex(IndexedAbstractHeap& heap, LValue storage, LValue index, Edge edge)
+ {
+ return m_out.baseIndex(
+ heap, storage, m_out.zeroExt(index, m_out.intPtr),
+ m_state.forNode(edge).m_value);
+ }
+
LValue allocateCell(LValue allocator, LValue structure, LBasicBlock slowPath)
{
LBasicBlock success = FTL_NEW_BLOCK(m_out, ("object allocation success"));
@@ -2832,6 +3004,27 @@
LValue length = m_out.load32(stringValue, m_heaps.JSString_length);
return m_out.notEqual(length, m_out.int32Zero);
}
+ case UntypedUse: {
+ LValue value = lowJSValue(m_node->child1());
+
+ LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("Boolify untyped slow case"));
+ LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("Boolify untyped fast case"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Boolify untyped continuation"));
+
+ m_out.branch(isNotBoolean(value), slowCase, fastCase);
+
+ LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
+ ValueFromBlock fastResult = m_out.anchor(unboxBoolean(value));
+ m_out.jump(continuation);
+
+ m_out.appendTo(slowCase, continuation);
+ ValueFromBlock slowResult = m_out.anchor(m_out.notNull(vmCall(
+ m_out.operation(operationConvertJSValueToBoolean), m_callFrame, value)));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ return m_out.phi(m_out.boolean, fastResult, slowResult);
+ }
default:
RELEASE_ASSERT_NOT_REACHED();
return 0;
@@ -3048,14 +3241,6 @@
return doubleToInt32(doubleValue, -limit, limit);
}
- LValue doubleToUInt32(LValue doubleValue)
- {
- if (Output::hasSensibleDoubleToInt())
- return sensibleDoubleToInt32(doubleValue);
-
- return doubleToInt32(doubleValue, 0, pow(2, 32) - 1, false);
- }
-
LValue sensibleDoubleToInt32(LValue doubleValue)
{
LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("sensible doubleToInt32 slow path"));
@@ -3286,7 +3471,7 @@
LValue lowCell(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
{
- ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isCell(edge.useKind()));
+ ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || DFG::isCell(edge.useKind()));
if (edge->op() == JSConstant) {
JSValue value = m_graph.valueOfJSConstant(edge.node());
@@ -3595,6 +3780,11 @@
return m_out.testNonZero64(jsValue, m_tagMask);
}
+ LValue isCell(LValue jsValue)
+ {
+ return m_out.testIsZero64(jsValue, m_tagMask);
+ }
+
LValue isNotBoolean(LValue jsValue)
{
return m_out.testNonZero64(