Changeset 233184 in webkit
- Timestamp:
- Jun 25, 2018 4:56:35 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r233180 r233184 1 2018-06-25 Saam Barati <sbarati@apple.com> 2 3 JSImmutableButterfly can't be allocated from a subspace with HeapCell::Kind::Auxiliary 4 https://bugs.webkit.org/show_bug.cgi?id=186878 5 <rdar://problem/40568659> 6 7 Reviewed by Mark Lam. 8 9 Make these test not susceptible to conservative scan leaks by ensuring at least 10 one object gets collected when we allocate many of them. Before, these were just 11 testing that a fixed number of objects were collected. 12 13 * editing/selection/navigation-clears-editor-state-expected.txt: 14 * editing/selection/navigation-clears-editor-state.html: 15 * fast/dom/reference-cycle-leaks.html: 16 * fast/misc/resources/test-observegc.js: 17 * fast/misc/test-observegc-expected.txt: 18 * platform/mac-wk2/plugins/refcount-leaks-expected.txt: 19 * plugins/refcount-leaks-expected.txt: 20 * plugins/refcount-leaks.html: 21 1 22 2018-06-25 John Wilander <wilander@apple.com> 2 23 -
trunk/LayoutTests/editing/selection/navigation-clears-editor-state-expected.txt
r232434 r233184 4 4 5 5 6 iframe = appendIframe() 7 PASS internals.numberOfLiveDocuments() is initialDocumentCount + 1 8 iframe.src = "resources/select-iframe-focusin-document-crash-frame.html" 9 PASS internals.numberOfLiveDocuments() is initialDocumentCount + 1 6 PASS freed more than 60 documents 10 7 PASS successfullyParsed is true 11 8 -
trunk/LayoutTests/editing/selection/navigation-clears-editor-state.html
r232434 r233184 36 36 initialDocumentCount = internals.numberOfLiveDocuments(); 37 37 38 evalAndLog('iframe = appendIframe()'); 38 let frames = []; 39 const count = 200; 40 for (let i = 0; i < count; ++i) 41 frames.push(appendIframe()); 39 42 40 43 await wait(0); // Make sure the transient document created by inserting an iframe is removed. 41 44 GCController.collect(); 42 45 43 shouldBe('internals.numberOfLiveDocuments()', 'initialDocumentCount + 1');44 setEditorStates(iframe);46 for (let frame of frames) 47 setEditorStates(frame); 45 48 46 49 await wait(0); // Wait for UI update timer to fire. 47 50 48 evalAndLog('iframe.src = "resources/select-iframe-focusin-document-crash-frame.html"'); 49 iframe.onload = () => { 50 GCController.collect(); 51 shouldBe('internals.numberOfLiveDocuments()', 'initialDocumentCount + 1'); 52 finishJSTest(); 51 let resolved = 0; 52 for (let frame of frames) { 53 frame.src = "resources/select-iframe-focusin-document-crash-frame.html"; 54 frame.onload = () => { 55 ++resolved; 56 if (resolved !== count) 57 return; 58 let before = internals.numberOfLiveDocuments(); 59 GCController.collect(); 60 let after = internals.numberOfLiveDocuments(); 61 let delta = before - after; 62 if (delta > 0.3 * count) 63 debug("PASS freed more than 60 documents"); 64 else 65 debug("FAIL freed fewer than 60 documents"); 66 finishJSTest(); 67 }; 53 68 } 54 69 } … … 58 73 } else { 59 74 if (window.testRunner) 60 setTimeout(() => testRunner.notifyDone(), 3000);75 setTimeout(() => testRunner.notifyDone(), 5000); 61 76 // Clear out any lingering documents from the previous tests. 62 77 GCController.collect(); -
trunk/LayoutTests/fast/dom/reference-cycle-leaks.html
r225729 r233184 8 8 { 9 9 // Bump this number as high as we need to, to get reproducible results. 10 const repetitions = 20;10 const repetitions = 40; 11 11 12 12 gc(); -
trunk/LayoutTests/fast/misc/resources/test-observegc.js
r201425 r233184 1 1 description("Ensures that window.internals.observegc works as expected"); 2 2 3 var testObject = { testProperty : "testValue" }; 3 var observers = []; 4 for (let i = 0; i < 1000; ++i) { 5 let testObject = { testProperty : "testValue" }; 6 let observer = internals.observeGC(testObject); 7 observers.push(observer); 8 testObject = null; 9 } 4 10 5 var observer = internals.observeGC(testObject);6 testObject = null;7 11 gc(); 8 12 9 shouldBe('observer.wasCollected', 'true'); 13 var anyCollected = false; 14 for (let observer of observers) { 15 if (observer.wasCollected) 16 anyCollected = true; 17 } 18 19 shouldBe('anyCollected', 'true'); -
trunk/LayoutTests/fast/misc/test-observegc-expected.txt
r201425 r233184 4 4 5 5 6 PASS observer.wasCollected is true6 PASS anyCollected is true 7 7 PASS successfullyParsed is true 8 8 -
trunk/LayoutTests/platform/mac-wk2/plugins/refcount-leaks-expected.txt
r111070 r233184 1 PASS countAfterCreate === countOrig + 50 is true 2 FAIL countAfterGC < countAfterCreate should be true. Was false. 3 PASS refAfterGet === refOrig + 50 is true 4 FAIL refAfterGetGC < refAfterGet should be true. Was false. 5 PASS refAfterPass === refBeforePass + 50 is true 6 FAIL refAfterPassAndGC < refAfterPass should be true. Was false. 1 7 Test that we can get an NPObject returned through a method on an NPAPI Object. 2 Prints "SUCCESS" on success, "FAILURE" on failure.3 8 4 --- num test objects:5 countAfterCreate == countOrig + 3? PASS6 countOrig == countAfterGC? FAIL7 8 --- refcount on plug.testObject:9 originally: 210 after GC: 511 after passing: 812 FAILURE -
trunk/LayoutTests/plugins/refcount-leaks-expected.txt
r72302 r233184 1 PASS countAfterCreate === countOrig + 50 is true 2 PASS countAfterGC < countAfterCreate is true 3 PASS refAfterGet === refOrig + 50 is true 4 PASS refAfterGetGC < refAfterGet is true 5 PASS refAfterPass === refBeforePass + 50 is true 6 PASS refAfterPassAndGC < refAfterPass is true 1 7 Test that we can get an NPObject returned through a method on an NPAPI Object. 2 Prints "SUCCESS" on success, "FAILURE" on failure.3 8 4 --- num test objects:5 countAfterCreate == countOrig + 3? PASS6 countOrig == countAfterGC? PASS7 8 --- refcount on plug.testObject:9 originally: 210 after GC: 211 after passing: 212 SUCCESS -
trunk/LayoutTests/plugins/refcount-leaks.html
r120417 r233184 1 <head> 2 <script src="../resources/js-test-pre.js"></script> 3 </head> 4 1 5 <script> 2 3 6 function noop(x) { 7 } 4 8 5 function doGC() { 6 if (window.GCController) { 7 // GC twice to make sure everything is cleaned up. 8 for (var i = 0; i < 2; i++) { 9 window.GCController.collect(); 10 } 9 function doGC() { 10 // GC twice to make sure everything is cleaned up. 11 for (var i = 0; i < 2; i++) { 12 gc(); 11 13 } 12 14 } 13 15 14 function runtest() { 16 var countOrig; 17 var countAfterCreate; 18 var countAfterGC; 19 var testObj; 20 var refOrig; 21 var refAfterGet; 22 var refAfterGetGC; 23 var refBeforePass; 24 var refAfterPass; 25 var refAfterPassAndGC; 26 27 function runtest() { 15 28 if (window.testRunner) 16 testRunner.dumpAsText(); 17 18 19 var output = document.getElementById("output"); 20 output.innerHTML = ""; 29 testRunner.dumpAsText(); 21 30 22 31 // Test that objects are deleted after their JS references are released. 23 varcountOrig = plug.testObjectCount;24 o1 = plug.testCreateTestObject();25 o2 = plug.testCreateTestObject();26 o3= plug.testCreateTestObject();27 varcountAfterCreate = plug.testObjectCount;28 o1 = o2 = o3= null;32 countOrig = plug.testObjectCount; 33 let x; 34 for (let i = 0; i < 50; ++i) 35 x = plug.testCreateTestObject(); 36 countAfterCreate = plug.testObjectCount; 37 x = null; 29 38 doGC(); 30 var countAfterGC = plug.testObjectCount; 31 32 output.innerHTML += "--- num test objects:<br>"; 33 output.innerHTML += "countAfterCreate == countOrig + 3? " 34 + ((countAfterCreate == countOrig + 3) ? "PASS" : "FAIL") 35 + "<br>"; 36 output.innerHTML += "countOrig == countAfterGC? " 37 + ((countOrig == countAfterGC) ? "PASS" : "FAIL") 38 + "<br>"; 39 output.innerHTML += "<br>"; 39 countAfterGC = plug.testObjectCount; 40 shouldBe('countAfterCreate === countOrig + 50', 'true'); 41 shouldBe('countAfterGC < countAfterCreate', 'true'); 40 42 41 43 // Test that the object refcount returns to normal after JS references 42 44 // are released. 43 var testObj = plug.testObject; 44 var refOrig = testObj.refCount; 45 var o1 = plug.testObject; 46 var o2 = plug.testObject; 47 var o3 = plug.testObject; 48 var refAfterGet = testObj.refCount; 49 o1 = o2 = o3 = null; 45 testObj = plug.testObject; 46 refOrig = testObj.refCount; 47 for (let i = 0; i < 50; ++i) 48 plug.testObject; 49 refAfterGet = testObj.refCount; 50 50 doGC(); 51 var refAfterGetGC = testObj.refCount; 51 refAfterGetGC = testObj.refCount; 52 shouldBe('refAfterGet === refOrig + 50', 'true'); 53 shouldBe('refAfterGetGC < refAfterGet', 'true'); 52 54 53 55 // Test that calling NPN_Invoke with our object as a parameter returns 54 56 // our refcount to normal (may require a GC). 55 plug.testPassTestObject("noop", testObj); 56 plug.testPassTestObject("noop", testObj); 57 plug.testPassTestObject("noop", testObj); 57 refBeforePass = testObj.refCount; 58 for (let i = 0; i < 50; ++i) 59 plug.testPassTestObject("noop", testObj); 60 refAfterPass = testObj.refCount; 58 61 doGC(); 59 var refAfterPass = testObj.refCount; 60 61 output.innerHTML += "--- refcount on plug.testObject:<br>"; 62 output.innerHTML += "originally: " + refOrig + "<br>"; 63 output.innerHTML += "after GC: " + refAfterGetGC + "<br>"; 64 output.innerHTML += "after passing: " + refAfterPass + "<br>"; 65 66 var success = (countAfterGC == countOrig) && (refAfterPass == refOrig); 67 output.innerHTML += (success ? "SUCCESS" : "FAILURE"); 68 } 62 refAfterPassAndGC = testObj.refCount; 63 shouldBe('refAfterPass === refBeforePass + 50', 'true'); 64 shouldBe('refAfterPassAndGC < refAfterPass', 'true'); 65 } 69 66 </script> 70 67 71 68 <body onload="runtest()"> 72 69 73 Test that we can get an NPObject returned through a method on74 an NPAPI Object.<P>70 Test that we can get an NPObject returned through a method on 71 an NPAPI Object.<P> 75 72 76 Prints "SUCCESS" on success, "FAILURE" on failure. 77 78 <embed name="plug" type="application/x-webkit-test-netscape"> 79 80 <div id=output>FAILURE</div> 81 73 <embed name="plug" type="application/x-webkit-test-netscape"> 82 74 </body> 83 -
trunk/Source/JavaScriptCore/ChangeLog
r233167 r233184 1 2018-06-25 Saam Barati <sbarati@apple.com> 2 3 JSImmutableButterfly can't be allocated from a subspace with HeapCell::Kind::Auxiliary 4 https://bugs.webkit.org/show_bug.cgi?id=186878 5 <rdar://problem/40568659> 6 7 Reviewed by Mark Lam. 8 9 This patch fixes a bug in our JSImmutableButterfly implementation uncovered by 10 our stress GC bots. Before this patch, JSImmutableButterfly was allocated 11 with HeapCell::Kind::Auxiliary. This is wrong. Things that are JSCells must be 12 allocated from HeapCell::Kind::JSCell. The way this broke on the stress GC 13 bots is that our conservative marking won't do cell marking for things that 14 are Auxiliary. This means that if the stack is the only thing pointing to a 15 JSImmutableButterfly when a GC took place, that JSImmutableButterfly would 16 not be visited. This patch fixes this bug. This patch also extends our conservative 17 marking to understand that there may be interior pointers to things that are HeapCell::Kind::JSCell. 18 19 * bytecompiler/NodesCodegen.cpp: 20 (JSC::ArrayNode::emitBytecode): 21 * heap/HeapUtil.h: 22 (JSC::HeapUtil::findGCObjectPointersForMarking): 23 * runtime/JSImmutableButterfly.h: 24 (JSC::JSImmutableButterfly::subspaceFor): 25 1 26 2018-06-25 Mark Lam <mark.lam@apple.com> 2 27 -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r233122 r233184 407 407 if (length && !hadVariableExpression) { 408 408 recommendedIndexingType |= CopyOnWrite; 409 ASSERT(generator.vm()->heap.isDeferred()); // We run bytecode generator under a DeferGC. If we stopped doing that, we'd need to put a DeferGC here as we filled in these slots. 409 410 auto* array = JSImmutableButterfly::create(*generator.vm(), recommendedIndexingType, length); 410 411 unsigned index = 0; -
trunk/Source/JavaScriptCore/heap/HeapUtil.h
r227717 r233184 88 88 MarkedBlock* previousCandidate = MarkedBlock::blockFor(previousPointer); 89 89 if (!filter.ruleOut(bitwise_cast<Bits>(previousCandidate)) 90 && set.contains(previousCandidate) 91 && previousCandidate->handle().cellKind() == HeapCell::Auxiliary) { 90 && set.contains(previousCandidate)) { 92 91 previousPointer = static_cast<char*>(previousCandidate->handle().cellAlign(previousPointer)); 93 92 if (previousCandidate->handle().isLiveCell(markingVersion, newlyAllocatedVersion, isMarking, previousPointer)) … … 104 103 return; 105 104 106 HeapCell::Kind cellKind = candidate->handle().cellKind(); 105 MarkedBlock::Handle& handle = candidate->handle(); 106 HeapCell::Kind cellKind = handle.cellKind(); 107 107 108 108 auto tryPointer = [&] (void* pointer) { 109 if ( candidate->handle().isLiveCell(markingVersion, newlyAllocatedVersion, isMarking, pointer))109 if (handle.isLiveCell(markingVersion, newlyAllocatedVersion, isMarking, pointer)) 110 110 func(pointer, cellKind); 111 111 }; 112 112 113 if (candidate->handle().cellKind() == HeapCell::JSCell) {114 if (!MarkedBlock::isAtomAligned(pointer))115 return;116 117 tryPointer(pointer);118 return;119 }120 121 113 // A butterfly could point into the middle of an object. 122 char* alignedPointer = static_cast<char*>( candidate->handle().cellAlign(pointer));114 char* alignedPointer = static_cast<char*>(handle.cellAlign(pointer)); 123 115 tryPointer(alignedPointer); 124 116 -
trunk/Source/JavaScriptCore/runtime/JSImmutableButterfly.h
r232954 r233184 90 90 { 91 91 // We allocate out of the JSValue gigacage as other code expects all butterflies to live there. 92 return &vm.jsValueGigacage AuxiliarySpace;92 return &vm.jsValueGigacageCellSpace; 93 93 } 94 94
Note: See TracChangeset
for help on using the changeset viewer.