Bug 1661728: Remove ICScript::jitScript_ r=jandem

The bug here occurs when we:
a) Trial-inline A into B, creating an ICScript owned by B with a pointer to A's JitScript.
b) Perform a compacting GC, discarding the JitScript for A, but preserving the JitScript for B (because it is on the stack).
c) Create a new JitScript for A.
d) Warp-compile B, without hitting the B->A trial-inlined call IC.

In this case, the `JitScript*` stored in the ICScript created in `a)` is dangling, and does not match the JitScript created in `c)`.

The easy way to fix this is to not store a `JitScript*` here in the first place. We only use `ICScript::jitScript_` to:
a) Tell whether the ICScript is inlined, which can be done more easily by looking at the depth.
b) Find the `FallbackICStubSpace` for non-inlined ICScripts.

If we use the depth to tell when an ICScript is inlined, then we don't need a pointer to find the owning JitScript (and therefore its stub space) for non-inlined ICScripts. Non-inlined ICScripts are embedded inside a JitScript, so we can compute the offset directly.

Differential Revision: https://phabricator.services.mozilla.com/D88690
This commit is contained in:
Iain Ireland 2020-08-31 12:52:47 +00:00
Родитель 68abfa3c44
Коммит d12c86aa57
4 изменённых файлов: 18 добавлений и 22 удалений

Просмотреть файл

@ -62,8 +62,8 @@ JitScript::JitScript(JSScript* script, Offset typeSetOffset,
typeSetOffset_(typeSetOffset),
bytecodeTypeMapOffset_(bytecodeTypeMapOffset),
endOffset_(endOffset),
icScript_(this, script->getWarmUpCount(),
typeSetOffset - offsetOfICScript(), /*depth=*/0) {
icScript_(script->getWarmUpCount(), typeSetOffset - offsetOfICScript(),
/*depth=*/0) {
setTypesGeneration(script->zone()->types.generation);
if (IsTypeInferenceEnabled()) {
@ -269,8 +269,6 @@ void ICScript::trace(JSTracer* trc) {
}
}
bool ICScript::isInlined() const { return jitScript()->icScript() != this; }
bool ICScript::addInlinedChild(JSContext* cx, UniquePtr<ICScript> child,
uint32_t pcOffset) {
if (!inlinedChildren_) {
@ -877,8 +875,14 @@ InliningRoot* JitScript::getOrCreateInliningRoot(JSContext* cx,
}
FallbackICStubSpace* ICScript::fallbackStubSpace() {
if (inliningRoot_) {
if (isInlined()) {
return inliningRoot_->fallbackStubSpace();
}
return jitScript_->fallbackStubSpace();
return outerJitScript()->fallbackStubSpace();
}
JitScript* ICScript::outerJitScript() {
MOZ_ASSERT(!isInlined());
uint8_t* ptr = reinterpret_cast<uint8_t*>(this);
return reinterpret_cast<JitScript*>(ptr - JitScript::offsetOfICScript());
}

Просмотреть файл

@ -92,17 +92,14 @@ class InliningRoot;
class alignas(uintptr_t) ICScript final : public TrailingArray {
public:
ICScript(JitScript* jitScript, uint32_t warmUpCount, Offset endOffset,
uint32_t depth, InliningRoot* inliningRoot = nullptr)
: jitScript_(jitScript),
inliningRoot_(inliningRoot),
ICScript(uint32_t warmUpCount, Offset endOffset, uint32_t depth,
InliningRoot* inliningRoot = nullptr)
: inliningRoot_(inliningRoot),
warmUpCount_(warmUpCount),
endOffset_(endOffset),
depth_(depth) {}
JitScript* jitScript() const { return jitScript_; }
bool isInlined() const;
bool isInlined() const { return depth_ > 0; }
MOZ_MUST_USE bool initICEntries(JSContext* cx, JSScript* script);
@ -157,11 +154,6 @@ class alignas(uintptr_t) ICScript final : public TrailingArray {
uint32_t pcOffset_;
};
// Pointer to the owning JitScript. If this ICScript is not
// a clone for inlining, `this->jitScript_ + JitScript::offsetOfICScript()`
// should equal `this`.
JitScript* jitScript_;
// If this ICScript was created for trial inlining or has another
// ICScript inlined into it, a pointer to the root of the inlining
// tree. Otherwise, nullptr.
@ -186,6 +178,8 @@ class alignas(uintptr_t) ICScript final : public TrailingArray {
ICEntry* icEntries() { return offsetToPointer<ICEntry>(icEntriesOffset()); }
JitScript* outerJitScript();
friend class JitScript;
};

Просмотреть файл

@ -226,7 +226,6 @@ ICScript* TrialInliner::createInlinedICScript(JSFunction* target,
MOZ_ASSERT(target->hasJitScript());
JSScript* targetScript = target->baseScript()->asJSScript();
JitScript* targetJitScript = targetScript->jitScript();
// We don't have to check for overflow here because we have already
// successfully allocated an ICScript with this number of entries
@ -247,8 +246,8 @@ ICScript* TrialInliner::createInlinedICScript(JSFunction* target,
const uint32_t InitialWarmUpCount = 0;
uint32_t depth = icScript_->depth() + 1;
UniquePtr<ICScript> inlinedICScript(new (raw) ICScript(
targetJitScript, InitialWarmUpCount, allocSize, depth, root_));
UniquePtr<ICScript> inlinedICScript(
new (raw) ICScript(InitialWarmUpCount, allocSize, depth, root_));
{
// Suppress GC. This matches the AutoEnterAnalysis in

Просмотреть файл

@ -969,7 +969,6 @@ AbortReasonOr<bool> WarpScriptOracle::maybeInlineCallIC(
if (!TrialInliner::canInline(targetFunction, script_)) {
return false;
}
MOZ_ASSERT(targetScript->jitScript() == icScript->jitScript());
// Add the inlined script to the inline script tree.
LifoAlloc* lifoAlloc = alloc_.lifoAlloc();