Diff
Modified: trunk/LayoutTests/ChangeLog (160245 => 160246)
--- trunk/LayoutTests/ChangeLog 2013-12-06 21:40:34 UTC (rev 160245)
+++ trunk/LayoutTests/ChangeLog 2013-12-06 22:05:10 UTC (rev 160246)
@@ -1,3 +1,19 @@
+2013-12-06 Filip Pizlo <[email protected]>
+
+ FTL should support hole/OOB array accesses
+ https://bugs.webkit.org/show_bug.cgi?id=118077
+
+ Reviewed by Oliver Hunt and Mark Hahnenberg.
+
+ * js/regress/double-get-by-val-out-of-bounds-expected.txt: Added.
+ * js/regress/double-get-by-val-out-of-bounds.html: Added.
+ * js/regress/get-by-val-out-of-bounds-expected.txt: Added.
+ * js/regress/get-by-val-out-of-bounds.html: Added.
+ * js/regress/script-tests/double-get-by-val-out-of-bounds.js: Added.
+ (foo):
+ * js/regress/script-tests/get-by-val-out-of-bounds.js: Added.
+ (foo):
+
2013-12-06 Rob Buis <[email protected]>
[CSS Shapes] ShapeOutsideInfo needs to use the parent's writing mode when calculating offsets
Added: trunk/LayoutTests/js/regress/double-get-by-val-out-of-bounds-expected.txt (0 => 160246)
--- trunk/LayoutTests/js/regress/double-get-by-val-out-of-bounds-expected.txt (rev 0)
+++ trunk/LayoutTests/js/regress/double-get-by-val-out-of-bounds-expected.txt 2013-12-06 22:05:10 UTC (rev 160246)
@@ -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: trunk/LayoutTests/js/regress/double-get-by-val-out-of-bounds.html (0 => 160246)
--- trunk/LayoutTests/js/regress/double-get-by-val-out-of-bounds.html (rev 0)
+++ trunk/LayoutTests/js/regress/double-get-by-val-out-of-bounds.html 2013-12-06 22:05:10 UTC (rev 160246)
@@ -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: trunk/LayoutTests/js/regress/get-by-val-out-of-bounds-expected.txt (0 => 160246)
--- trunk/LayoutTests/js/regress/get-by-val-out-of-bounds-expected.txt (rev 0)
+++ trunk/LayoutTests/js/regress/get-by-val-out-of-bounds-expected.txt 2013-12-06 22:05:10 UTC (rev 160246)
@@ -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: trunk/LayoutTests/js/regress/get-by-val-out-of-bounds.html (0 => 160246)
--- trunk/LayoutTests/js/regress/get-by-val-out-of-bounds.html (rev 0)
+++ trunk/LayoutTests/js/regress/get-by-val-out-of-bounds.html 2013-12-06 22:05:10 UTC (rev 160246)
@@ -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: trunk/LayoutTests/js/regress/script-tests/double-get-by-val-out-of-bounds.js (0 => 160246)
--- trunk/LayoutTests/js/regress/script-tests/double-get-by-val-out-of-bounds.js (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/double-get-by-val-out-of-bounds.js 2013-12-06 22:05:10 UTC (rev 160246)
@@ -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: trunk/LayoutTests/js/regress/script-tests/get-by-val-out-of-bounds.js (0 => 160246)
--- trunk/LayoutTests/js/regress/script-tests/get-by-val-out-of-bounds.js (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/get-by-val-out-of-bounds.js 2013-12-06 22:05:10 UTC (rev 160246)
@@ -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;
+}
Modified: trunk/Source/_javascript_Core/ChangeLog (160245 => 160246)
--- trunk/Source/_javascript_Core/ChangeLog 2013-12-06 21:40:34 UTC (rev 160245)
+++ trunk/Source/_javascript_Core/ChangeLog 2013-12-06 22:05:10 UTC (rev 160246)
@@ -1,3 +1,17 @@
+2013-12-06 Filip Pizlo <[email protected]>
+
+ FTL should support hole/OOB array accesses
+ https://bugs.webkit.org/show_bug.cgi?id=118077
+
+ Reviewed by Oliver Hunt and Mark Hahnenberg.
+
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLIntrinsicRepository.h:
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::LowerDFGToLLVM::compileGetByVal):
+ (JSC::FTL::LowerDFGToLLVM::baseIndex):
+
2013-12-06 Michael Saboff <[email protected]>
Split sizing of VarArgs frames from loading arguments for the frame
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (160245 => 160246)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2013-12-06 21:40:34 UTC (rev 160245)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2013-12-06 22:05:10 UTC (rev 160246)
@@ -158,13 +158,6 @@
return CanCompileAndOSREnter;
return CannotCompile;
}
- switch (node->arrayMode().speculation()) {
- case Array::SaneChain:
- case Array::InBounds:
- break;
- default:
- return CannotCompile;
- }
break;
case PutByVal:
case PutByValAlias:
Modified: trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h (160245 => 160246)
--- trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h 2013-12-06 21:40:34 UTC (rev 160245)
+++ trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h 2013-12-06 22:05:10 UTC (rev 160246)
@@ -54,6 +54,7 @@
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_EJssZ, functionType(int64, intPtr, intPtr, int32)) \
macro(J_JITOperation_ESsiJI, functionType(int64, intPtr, intPtr, int64, intPtr)) \
macro(Jss_JITOperation_EZ, functionType(intPtr, intPtr, int32)) \
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (160245 => 160246)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2013-12-06 21:40:34 UTC (rev 160245)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2013-12-06 22:05:10 UTC (rev 160246)
@@ -1482,25 +1482,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;
}
@@ -1508,16 +1528,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(
@@ -1528,9 +1548,35 @@
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;
}
@@ -2715,6 +2761,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"));