mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 950927 - Don't forward Ion elements pointers until end of minor collection r=terrence
This commit is contained in:
parent
cdc32441f8
commit
1a00d3db97
@ -16,6 +16,9 @@
|
||||
|
||||
#include "gc/GCInternals.h"
|
||||
#include "gc/Memory.h"
|
||||
#ifdef JS_ION
|
||||
#include "jit/IonFrames.h"
|
||||
#endif
|
||||
#include "vm/ArrayObject.h"
|
||||
#include "vm/Debugger.h"
|
||||
#if defined(DEBUG)
|
||||
@ -348,6 +351,15 @@ js::Nursery::setElementsForwardingPointer(ObjectElements *oldHeader, ObjectEleme
|
||||
*reinterpret_cast<HeapSlot **>(oldHeader->elements()) = newHeader->elements();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool IsWriteableAddress(void *ptr)
|
||||
{
|
||||
volatile uint64_t *vPtr = reinterpret_cast<volatile uint64_t *>(ptr);
|
||||
*vPtr = *vPtr;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
js::Nursery::forwardBufferPointer(HeapSlot **pSlotsElems)
|
||||
{
|
||||
@ -366,6 +378,7 @@ js::Nursery::forwardBufferPointer(HeapSlot **pSlotsElems)
|
||||
*/
|
||||
*pSlotsElems = *reinterpret_cast<HeapSlot **>(old);
|
||||
JS_ASSERT(!isInside(*pSlotsElems));
|
||||
JS_ASSERT(IsWriteableAddress(*pSlotsElems));
|
||||
}
|
||||
|
||||
// Structure for counting how many times objects of a particular type have been
|
||||
@ -646,6 +659,11 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList
|
||||
TenureCountCache tenureCounts;
|
||||
collectToFixedPoint(&trc, tenureCounts);
|
||||
|
||||
#ifdef JS_ION
|
||||
/* Update any slot or element pointers whose destination has been tenured. */
|
||||
js::jit::UpdateJitActivationsForMinorGC(rt, &trc);
|
||||
#endif
|
||||
|
||||
/* Resize the nursery. */
|
||||
double promotionRate = trc.tenuredSize / double(allocationEnd() - start());
|
||||
if (promotionRate > 0.05)
|
||||
|
31
js/src/jit-test/tests/gc/bug-950927.js
Normal file
31
js/src/jit-test/tests/gc/bug-950927.js
Normal file
@ -0,0 +1,31 @@
|
||||
var lfcode = new Array();
|
||||
lfcode.push("\
|
||||
var optionNames = options().split(',');\
|
||||
for (var i = 0; i < optionNames.length; i++) {}\
|
||||
");
|
||||
lfcode.push("gczeal(7,5);");
|
||||
lfcode.push("4");
|
||||
lfcode.push("\
|
||||
var S = new Array();\
|
||||
var x = 1;\
|
||||
for ( var i = 8; i >= 0; i-- ) {\
|
||||
S[0] += ' ';\
|
||||
S[0] += ',';\
|
||||
}\
|
||||
eval(S);\
|
||||
");
|
||||
var lfRunTypeId = -1;
|
||||
while (true) {
|
||||
var file = lfcode.shift(); if (file == undefined) { break; }
|
||||
loadFile(file)
|
||||
}
|
||||
function loadFile(lfVarx) {
|
||||
if (lfVarx.substr(-3) != ".js" && lfVarx.length != 1) {
|
||||
switch (lfRunTypeId) {
|
||||
case 4: eval("(function() { " + lfVarx + " })();"); break;
|
||||
default: evaluate(lfVarx, { noScriptRval : true }); break;
|
||||
}
|
||||
} else if (!isNaN(lfVarx)) {
|
||||
lfRunTypeId = parseInt(lfVarx);
|
||||
}
|
||||
}
|
@ -887,27 +887,54 @@ MarkIonJSFrame(JSTracer *trc, const IonFrameIterator &frame)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (trc->runtime->isHeapMinorCollecting()) {
|
||||
// Minor GCs may move slots/elements allocated in the nursery. Update
|
||||
// any slots/elements pointers stored in this frame.
|
||||
static void
|
||||
UpdateIonJSFrameForMinorGC(JSTracer *trc, const IonFrameIterator &frame)
|
||||
{
|
||||
// Minor GCs may move slots/elements allocated in the nursery. Update
|
||||
// any slots/elements pointers stored in this frame.
|
||||
|
||||
GeneralRegisterSet slotsRegs = safepoint.slotsOrElementsSpills();
|
||||
spill = frame.spillBase();
|
||||
for (GeneralRegisterBackwardIterator iter(safepoint.allGprSpills()); iter.more(); iter++) {
|
||||
--spill;
|
||||
if (slotsRegs.has(*iter))
|
||||
trc->runtime->gcNursery.forwardBufferPointer(reinterpret_cast<HeapSlot **>(spill));
|
||||
}
|
||||
IonJSFrameLayout *layout = (IonJSFrameLayout *)frame.fp();
|
||||
|
||||
while (safepoint.getSlotsOrElementsSlot(&slot)) {
|
||||
HeapSlot **slots = reinterpret_cast<HeapSlot **>(layout->slotRef(slot));
|
||||
trc->runtime->gcNursery.forwardBufferPointer(slots);
|
||||
}
|
||||
IonScript *ionScript = nullptr;
|
||||
if (frame.checkInvalidation(&ionScript)) {
|
||||
// This frame has been invalidated, meaning that its IonScript is no
|
||||
// longer reachable through the callee token (JSFunction/JSScript->ion
|
||||
// is now nullptr or recompiled).
|
||||
} else if (CalleeTokenIsFunction(layout->calleeToken())) {
|
||||
ionScript = CalleeTokenToFunction(layout->calleeToken())->nonLazyScript()->ionScript();
|
||||
} else {
|
||||
ionScript = CalleeTokenToScript(layout->calleeToken())->ionScript();
|
||||
}
|
||||
|
||||
const SafepointIndex *si = ionScript->getSafepointIndex(frame.returnAddressToFp());
|
||||
SafepointReader safepoint(ionScript, si);
|
||||
|
||||
GeneralRegisterSet slotsRegs = safepoint.slotsOrElementsSpills();
|
||||
uintptr_t *spill = frame.spillBase();
|
||||
for (GeneralRegisterBackwardIterator iter(safepoint.allGprSpills()); iter.more(); iter++) {
|
||||
--spill;
|
||||
if (slotsRegs.has(*iter))
|
||||
trc->runtime->gcNursery.forwardBufferPointer(reinterpret_cast<HeapSlot **>(spill));
|
||||
}
|
||||
|
||||
// Skip to the right place in the safepoint
|
||||
uint32_t slot;
|
||||
while (safepoint.getGcSlot(&slot));
|
||||
while (safepoint.getValueSlot(&slot));
|
||||
#ifdef JS_NUNBOX32
|
||||
LAllocation type, payload;
|
||||
while (safepoint.getNunboxSlot(&type, &payload));
|
||||
#endif
|
||||
|
||||
while (safepoint.getSlotsOrElementsSlot(&slot)) {
|
||||
HeapSlot **slots = reinterpret_cast<HeapSlot **>(layout->slotRef(slot));
|
||||
trc->runtime->gcNursery.forwardBufferPointer(slots);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
MarkBaselineStubFrame(JSTracer *trc, const IonFrameIterator &frame)
|
||||
@ -1165,6 +1192,20 @@ MarkJitActivations(JSRuntime *rt, JSTracer *trc)
|
||||
MarkJitActivation(trc, activations);
|
||||
}
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
void
|
||||
UpdateJitActivationsForMinorGC(JSRuntime *rt, JSTracer *trc)
|
||||
{
|
||||
JS_ASSERT(trc->runtime->isHeapMinorCollecting());
|
||||
for (JitActivationIterator activations(rt); !activations.done(); ++activations) {
|
||||
for (IonFrameIterator frames(activations); !frames.done(); ++frames) {
|
||||
if (frames.type() == IonFrame_OptimizedJS)
|
||||
UpdateIonJSFrameForMinorGC(trc, frames);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
AutoTempAllocatorRooter::trace(JSTracer *trc)
|
||||
{
|
||||
|
@ -268,6 +268,10 @@ void EnsureExitFrame(IonCommonFrameLayout *frame);
|
||||
void MarkJitActivations(JSRuntime *rt, JSTracer *trc);
|
||||
void MarkIonCompilerRoots(JSTracer *trc);
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
void UpdateJitActivationsForMinorGC(JSRuntime *rt, JSTracer *trc);
|
||||
#endif
|
||||
|
||||
static inline uint32_t
|
||||
MakeFrameDescriptor(uint32_t frameSize, FrameType type)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user