Bug 950927 - Don't forward Ion elements pointers until end of minor collection r=terrence

This commit is contained in:
Jon Coppeard 2014-01-14 14:51:08 +00:00
parent cdc32441f8
commit 1a00d3db97
4 changed files with 108 additions and 14 deletions

View File

@ -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)

View 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);
}
}

View File

@ -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)
{

View File

@ -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)
{