mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-06 07:48:38 +09:00
Issue #2155 - Move NestableControl classes except ForOfLoopControl to BytecodeControlStructures.{cpp.h}
Based-on: m-c 1460489/3
This commit is contained in:
parent
81691afbc3
commit
a8ac1cac3d
5 changed files with 277 additions and 237 deletions
84
js/src/frontend/BytecodeControlStructures.cpp
Normal file
84
js/src/frontend/BytecodeControlStructures.cpp
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "frontend/BytecodeControlStructures.h"
|
||||
|
||||
#include "frontend/BytecodeEmitter.h"
|
||||
#include "frontend/EmitterScope.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::frontend;
|
||||
|
||||
NestableControl::NestableControl(BytecodeEmitter* bce, StatementKind kind)
|
||||
: Nestable<NestableControl>(&bce->innermostNestableControl),
|
||||
kind_(kind),
|
||||
emitterScope_(bce->innermostEmitterScopeNoCheck())
|
||||
{}
|
||||
|
||||
BreakableControl::BreakableControl(BytecodeEmitter* bce, StatementKind kind)
|
||||
: NestableControl(bce, kind)
|
||||
{
|
||||
MOZ_ASSERT(is<BreakableControl>());
|
||||
}
|
||||
|
||||
bool
|
||||
BreakableControl::patchBreaks(BytecodeEmitter* bce)
|
||||
{
|
||||
return bce->emitJumpTargetAndPatch(breaks);
|
||||
}
|
||||
|
||||
LabelControl::LabelControl(BytecodeEmitter* bce, JSAtom* label, ptrdiff_t startOffset)
|
||||
: BreakableControl(bce, StatementKind::Label),
|
||||
label_(bce->cx, label),
|
||||
startOffset_(startOffset)
|
||||
{}
|
||||
|
||||
LoopControl::LoopControl(BytecodeEmitter* bce, StatementKind loopKind)
|
||||
: BreakableControl(bce, loopKind),
|
||||
tdzCache_(bce),
|
||||
continueTarget({ -1 })
|
||||
{
|
||||
MOZ_ASSERT(is<LoopControl>());
|
||||
|
||||
LoopControl* enclosingLoop = findNearest<LoopControl>(enclosing());
|
||||
|
||||
stackDepth_ = bce->stackDepth;
|
||||
loopDepth_ = enclosingLoop ? enclosingLoop->loopDepth_ + 1 : 1;
|
||||
|
||||
int loopSlots;
|
||||
if (loopKind == StatementKind::Spread || loopKind == StatementKind::ForOfLoop)
|
||||
loopSlots = 3;
|
||||
else if (loopKind == StatementKind::ForInLoop)
|
||||
loopSlots = 2;
|
||||
else
|
||||
loopSlots = 0;
|
||||
|
||||
MOZ_ASSERT(loopSlots <= stackDepth_);
|
||||
|
||||
if (enclosingLoop) {
|
||||
canIonOsr_ = (enclosingLoop->canIonOsr_ &&
|
||||
stackDepth_ == enclosingLoop->stackDepth_ + loopSlots);
|
||||
} else {
|
||||
canIonOsr_ = stackDepth_ == loopSlots;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
LoopControl::patchBreaksAndContinues(BytecodeEmitter* bce)
|
||||
{
|
||||
MOZ_ASSERT(continueTarget.offset != -1);
|
||||
if (!patchBreaks(bce))
|
||||
return false;
|
||||
bce->patchJumpsToTarget(continues, continueTarget);
|
||||
return true;
|
||||
}
|
||||
|
||||
TryFinallyControl::TryFinallyControl(BytecodeEmitter* bce, StatementKind kind)
|
||||
: NestableControl(bce, kind),
|
||||
emittingSubroutine_(false)
|
||||
{
|
||||
MOZ_ASSERT(is<TryFinallyControl>());
|
||||
}
|
||||
175
js/src/frontend/BytecodeControlStructures.h
Normal file
175
js/src/frontend/BytecodeControlStructures.h
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef frontend_BytecodeControlStructures_h
|
||||
#define frontend_BytecodeControlStructures_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ds/Nestable.h"
|
||||
#include "frontend/JumpList.h"
|
||||
#include "frontend/SharedContext.h"
|
||||
#include "frontend/TDZCheckCache.h"
|
||||
#include "gc/Rooting.h"
|
||||
#include "vm/String.h"
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
struct BytecodeEmitter;
|
||||
class EmitterScope;
|
||||
|
||||
class NestableControl : public Nestable<NestableControl>
|
||||
{
|
||||
StatementKind kind_;
|
||||
|
||||
// The innermost scope when this was pushed.
|
||||
EmitterScope* emitterScope_;
|
||||
|
||||
protected:
|
||||
NestableControl(BytecodeEmitter* bce, StatementKind kind);
|
||||
|
||||
public:
|
||||
using Nestable<NestableControl>::enclosing;
|
||||
using Nestable<NestableControl>::findNearest;
|
||||
|
||||
StatementKind kind() const {
|
||||
return kind_;
|
||||
}
|
||||
|
||||
EmitterScope* emitterScope() const {
|
||||
return emitterScope_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool is() const;
|
||||
|
||||
template <typename T>
|
||||
T& as() {
|
||||
MOZ_ASSERT(this->is<T>());
|
||||
return static_cast<T&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class BreakableControl : public NestableControl
|
||||
{
|
||||
public:
|
||||
// Offset of the last break.
|
||||
JumpList breaks;
|
||||
|
||||
BreakableControl(BytecodeEmitter* bce, StatementKind kind);
|
||||
|
||||
MOZ_MUST_USE bool patchBreaks(BytecodeEmitter* bce);
|
||||
};
|
||||
template <>
|
||||
inline bool
|
||||
NestableControl::is<BreakableControl>() const
|
||||
{
|
||||
return StatementKindIsUnlabeledBreakTarget(kind_) || kind_ == StatementKind::Label;
|
||||
}
|
||||
|
||||
class LabelControl : public BreakableControl
|
||||
{
|
||||
RootedAtom label_;
|
||||
|
||||
// The code offset when this was pushed. Used for effectfulness checking.
|
||||
ptrdiff_t startOffset_;
|
||||
|
||||
public:
|
||||
LabelControl(BytecodeEmitter* bce, JSAtom* label, ptrdiff_t startOffset);
|
||||
|
||||
HandleAtom label() const {
|
||||
return label_;
|
||||
}
|
||||
|
||||
ptrdiff_t startOffset() const {
|
||||
return startOffset_;
|
||||
}
|
||||
};
|
||||
template <>
|
||||
inline bool
|
||||
NestableControl::is<LabelControl>() const
|
||||
{
|
||||
return kind_ == StatementKind::Label;
|
||||
}
|
||||
|
||||
class LoopControl : public BreakableControl
|
||||
{
|
||||
// Loops' children are emitted in dominance order, so they can always
|
||||
// have a TDZCheckCache.
|
||||
TDZCheckCache tdzCache_;
|
||||
|
||||
// Stack depth when this loop was pushed on the control stack.
|
||||
int32_t stackDepth_;
|
||||
|
||||
// The loop nesting depth. Used as a hint to Ion.
|
||||
uint32_t loopDepth_;
|
||||
|
||||
// Can we OSR into Ion from here? True unless there is non-loop state on the stack.
|
||||
bool canIonOsr_;
|
||||
|
||||
public:
|
||||
// The target of continue statement jumps, e.g., the update portion of a
|
||||
// for(;;) loop.
|
||||
JumpTarget continueTarget;
|
||||
|
||||
// Offset of the last continue in the loop.
|
||||
JumpList continues;
|
||||
|
||||
LoopControl(BytecodeEmitter* bce, StatementKind loopKind);
|
||||
|
||||
uint32_t loopDepth() const {
|
||||
return loopDepth_;
|
||||
}
|
||||
|
||||
bool canIonOsr() const {
|
||||
return canIonOsr_;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool patchBreaksAndContinues(BytecodeEmitter* bce);
|
||||
};
|
||||
template <>
|
||||
inline bool
|
||||
NestableControl::is<LoopControl>() const
|
||||
{
|
||||
return StatementKindIsLoop(kind_);
|
||||
}
|
||||
|
||||
class TryFinallyControl : public NestableControl
|
||||
{
|
||||
bool emittingSubroutine_;
|
||||
|
||||
public:
|
||||
// The subroutine when emitting a finally block.
|
||||
JumpList gosubs;
|
||||
|
||||
// Offset of the last catch guard, if any.
|
||||
JumpList guardJump;
|
||||
|
||||
TryFinallyControl(BytecodeEmitter* bce, StatementKind kind);
|
||||
|
||||
void setEmittingSubroutine() {
|
||||
emittingSubroutine_ = true;
|
||||
}
|
||||
|
||||
bool emittingSubroutine() const {
|
||||
return emittingSubroutine_;
|
||||
}
|
||||
};
|
||||
template <>
|
||||
inline bool
|
||||
NestableControl::is<TryFinallyControl>() const
|
||||
{
|
||||
return kind_ == StatementKind::Try || kind_ == StatementKind::Finally;
|
||||
}
|
||||
|
||||
} /* namespace frontend */
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* frontend_BytecodeControlStructures_h */
|
||||
|
|
@ -28,6 +28,7 @@
|
|||
#include "jsutil.h"
|
||||
|
||||
#include "ds/Nestable.h"
|
||||
#include "frontend/BytecodeControlStructures.h"
|
||||
#include "frontend/CallOrNewEmitter.h"
|
||||
#include "frontend/ElemOpEmitter.h"
|
||||
#include "frontend/EmitterScope.h"
|
||||
|
|
@ -62,11 +63,6 @@ using mozilla::NumberIsInt32;
|
|||
using mozilla::PodCopy;
|
||||
using mozilla::Some;
|
||||
|
||||
class BreakableControl;
|
||||
class LabelControl;
|
||||
class LoopControl;
|
||||
class ForOfLoopControl;
|
||||
class TryFinallyControl;
|
||||
class OptionalEmitter;
|
||||
|
||||
static bool
|
||||
|
|
@ -89,222 +85,6 @@ GetCallArgsAndCount(ParseNode* callNode, ParseNode** argumentNode)
|
|||
return callNode->pn_count - 1;
|
||||
}
|
||||
|
||||
class BytecodeEmitter::NestableControl : public Nestable<BytecodeEmitter::NestableControl>
|
||||
{
|
||||
StatementKind kind_;
|
||||
|
||||
// The innermost scope when this was pushed.
|
||||
EmitterScope* emitterScope_;
|
||||
|
||||
protected:
|
||||
NestableControl(BytecodeEmitter* bce, StatementKind kind)
|
||||
: Nestable<NestableControl>(&bce->innermostNestableControl),
|
||||
kind_(kind),
|
||||
emitterScope_(bce->innermostEmitterScopeNoCheck())
|
||||
{ }
|
||||
|
||||
public:
|
||||
using Nestable<NestableControl>::enclosing;
|
||||
using Nestable<NestableControl>::findNearest;
|
||||
|
||||
StatementKind kind() const {
|
||||
return kind_;
|
||||
}
|
||||
|
||||
EmitterScope* emitterScope() const {
|
||||
return emitterScope_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool is() const;
|
||||
|
||||
template <typename T>
|
||||
T& as() {
|
||||
MOZ_ASSERT(this->is<T>());
|
||||
return static_cast<T&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
// Template specializations are disallowed in different namespaces; specialize
|
||||
// all the NestableControl subtypes up front.
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
template <>
|
||||
bool
|
||||
BytecodeEmitter::NestableControl::is<BreakableControl>() const
|
||||
{
|
||||
return StatementKindIsUnlabeledBreakTarget(kind_) || kind_ == StatementKind::Label;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
BytecodeEmitter::NestableControl::is<LabelControl>() const
|
||||
{
|
||||
return kind_ == StatementKind::Label;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
BytecodeEmitter::NestableControl::is<LoopControl>() const
|
||||
{
|
||||
return StatementKindIsLoop(kind_);
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
BytecodeEmitter::NestableControl::is<ForOfLoopControl>() const
|
||||
{
|
||||
return kind_ == StatementKind::ForOfLoop;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
BytecodeEmitter::NestableControl::is<TryFinallyControl>() const
|
||||
{
|
||||
return kind_ == StatementKind::Try || kind_ == StatementKind::Finally;
|
||||
}
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace js
|
||||
|
||||
class BreakableControl : public BytecodeEmitter::NestableControl
|
||||
{
|
||||
public:
|
||||
// Offset of the last break.
|
||||
JumpList breaks;
|
||||
|
||||
BreakableControl(BytecodeEmitter* bce, StatementKind kind)
|
||||
: NestableControl(bce, kind)
|
||||
{
|
||||
MOZ_ASSERT(is<BreakableControl>());
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool patchBreaks(BytecodeEmitter* bce) {
|
||||
return bce->emitJumpTargetAndPatch(breaks);
|
||||
}
|
||||
};
|
||||
|
||||
class LabelControl : public BreakableControl
|
||||
{
|
||||
RootedAtom label_;
|
||||
|
||||
// The code offset when this was pushed. Used for effectfulness checking.
|
||||
ptrdiff_t startOffset_;
|
||||
|
||||
public:
|
||||
LabelControl(BytecodeEmitter* bce, JSAtom* label, ptrdiff_t startOffset)
|
||||
: BreakableControl(bce, StatementKind::Label),
|
||||
label_(bce->cx, label),
|
||||
startOffset_(startOffset)
|
||||
{ }
|
||||
|
||||
HandleAtom label() const {
|
||||
return label_;
|
||||
}
|
||||
|
||||
ptrdiff_t startOffset() const {
|
||||
return startOffset_;
|
||||
}
|
||||
};
|
||||
|
||||
class LoopControl : public BreakableControl
|
||||
{
|
||||
// Loops' children are emitted in dominance order, so they can always
|
||||
// have a TDZCheckCache.
|
||||
TDZCheckCache tdzCache_;
|
||||
|
||||
// Stack depth when this loop was pushed on the control stack.
|
||||
int32_t stackDepth_;
|
||||
|
||||
// The loop nesting depth. Used as a hint to Ion.
|
||||
uint32_t loopDepth_;
|
||||
|
||||
// Can we OSR into Ion from here? True unless there is non-loop state on the stack.
|
||||
bool canIonOsr_;
|
||||
|
||||
public:
|
||||
// The target of continue statement jumps, e.g., the update portion of a
|
||||
// for(;;) loop.
|
||||
JumpTarget continueTarget;
|
||||
|
||||
// Offset of the last continue in the loop.
|
||||
JumpList continues;
|
||||
|
||||
LoopControl(BytecodeEmitter* bce, StatementKind loopKind)
|
||||
: BreakableControl(bce, loopKind),
|
||||
tdzCache_(bce),
|
||||
continueTarget({ -1 })
|
||||
{
|
||||
MOZ_ASSERT(is<LoopControl>());
|
||||
|
||||
LoopControl* enclosingLoop = findNearest<LoopControl>(enclosing());
|
||||
|
||||
stackDepth_ = bce->stackDepth;
|
||||
loopDepth_ = enclosingLoop ? enclosingLoop->loopDepth_ + 1 : 1;
|
||||
|
||||
int loopSlots;
|
||||
if (loopKind == StatementKind::Spread || loopKind == StatementKind::ForOfLoop)
|
||||
loopSlots = 3;
|
||||
else if (loopKind == StatementKind::ForInLoop)
|
||||
loopSlots = 2;
|
||||
else
|
||||
loopSlots = 0;
|
||||
|
||||
MOZ_ASSERT(loopSlots <= stackDepth_);
|
||||
|
||||
if (enclosingLoop) {
|
||||
canIonOsr_ = (enclosingLoop->canIonOsr_ &&
|
||||
stackDepth_ == enclosingLoop->stackDepth_ + loopSlots);
|
||||
} else {
|
||||
canIonOsr_ = stackDepth_ == loopSlots;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t loopDepth() const {
|
||||
return loopDepth_;
|
||||
}
|
||||
|
||||
bool canIonOsr() const {
|
||||
return canIonOsr_;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool patchBreaksAndContinues(BytecodeEmitter* bce) {
|
||||
MOZ_ASSERT(continueTarget.offset != -1);
|
||||
if (!patchBreaks(bce))
|
||||
return false;
|
||||
bce->patchJumpsToTarget(continues, continueTarget);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class TryFinallyControl : public BytecodeEmitter::NestableControl
|
||||
{
|
||||
bool emittingSubroutine_;
|
||||
|
||||
public:
|
||||
// The subroutine when emitting a finally block.
|
||||
JumpList gosubs;
|
||||
|
||||
// Offset of the last catch guard, if any.
|
||||
JumpList guardJump;
|
||||
|
||||
TryFinallyControl(BytecodeEmitter* bce, StatementKind kind)
|
||||
: NestableControl(bce, kind),
|
||||
emittingSubroutine_(false)
|
||||
{
|
||||
MOZ_ASSERT(is<TryFinallyControl>());
|
||||
}
|
||||
|
||||
void setEmittingSubroutine() {
|
||||
emittingSubroutine_ = true;
|
||||
}
|
||||
|
||||
bool emittingSubroutine() const {
|
||||
return emittingSubroutine_;
|
||||
}
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS TryEmitter
|
||||
{
|
||||
public:
|
||||
|
|
@ -898,6 +678,19 @@ class ForOfLoopControl : public LoopControl
|
|||
}
|
||||
};
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
template <>
|
||||
bool
|
||||
NestableControl::is<ForOfLoopControl>() const
|
||||
{
|
||||
return kind_ == StatementKind::ForOfLoop;
|
||||
}
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace js
|
||||
|
||||
BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
|
||||
Parser<FullParseHandler>* parser, SharedContext* sc,
|
||||
HandleScript script, Handle<LazyScript*> lazyScript,
|
||||
|
|
@ -958,13 +751,6 @@ BytecodeEmitter::init()
|
|||
return atomIndices.acquire(cx);
|
||||
}
|
||||
|
||||
template <typename Predicate /* (NestableControl*) -> bool */>
|
||||
BytecodeEmitter::NestableControl*
|
||||
BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const
|
||||
{
|
||||
return NestableControl::findNearest(innermostNestableControl, predicate);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T*
|
||||
BytecodeEmitter::findInnermostNestableControl() const
|
||||
|
|
@ -1463,7 +1249,7 @@ class NonLocalExitControl
|
|||
bce_->stackDepth = savedDepth_;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool prepareForNonLocalJump(BytecodeEmitter::NestableControl* target);
|
||||
MOZ_MUST_USE bool prepareForNonLocalJump(NestableControl* target);
|
||||
|
||||
MOZ_MUST_USE bool prepareForNonLocalJumpToOutermost() {
|
||||
return prepareForNonLocalJump(nullptr);
|
||||
|
|
@ -1494,10 +1280,8 @@ NonLocalExitControl::leaveScope(EmitterScope* es)
|
|||
* Emit additional bytecode(s) for non-local jumps.
|
||||
*/
|
||||
bool
|
||||
NonLocalExitControl::prepareForNonLocalJump(BytecodeEmitter::NestableControl* target)
|
||||
NonLocalExitControl::prepareForNonLocalJump(NestableControl* target)
|
||||
{
|
||||
using NestableControl = BytecodeEmitter::NestableControl;
|
||||
|
||||
EmitterScope* es = bce_->innermostEmitterScope();
|
||||
int npops = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -123,13 +123,12 @@ typedef Vector<jssrcnote, 64> SrcNotesVector;
|
|||
class CallOrNewEmitter;
|
||||
class ElemOpEmitter;
|
||||
class EmitterScope;
|
||||
class NestableControl;
|
||||
class PropOpEmitter;
|
||||
class TDZCheckCache;
|
||||
|
||||
struct MOZ_STACK_CLASS BytecodeEmitter
|
||||
{
|
||||
class NestableControl;
|
||||
|
||||
SharedContext* const sc; /* context shared between parsing and bytecode generation */
|
||||
|
||||
ExclusiveContext* const cx;
|
||||
|
|
@ -257,9 +256,6 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
|
||||
MOZ_MUST_USE bool init();
|
||||
|
||||
template <typename Predicate /* (NestableControl*) -> bool */>
|
||||
NestableControl* findInnermostNestableControl(Predicate predicate) const;
|
||||
|
||||
template <typename T>
|
||||
T* findInnermostNestableControl() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@ UNIFIED_SOURCES += [
|
|||
'ds/LifoAlloc.cpp',
|
||||
'ds/MemoryProtectionExceptionHandler.cpp',
|
||||
'frontend/BytecodeCompiler.cpp',
|
||||
'frontend/BytecodeControlStructures.cpp',
|
||||
'frontend/BytecodeEmitter.cpp',
|
||||
'frontend/CallOrNewEmitter.cpp',
|
||||
'frontend/ElemOpEmitter.cpp',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue