Diff
Modified: trunk/LayoutTests/ChangeLog (153380 => 153381)
--- trunk/LayoutTests/ChangeLog 2013-07-26 20:41:32 UTC (rev 153380)
+++ trunk/LayoutTests/ChangeLog 2013-07-26 21:12:30 UTC (rev 153381)
@@ -1,3 +1,24 @@
+2013-07-26 Filip Pizlo <[email protected]>
+
+ REGRESSION: Crash when opening a message on Gmail
+ https://bugs.webkit.org/show_bug.cgi?id=119105
+
+ Reviewed by Oliver Hunt and Mark Hahnenberg.
+
+ * fast/js/dfg-get-by-id-unset-then-proto-less-warmup.html: Added.
+ * fast/js/dfg-get-by-id-unset-then-proto-more-warmup.html: Added.
+ * fast/js/dfg-get-by-id-unset-then-proto.html: Added.
+ * fast/js/jsc-test-list
+ * fast/js/script-tests/dfg-get-by-id-unset-then-proto-less-warmup.js: Added.
+ (foo):
+ (Blah):
+ * fast/js/script-tests/dfg-get-by-id-unset-then-proto-more-warmup.js: Added.
+ (foo):
+ (Blah):
+ * fast/js/script-tests/dfg-get-by-id-unset-then-proto.js: Added.
+ (foo):
+ (Blah):
+
2013-07-19 Mark Hahnenberg <[email protected]>
Setting a large numeric property on an object causes it to allocate a huge backing store
Added: trunk/LayoutTests/fast/js/dfg-get-by-id-unset-then-proto-less-warmup.html (0 => 153381)
--- trunk/LayoutTests/fast/js/dfg-get-by-id-unset-then-proto-less-warmup.html (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-get-by-id-unset-then-proto-less-warmup.html 2013-07-26 21:12:30 UTC (rev 153381)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/fast/js/dfg-get-by-id-unset-then-proto-more-warmup.html (0 => 153381)
--- trunk/LayoutTests/fast/js/dfg-get-by-id-unset-then-proto-more-warmup.html (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-get-by-id-unset-then-proto-more-warmup.html 2013-07-26 21:12:30 UTC (rev 153381)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/fast/js/dfg-get-by-id-unset-then-proto.html (0 => 153381)
--- trunk/LayoutTests/fast/js/dfg-get-by-id-unset-then-proto.html (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-get-by-id-unset-then-proto.html 2013-07-26 21:12:30 UTC (rev 153381)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Modified: trunk/LayoutTests/fast/js/jsc-test-list (153380 => 153381)
--- trunk/LayoutTests/fast/js/jsc-test-list 2013-07-26 20:41:32 UTC (rev 153380)
+++ trunk/LayoutTests/fast/js/jsc-test-list 2013-07-26 21:12:30 UTC (rev 153381)
@@ -142,6 +142,9 @@
fast/js/dfg-float64array
fast/js/dfg-flush-get-local
fast/js/dfg-force-exit-then-sparse-conditional-constant-prop-in-loop
+fast/js/dfg-get-by-id-unset-then-proto
+fast/js/dfg-get-by-id-unset-then-proto-less-warmup
+fast/js/dfg-get-by-id-unset-then-proto-more-warmup
fast/js/dfg-get-by-val-clobber
fast/js/dfg-get-by-val-getter-cse
fast/js/dfg-getter
Added: trunk/LayoutTests/fast/js/script-tests/dfg-get-by-id-unset-then-proto-less-warmup.js (0 => 153381)
--- trunk/LayoutTests/fast/js/script-tests/dfg-get-by-id-unset-then-proto-less-warmup.js (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/dfg-get-by-id-unset-then-proto-less-warmup.js 2013-07-26 21:12:30 UTC (rev 153381)
@@ -0,0 +1,42 @@
+description(
+"Tests what happens when the first attempt to cache an access goes down the unset route and then subsequently it tries to cache using a proto (less warmup)."
+);
+
+function foo(p, o) {
+ if (p)
+ return o.f;
+ return 42;
+}
+
+noInline(foo);
+
+// Get foo into the LLInt
+for (var i = 0; i < 10; ++i)
+ foo(false, {});
+
+// Warm up foo()'s p=true path and make it as polymorphic as possible.
+for (var i = 0; i < 3; ++i) {
+ foo(true, {f:42});
+ foo(true, {g:1, f:23});
+}
+
+// Force compilation by going down p=false.
+while (!dfgCompiled({f:foo}))
+ foo(false, {});
+
+// Hit the unset case.
+for (var j = 0; j < 1; ++j) {
+ var o = {};
+ for (var i = 0; i < 1000; ++i)
+ o["i" + i] = i;
+ o.f = 42;
+ shouldBe("foo(true, o)", "42");
+}
+
+function Blah() {
+}
+Blah.prototype.f = 23;
+
+// Hit the prototype case.
+shouldBe("foo(true, new Blah())", "23");
+
Added: trunk/LayoutTests/fast/js/script-tests/dfg-get-by-id-unset-then-proto-more-warmup.js (0 => 153381)
--- trunk/LayoutTests/fast/js/script-tests/dfg-get-by-id-unset-then-proto-more-warmup.js (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/dfg-get-by-id-unset-then-proto-more-warmup.js 2013-07-26 21:12:30 UTC (rev 153381)
@@ -0,0 +1,42 @@
+description(
+"Tests what happens when the first attempt to cache an access goes down the unset route and then subsequently it tries to cache using a proto (more warmup)."
+);
+
+function foo(p, o) {
+ if (p)
+ return o.f;
+ return 42;
+}
+
+noInline(foo);
+
+// Get foo into the LLInt
+for (var i = 0; i < 10; ++i)
+ foo(false, {});
+
+// Warm up foo()'s p=true path and make it as polymorphic as possible.
+for (var i = 0; i < 3; ++i) {
+ foo(true, {f:42});
+ foo(true, {g:1, f:23});
+}
+
+// Force compilation by going down p=false.
+while (!dfgCompiled({f:foo}))
+ foo(false, {});
+
+// Hit the unset case.
+for (var j = 0; j < 3; ++j) {
+ var o = {};
+ for (var i = 0; i < 1000; ++i)
+ o["i" + i] = i;
+ o.f = 42;
+ shouldBe("foo(true, o)", "42");
+}
+
+function Blah() {
+}
+Blah.prototype.f = 23;
+
+// Hit the prototype case.
+shouldBe("foo(true, new Blah())", "23");
+
Added: trunk/LayoutTests/fast/js/script-tests/dfg-get-by-id-unset-then-proto.js (0 => 153381)
--- trunk/LayoutTests/fast/js/script-tests/dfg-get-by-id-unset-then-proto.js (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/dfg-get-by-id-unset-then-proto.js 2013-07-26 21:12:30 UTC (rev 153381)
@@ -0,0 +1,42 @@
+description(
+"Tests what happens when the first attempt to cache an access goes down the unset route and then subsequently it tries to cache using a proto."
+);
+
+function foo(p, o) {
+ if (p)
+ return o.f;
+ return 42;
+}
+
+noInline(foo);
+
+// Get foo into the LLInt
+for (var i = 0; i < 10; ++i)
+ foo(false, {});
+
+// Warm up foo()'s p=true path and make it as polymorphic as possible.
+for (var i = 0; i < 3; ++i) {
+ foo(true, {f:42});
+ foo(true, {g:1, f:23});
+}
+
+// Force compilation by going down p=false.
+while (!dfgCompiled({f:foo}))
+ foo(false, {});
+
+// Hit the unset case.
+for (var j = 0; j < 2; ++j) {
+ var o = {};
+ for (var i = 0; i < 1000; ++i)
+ o["i" + i] = i;
+ o.f = 42;
+ shouldBe("foo(true, o)", "42");
+}
+
+function Blah() {
+}
+Blah.prototype.f = 23;
+
+// Hit the prototype case.
+shouldBe("foo(true, new Blah())", "23");
+
Modified: trunk/Source/_javascript_Core/ChangeLog (153380 => 153381)
--- trunk/Source/_javascript_Core/ChangeLog 2013-07-26 20:41:32 UTC (rev 153380)
+++ trunk/Source/_javascript_Core/ChangeLog 2013-07-26 21:12:30 UTC (rev 153381)
@@ -1,3 +1,23 @@
+2013-07-26 Filip Pizlo <[email protected]>
+
+ REGRESSION: Crash when opening a message on Gmail
+ https://bugs.webkit.org/show_bug.cgi?id=119105
+
+ Reviewed by Oliver Hunt and Mark Hahnenberg.
+
+ - GetById patching in the DFG needs to be more disciplined about how it derives the
+ slow path.
+
+ - Fix some dumping code thread safety issues.
+
+ * bytecode/CallLinkStatus.cpp:
+ (JSC::CallLinkStatus::dump):
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dumpBytecode):
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::getPolymorphicStructureList):
+ (JSC::DFG::tryBuildGetByIDList):
+
2013-07-26 Balazs Kilvady <[email protected]>
[mips] Fix LLINT build for mips backend
Modified: trunk/Source/_javascript_Core/bytecode/CallLinkStatus.cpp (153380 => 153381)
--- trunk/Source/_javascript_Core/bytecode/CallLinkStatus.cpp 2013-07-26 20:41:32 UTC (rev 153380)
+++ trunk/Source/_javascript_Core/bytecode/CallLinkStatus.cpp 2013-07-26 21:12:30 UTC (rev 153381)
@@ -143,8 +143,11 @@
if (m_callTarget)
out.print(comma, "Known target: ", m_callTarget);
- if (m_executable)
- out.print(comma, "Executable/CallHash: ", RawPointer(m_executable), "/", m_executable->hashFor(CodeForCall));
+ if (m_executable) {
+ out.print(comma, "Executable/CallHash: ", RawPointer(m_executable));
+ if (!isCompilationThread())
+ out.print("/", m_executable->hashFor(CodeForCall));
+ }
if (m_structure)
out.print(comma, "Structure: ", RawPointer(m_structure));
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (153380 => 153381)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2013-07-26 20:41:32 UTC (rev 153380)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2013-07-26 21:12:30 UTC (rev 153381)
@@ -487,7 +487,6 @@
}
if (needsFullScopeChain() && codeType() == FunctionCode)
out.printf("; activation in r%d", activationRegister());
- out.print("\n\nSource: ", sourceCodeOnOneLine(), "\n\n");
const Instruction* begin = instructions().begin();
const Instruction* end = instructions().end();
Modified: trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp (153380 => 153381)
--- trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp 2013-07-26 20:41:32 UTC (rev 153380)
+++ trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp 2013-07-26 21:12:30 UTC (rev 153381)
@@ -370,8 +370,11 @@
static bool getPolymorphicStructureList(
VM* vm, CodeBlock* codeBlock, StructureStubInfo& stubInfo,
- PolymorphicAccessStructureList*& polymorphicStructureList, int& listIndex)
+ PolymorphicAccessStructureList*& polymorphicStructureList, int& listIndex,
+ CodeLocationLabel& slowCase)
{
+ slowCase = stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase);
+
if (stubInfo.accessType == access_unset) {
RELEASE_ASSERT(!stubInfo.stubRoutine);
polymorphicStructureList = new PolymorphicAccessStructureList();
@@ -379,11 +382,12 @@
listIndex = 0;
} else if (stubInfo.accessType == access_get_by_id_self) {
RELEASE_ASSERT(!stubInfo.stubRoutine);
- polymorphicStructureList = new PolymorphicAccessStructureList(*vm, codeBlock->ownerExecutable(), JITStubRoutine::createSelfManagedRoutine(stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase)), stubInfo.u.getByIdSelf.baseObjectStructure.get(), true);
+ polymorphicStructureList = new PolymorphicAccessStructureList(*vm, codeBlock->ownerExecutable(), JITStubRoutine::createSelfManagedRoutine(slowCase), stubInfo.u.getByIdSelf.baseObjectStructure.get(), true);
stubInfo.initGetByIdSelfList(polymorphicStructureList, 1, true);
listIndex = 1;
} else if (stubInfo.accessType == access_get_by_id_chain) {
RELEASE_ASSERT(!!stubInfo.stubRoutine);
+ slowCase = CodeLocationLabel(stubInfo.stubRoutine->code().code());
polymorphicStructureList = new PolymorphicAccessStructureList(*vm, codeBlock->ownerExecutable(), stubInfo.stubRoutine, stubInfo.u.getByIdChain.baseObjectStructure.get(), stubInfo.u.getByIdChain.chain.get(), true);
stubInfo.stubRoutine.clear();
stubInfo.initGetByIdSelfList(polymorphicStructureList, 1, false);
@@ -392,6 +396,7 @@
RELEASE_ASSERT(stubInfo.accessType == access_get_by_id_self_list);
polymorphicStructureList = stubInfo.u.getByIdSelfList.structureList;
listIndex = stubInfo.u.getByIdSelfList.listSize;
+ slowCase = CodeLocationLabel(polymorphicStructureList->list[listIndex - 1].stubRoutine->code().code());
}
if (listIndex == POLYMORPHIC_LIST_CACHE_SIZE)
@@ -441,8 +446,9 @@
PolymorphicAccessStructureList* polymorphicStructureList;
int listIndex;
+ CodeLocationLabel slowCase;
- if (!getPolymorphicStructureList(vm, codeBlock, stubInfo, polymorphicStructureList, listIndex))
+ if (!getPolymorphicStructureList(vm, codeBlock, stubInfo, polymorphicStructureList, listIndex, slowCase))
return false;
stubInfo.u.getByIdSelfList.listSize++;
@@ -545,14 +551,7 @@
LinkBuffer patchBuffer(*vm, &stubJit, codeBlock);
- CodeLocationLabel lastProtoBegin;
- if (listIndex)
- lastProtoBegin = CodeLocationLabel(polymorphicStructureList->list[listIndex - 1].stubRoutine->code().code());
- else
- lastProtoBegin = stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase);
- ASSERT(!!lastProtoBegin);
-
- patchBuffer.link(wrongStruct, lastProtoBegin);
+ patchBuffer.link(wrongStruct, slowCase);
patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone));
if (!isDirect) {
patchBuffer.link(operationCall, operationFunction);
@@ -592,17 +591,15 @@
PolymorphicAccessStructureList* polymorphicStructureList;
int listIndex;
- if (!getPolymorphicStructureList(vm, codeBlock, stubInfo, polymorphicStructureList, listIndex))
+ CodeLocationLabel slowCase;
+ if (!getPolymorphicStructureList(vm, codeBlock, stubInfo, polymorphicStructureList, listIndex, slowCase))
return false;
stubInfo.u.getByIdProtoList.listSize++;
- CodeLocationLabel lastProtoBegin = CodeLocationLabel(polymorphicStructureList->list[listIndex - 1].stubRoutine->code().code());
- ASSERT(!!lastProtoBegin);
-
RefPtr<JITStubRoutine> stubRoutine;
- generateProtoChainAccessStub(exec, stubInfo, prototypeChain, count, offset, structure, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone), lastProtoBegin, stubRoutine);
+ generateProtoChainAccessStub(exec, stubInfo, prototypeChain, count, offset, structure, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone), slowCase, stubRoutine);
polymorphicStructureList->list[listIndex].set(*vm, codeBlock->ownerExecutable(), stubRoutine, structure, true);