Backed out 11 changesets (bug 1535994) for BytecodeEmitter.cpp related build bustages CLOSED TREE

Backed out changeset d5975f907521 (bug 1535994)
Backed out changeset e56d1810fb40 (bug 1535994)
Backed out changeset fdd1177e499a (bug 1535994)
Backed out changeset db520471b407 (bug 1535994)
Backed out changeset 096ab8585046 (bug 1535994)
Backed out changeset 8a480b0bbd05 (bug 1535994)
Backed out changeset 7c763b9a2118 (bug 1535994)
Backed out changeset 4f5084424c22 (bug 1535994)
Backed out changeset ee3359178d5f (bug 1535994)
Backed out changeset b77efa8567a2 (bug 1535994)
Backed out changeset 384cdd1ee833 (bug 1535994)
This commit is contained in:
Bogdan Tara 2019-04-10 12:30:10 +03:00
parent 93908a1360
commit bced020051
18 changed files with 344 additions and 522 deletions

View File

@ -41,7 +41,7 @@ LoopControl::LoopControl(BytecodeEmitter* bce, StatementKind loopKind)
LoopControl* enclosingLoop = findNearest<LoopControl>(enclosing());
stackDepth_ = bce->bytecodeSection().stackDepth();
stackDepth_ = bce->stackDepth;
loopDepth_ = enclosingLoop ? enclosingLoop->loopDepth_ + 1 : 1;
int loopSlots;
@ -81,7 +81,7 @@ bool LoopControl::emitContinueTarget(BytecodeEmitter* bce) {
bool LoopControl::emitSpecialBreakForDone(BytecodeEmitter* bce) {
// This doesn't pop stack values, nor handle any other controls.
// Should be called on the toplevel of the loop.
MOZ_ASSERT(bce->bytecodeSection().stackDepth() == stackDepth_);
MOZ_ASSERT(bce->stackDepth == stackDepth_);
MOZ_ASSERT(bce->innermostNestableControl == this);
if (!bce->newSrcNote(SRC_BREAK)) {
@ -109,7 +109,7 @@ bool LoopControl::emitLoopHead(BytecodeEmitter* bce,
}
}
head_ = {bce->bytecodeSection().offset()};
head_ = {bce->offset()};
ptrdiff_t off;
if (!bce->emitJumpTargetOp(JSOP_LOOPHEAD, &off)) {
return false;
@ -126,7 +126,7 @@ bool LoopControl::emitLoopEntry(BytecodeEmitter* bce,
}
}
JumpTarget entry = {bce->bytecodeSection().offset()};
JumpTarget entry = {bce->offset()};
bce->patchJumpsToTarget(entryJump_, entry);
MOZ_ASSERT(loopDepth_ > 0);
@ -135,8 +135,7 @@ bool LoopControl::emitLoopEntry(BytecodeEmitter* bce,
if (!bce->emitJumpTargetOp(JSOP_LOOPENTRY, &off)) {
return false;
}
SetLoopEntryDepthHintAndFlags(bce->bytecodeSection().code(off), loopDepth_,
canIonOsr_);
SetLoopEntryDepthHintAndFlags(bce->code(off), loopDepth_, canIonOsr_);
return true;
}

View File

@ -91,24 +91,6 @@ static bool ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn) {
kind == ParseNodeKind::Function;
}
BytecodeEmitter::BytecodeSection::BytecodeSection(JSContext* cx,
uint32_t lineNum)
: code_(cx),
notes_(cx),
tryNoteList_(cx),
scopeNoteList_(cx),
resumeOffsetList_(cx),
currentLine_(lineNum) {}
BytecodeEmitter::PerScriptData::PerScriptData(JSContext* cx)
: scopeList_(cx),
numberList_(cx),
atomIndices_(cx->frontendCollectionPool()) {}
bool BytecodeEmitter::PerScriptData::init(JSContext* cx) {
return atomIndices_.acquire(cx);
}
BytecodeEmitter::BytecodeEmitter(
BytecodeEmitter* parent, SharedContext* sc, HandleScript script,
Handle<LazyScript*> lazyScript, uint32_t lineNum, EmitterMode emitterMode,
@ -118,17 +100,23 @@ BytecodeEmitter::BytecodeEmitter(
parent(parent),
script(cx, script),
lazyScript(cx, lazyScript),
bytecodeSection_(cx, lineNum),
perScriptData_(cx),
code_(cx),
notes_(cx),
currentLine_(lineNum),
fieldInitializers_(fieldInitializers),
atomIndices(cx->frontendCollectionPool()),
firstLine(lineNum),
numberList(cx),
scopeList(cx),
tryNoteList(cx),
scopeNoteList(cx),
resumeOffsetList(cx),
emitterMode(emitterMode) {
MOZ_ASSERT_IF(emitterMode == LazyFunction, lazyScript);
if (sc->isFunctionBox()) {
// Functions have IC entries for type monitoring |this| and arguments.
bytecodeSection().setNumICEntries(sc->asFunctionBox()->function()->nargs() +
1);
numICEntries = sc->asFunctionBox()->function()->nargs() + 1;
}
}
@ -160,7 +148,7 @@ void BytecodeEmitter::initFromBodyPosition(TokenPos bodyPosition) {
setFunctionBodyEndPos(bodyPosition.end);
}
bool BytecodeEmitter::init() { return perScriptData_.init(cx); }
bool BytecodeEmitter::init() { return atomIndices.acquire(cx); }
template <typename T>
T* BytecodeEmitter::findInnermostNestableControl() const {
@ -206,7 +194,9 @@ bool BytecodeEmitter::markStepBreakpoint() {
// We track the location of the most recent separator for use in
// markSimpleBreakpoint. Note that this means that the position must already
// be set before markStepBreakpoint is called.
bytecodeSection().updateSeparatorPosition();
lastSeparatorOffet_ = code().length();
lastSeparatorLine_ = currentLine_;
lastSeparatorColumn_ = lastColumn_;
return true;
}
@ -220,7 +210,10 @@ bool BytecodeEmitter::markSimpleBreakpoint() {
// expression start, we need to skip marking it breakable in order to avoid
// having two breakpoints with the same line/column position.
// Note: This assumes that the position for the call has already been set.
if (!bytecodeSection().isDuplicateLocation()) {
bool isDuplicateLocation =
lastSeparatorLine_ == currentLine_ && lastSeparatorColumn_ == lastColumn_;
if (!isDuplicateLocation) {
if (!newSrcNote(SRC_BREAKPOINT)) {
return false;
}
@ -230,9 +223,9 @@ bool BytecodeEmitter::markSimpleBreakpoint() {
}
bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta, ptrdiff_t* offset) {
*offset = bytecodeSection().code().length();
*offset = code().length();
if (!bytecodeSection().code().growByUninitialized(delta)) {
if (!code().growByUninitialized(delta)) {
ReportOutOfMemory(cx);
return false;
}
@ -240,30 +233,30 @@ bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta, ptrdiff_t* offset) {
// If op is JOF_TYPESET (see the type barriers comment in TypeInference.h),
// reserve a type set to store its result.
if (CodeSpec[op].format & JOF_TYPESET) {
if (bytecodeSection().typesetCount() < JSScript::MaxBytecodeTypeSets) {
bytecodeSection().addTypesetCount();
if (typesetCount < JSScript::MaxBytecodeTypeSets) {
typesetCount++;
}
}
if (BytecodeOpHasIC(op)) {
bytecodeSection().addNumICEntries();
numICEntries++;
}
return true;
}
void BytecodeEmitter::BytecodeSection::updateDepth(ptrdiff_t target) {
void BytecodeEmitter::updateDepth(ptrdiff_t target) {
jsbytecode* pc = code(target);
int nuses = StackUses(pc);
int ndefs = StackDefs(pc);
stackDepth_ -= nuses;
MOZ_ASSERT(stackDepth_ >= 0);
stackDepth_ += ndefs;
stackDepth -= nuses;
MOZ_ASSERT(stackDepth >= 0);
stackDepth += ndefs;
if ((uint32_t)stackDepth_ > maxStackDepth_) {
maxStackDepth_ = stackDepth_;
if ((uint32_t)stackDepth > maxStackDepth) {
maxStackDepth = stackDepth;
}
}
@ -287,9 +280,9 @@ bool BytecodeEmitter::emit1(JSOp op) {
return false;
}
jsbytecode* code = bytecodeSection().code(offset);
jsbytecode* code = this->code(offset);
code[0] = jsbytecode(op);
bytecodeSection().updateDepth(offset);
updateDepth(offset);
return true;
}
@ -301,10 +294,10 @@ bool BytecodeEmitter::emit2(JSOp op, uint8_t op1) {
return false;
}
jsbytecode* code = bytecodeSection().code(offset);
jsbytecode* code = this->code(offset);
code[0] = jsbytecode(op);
code[1] = jsbytecode(op1);
bytecodeSection().updateDepth(offset);
updateDepth(offset);
return true;
}
@ -320,11 +313,11 @@ bool BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2) {
return false;
}
jsbytecode* code = bytecodeSection().code(offset);
jsbytecode* code = this->code(offset);
code[0] = jsbytecode(op);
code[1] = op1;
code[2] = op2;
bytecodeSection().updateDepth(offset);
updateDepth(offset);
return true;
}
@ -337,7 +330,7 @@ bool BytecodeEmitter::emitN(JSOp op, size_t extra, ptrdiff_t* offset) {
return false;
}
jsbytecode* code = bytecodeSection().code(off);
jsbytecode* code = this->code(off);
code[0] = jsbytecode(op);
/* The remaining |extra| bytes are set by the caller */
@ -346,7 +339,7 @@ bool BytecodeEmitter::emitN(JSOp op, size_t extra, ptrdiff_t* offset) {
* operand yet to be stored in the extra bytes after op.
*/
if (CodeSpec[op].nuses >= 0) {
bytecodeSection().updateDepth(off);
updateDepth(off);
}
if (offset) {
@ -358,7 +351,7 @@ bool BytecodeEmitter::emitN(JSOp op, size_t extra, ptrdiff_t* offset) {
bool BytecodeEmitter::emitJumpTargetOp(JSOp op, ptrdiff_t* off) {
MOZ_ASSERT(BytecodeIsJumpTarget(op));
size_t numEntries = bytecodeSection().numICEntries();
size_t numEntries = numICEntries;
if (MOZ_UNLIKELY(numEntries > UINT32_MAX)) {
reportError(nullptr, JSMSG_NEED_DIET, js_script_str);
return false;
@ -368,22 +361,21 @@ bool BytecodeEmitter::emitJumpTargetOp(JSOp op, ptrdiff_t* off) {
return false;
}
SET_ICINDEX(bytecodeSection().code(*off), numEntries);
SET_ICINDEX(code(*off), numEntries);
return true;
}
bool BytecodeEmitter::emitJumpTarget(JumpTarget* target) {
ptrdiff_t off = bytecodeSection().offset();
ptrdiff_t off = offset();
// Alias consecutive jump targets.
if (off == bytecodeSection().lastTargetOffset() +
ptrdiff_t(JSOP_JUMPTARGET_LENGTH)) {
target->offset = bytecodeSection().lastTargetOffset();
if (off == lastTarget.offset + ptrdiff_t(JSOP_JUMPTARGET_LENGTH)) {
target->offset = lastTarget.offset;
return true;
}
target->offset = off;
bytecodeSection().setLastTargetOffset(off);
lastTarget.offset = off;
ptrdiff_t opOff;
return emitJumpTargetOp(JSOP_JUMPTARGET, &opOff);
@ -395,11 +387,11 @@ bool BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump) {
return false;
}
jsbytecode* code = bytecodeSection().code(offset);
jsbytecode* code = this->code(offset);
code[0] = jsbytecode(op);
MOZ_ASSERT(-1 <= jump->offset && jump->offset < offset);
jump->push(bytecodeSection().code(0), offset);
bytecodeSection().updateDepth(offset);
jump->push(this->code(0), offset);
updateDepth(offset);
return true;
}
@ -433,12 +425,11 @@ bool BytecodeEmitter::emitBackwardJump(JSOp op, JumpTarget target,
}
void BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target) {
MOZ_ASSERT(-1 <= jump.offset && jump.offset <= bytecodeSection().offset());
MOZ_ASSERT(0 <= target.offset && target.offset <= bytecodeSection().offset());
MOZ_ASSERT_IF(
jump.offset != -1 && target.offset + 4 <= bytecodeSection().offset(),
BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset))));
jump.patchAll(bytecodeSection().code(0), target);
MOZ_ASSERT(-1 <= jump.offset && jump.offset <= offset());
MOZ_ASSERT(0 <= target.offset && target.offset <= offset());
MOZ_ASSERT_IF(jump.offset != -1 && target.offset + 4 <= offset(),
BytecodeIsJumpTarget(JSOp(*code(target.offset))));
jump.patchAll(code(0), target);
}
bool BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump) {
@ -468,7 +459,7 @@ bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn) {
}
bool BytecodeEmitter::emitDupAt(unsigned slotFromTop) {
MOZ_ASSERT(slotFromTop < unsigned(bytecodeSection().stackDepth()));
MOZ_ASSERT(slotFromTop < unsigned(stackDepth));
if (slotFromTop == 0) {
return emit1(JSOP_DUP);
@ -484,7 +475,7 @@ bool BytecodeEmitter::emitDupAt(unsigned slotFromTop) {
return false;
}
jsbytecode* pc = bytecodeSection().code(off);
jsbytecode* pc = code(off);
SET_UINT24(pc, slotFromTop);
return true;
}
@ -525,14 +516,14 @@ bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) {
ErrorReporter* er = &parser->errorReporter();
bool onThisLine;
if (!er->isOnThisLine(offset, bytecodeSection().currentLine(), &onThisLine)) {
if (!er->isOnThisLine(offset, currentLine(), &onThisLine)) {
er->errorNoOffset(JSMSG_OUT_OF_MEMORY);
return false;
}
if (!onThisLine) {
unsigned line = er->lineAt(offset);
unsigned delta = line - bytecodeSection().currentLine();
unsigned delta = line - currentLine();
/*
* Encode any change in the current source line number by using
@ -545,7 +536,7 @@ bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) {
* unsigned delta_ wrap to a very large number, which triggers a
* SRC_SETLINE.
*/
bytecodeSection().setCurrentLine(line);
setCurrentLine(line);
if (delta >= LengthOfSetLine(line)) {
if (!newSrcNote2(SRC_SETLINE, ptrdiff_t(line))) {
return false;
@ -558,7 +549,7 @@ bool BytecodeEmitter::updateLineNumberNotes(uint32_t offset) {
} while (--delta != 0);
}
bytecodeSection().updateSeparatorPositionIfPresent();
updateSeparatorPosition();
}
return true;
}
@ -575,8 +566,7 @@ bool BytecodeEmitter::updateSourceCoordNotes(uint32_t offset) {
}
uint32_t columnIndex = parser->errorReporter().columnAt(offset);
ptrdiff_t colspan =
ptrdiff_t(columnIndex) - ptrdiff_t(bytecodeSection().lastColumn());
ptrdiff_t colspan = ptrdiff_t(columnIndex) - ptrdiff_t(lastColumn_);
if (colspan != 0) {
// If the column span is so large that we can't store it, then just
// discard this information. This can happen with minimized or otherwise
@ -589,12 +579,20 @@ bool BytecodeEmitter::updateSourceCoordNotes(uint32_t offset) {
if (!newSrcNote2(SRC_COLSPAN, SN_COLSPAN_TO_OFFSET(colspan))) {
return false;
}
bytecodeSection().setLastColumn(columnIndex);
bytecodeSection().updateSeparatorPositionIfPresent();
lastColumn_ = columnIndex;
updateSeparatorPosition();
}
return true;
}
/* Updates the last separator position, if present */
void BytecodeEmitter::updateSeparatorPosition() {
if (!inPrologue() && lastSeparatorOffet_ == code().length()) {
lastSeparatorLine_ = currentLine_;
lastSeparatorColumn_ = lastColumn_;
}
}
Maybe<uint32_t> BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) {
if (!nextpn) {
return Nothing();
@ -628,7 +626,7 @@ bool BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand) {
if (!emitN(op, 4, &off)) {
return false;
}
SET_UINT32(bytecodeSection().code(off), operand);
SET_UINT32(code(off), operand);
return true;
}
@ -665,18 +663,17 @@ class NonLocalExitControl {
public:
NonLocalExitControl(BytecodeEmitter* bce, Kind kind)
: bce_(bce),
savedScopeNoteIndex_(bce->bytecodeSection().scopeNoteList().length()),
savedDepth_(bce->bytecodeSection().stackDepth()),
savedScopeNoteIndex_(bce->scopeNoteList.length()),
savedDepth_(bce->stackDepth),
openScopeNoteIndex_(bce->innermostEmitterScope()->noteIndex()),
kind_(kind) {}
~NonLocalExitControl() {
for (uint32_t n = savedScopeNoteIndex_;
n < bce_->bytecodeSection().scopeNoteList().length(); n++) {
bce_->bytecodeSection().scopeNoteList().recordEnd(
n, bce_->bytecodeSection().offset());
for (uint32_t n = savedScopeNoteIndex_; n < bce_->scopeNoteList.length();
n++) {
bce_->scopeNoteList.recordEnd(n, bce_->offset());
}
bce_->bytecodeSection().setStackDepth(savedDepth_);
bce_->stackDepth = savedDepth_;
}
MOZ_MUST_USE bool prepareForNonLocalJump(NestableControl* target);
@ -698,12 +695,11 @@ bool NonLocalExitControl::leaveScope(EmitterScope* es) {
if (es->enclosingInFrame()) {
enclosingScopeIndex = es->enclosingInFrame()->index();
}
if (!bce_->bytecodeSection().scopeNoteList().append(
enclosingScopeIndex, bce_->bytecodeSection().offset(),
openScopeNoteIndex_)) {
if (!bce_->scopeNoteList.append(enclosingScopeIndex, bce_->offset(),
openScopeNoteIndex_)) {
return false;
}
openScopeNoteIndex_ = bce_->bytecodeSection().scopeNoteList().length() - 1;
openScopeNoteIndex_ = bce_->scopeNoteList.length() - 1;
return true;
}
@ -842,7 +838,7 @@ bool NonLocalExitControl::prepareForNonLocalJump(NestableControl* target) {
}
// Close FOR_OF_ITERCLOSE trynotes.
ptrdiff_t end = bce_->bytecodeSection().offset();
ptrdiff_t end = bce_->offset();
for (ptrdiff_t start : forOfIterCloseScopeStarts) {
if (!bce_->addTryNote(JSTRY_FOR_OF_ITERCLOSE, 0, start, end)) {
return false;
@ -888,10 +884,10 @@ bool BytecodeEmitter::emitIndex32(JSOp op, uint32_t index) {
return false;
}
jsbytecode* code = bytecodeSection().code(offset);
jsbytecode* code = this->code(offset);
code[0] = jsbytecode(op);
SET_UINT32_INDEX(code, index);
bytecodeSection().updateDepth(offset);
updateDepth(offset);
return true;
}
@ -906,10 +902,10 @@ bool BytecodeEmitter::emitIndexOp(JSOp op, uint32_t index) {
return false;
}
jsbytecode* code = bytecodeSection().code(offset);
jsbytecode* code = this->code(offset);
code[0] = jsbytecode(op);
SET_UINT32_INDEX(code, index);
bytecodeSection().updateDepth(offset);
updateDepth(offset);
return true;
}
@ -944,24 +940,24 @@ bool BytecodeEmitter::emitAtomOp(uint32_t atomIndex, JSOp op) {
bool BytecodeEmitter::emitInternedScopeOp(uint32_t index, JSOp op) {
MOZ_ASSERT(JOF_OPTYPE(op) == JOF_SCOPE);
MOZ_ASSERT(index < perScriptData().scopeList().length());
MOZ_ASSERT(index < scopeList.length());
return emitIndex32(op, index);
}
bool BytecodeEmitter::emitInternedObjectOp(uint32_t index, JSOp op) {
MOZ_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT);
MOZ_ASSERT(index < perScriptData().objectList().length);
MOZ_ASSERT(index < objectList.length);
return emitIndex32(op, index);
}
bool BytecodeEmitter::emitObjectOp(ObjectBox* objbox, JSOp op) {
return emitInternedObjectOp(perScriptData().objectList().add(objbox), op);
return emitInternedObjectOp(objectList.add(objbox), op);
}
bool BytecodeEmitter::emitObjectPairOp(ObjectBox* objbox1, ObjectBox* objbox2,
JSOp op) {
uint32_t index = perScriptData().objectList().add(objbox1);
perScriptData().objectList().add(objbox2);
uint32_t index = objectList.add(objbox1);
objectList.add(objbox2);
return emitInternedObjectOp(index, op);
}
@ -978,7 +974,7 @@ bool BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot) {
return false;
}
SET_LOCALNO(bytecodeSection().code(off), slot);
SET_LOCALNO(code(off), slot);
return true;
}
@ -989,7 +985,7 @@ bool BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot) {
return false;
}
SET_ARGNO(bytecodeSection().code(off), slot);
SET_ARGNO(code(off), slot);
return true;
}
@ -1004,7 +1000,7 @@ bool BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec) {
return false;
}
jsbytecode* pc = bytecodeSection().code(off);
jsbytecode* pc = code(off);
SET_ENVCOORD_HOPS(pc, ec.hops());
pc += ENVCOORD_HOPS_LEN;
SET_ENVCOORD_SLOT(pc, ec.slot());
@ -1684,13 +1680,13 @@ bool BytecodeEmitter::emitNewInit() {
return false;
}
jsbytecode* code = bytecodeSection().code(offset);
jsbytecode* code = this->code(offset);
code[0] = JSOP_NEWINIT;
code[1] = 0;
code[2] = 0;
code[3] = 0;
code[4] = 0;
bytecodeSection().updateDepth(offset);
updateDepth(offset);
return true;
}
@ -1720,7 +1716,7 @@ bool BytecodeEmitter::iteratorResultShape(unsigned* shape) {
return false;
}
*shape = perScriptData().objectList().add(objbox);
*shape = objectList.add(objbox);
return true;
}
@ -2051,13 +2047,13 @@ bool BytecodeEmitter::emitNumberOp(double dval) {
if (!emitN(JSOP_UINT24, 3, &off)) {
return false;
}
SET_UINT24(bytecodeSection().code(off), u);
SET_UINT24(code(off), u);
} else {
ptrdiff_t off;
if (!emitN(JSOP_INT32, 4, &off)) {
return false;
}
SET_INT32(bytecodeSection().code(off), ival);
SET_INT32(code(off), ival);
}
return true;
}
@ -2258,13 +2254,13 @@ bool BytecodeEmitter::allocateResumeIndex(ptrdiff_t offset,
"resumeIndex * sizeof(uintptr_t) must fit in an int32. JIT code relies "
"on this when loading resume entries from BaselineScript");
*resumeIndex = bytecodeSection().resumeOffsetList().length();
*resumeIndex = resumeOffsetList.length();
if (*resumeIndex > MaxResumeIndex) {
reportError(nullptr, JSMSG_TOO_MANY_RESUME_INDEXES);
return false;
}
return bytecodeSection().resumeOffsetList().append(offset);
return resumeOffsetList.append(offset);
}
bool BytecodeEmitter::allocateResumeIndexRange(mozilla::Span<ptrdiff_t> offsets,
@ -2297,15 +2293,15 @@ bool BytecodeEmitter::emitYieldOp(JSOp op) {
}
if (op == JSOP_INITIALYIELD || op == JSOP_YIELD) {
bytecodeSection().addNumYields();
numYields++;
}
uint32_t resumeIndex;
if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) {
if (!allocateResumeIndex(offset(), &resumeIndex)) {
return false;
}
SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex);
SET_RESUMEINDEX(code(off), resumeIndex);
return emit1(JSOP_DEBUGAFTERYIELD);
}
@ -2573,7 +2569,7 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
}
#ifdef DEBUG
int depth = bytecodeSection().stackDepth();
int depth = stackDepth;
#endif
switch (target->getKind()) {
@ -2651,7 +2647,7 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind");
}
MOZ_ASSERT(bytecodeSection().stackDepth() == depth + int(*emitted));
MOZ_ASSERT(stackDepth == depth + int(*emitted));
return true;
}
@ -2814,7 +2810,7 @@ bool BytecodeEmitter::emitIteratorNext(
"can run user-modifiable iteration code");
// [stack] ... NEXT ITER
MOZ_ASSERT(bytecodeSection().stackDepth() >= 2);
MOZ_ASSERT(this->stackDepth >= 2);
if (!emitCall(JSOP_CALL, 0, callSourceCoordOffset)) {
// [stack] ... RESULT
@ -2837,7 +2833,7 @@ bool BytecodeEmitter::emitIteratorNext(
bool BytecodeEmitter::emitPushNotUndefinedOrNull() {
// [stack] V
MOZ_ASSERT(bytecodeSection().stackDepth() > 0);
MOZ_ASSERT(this->stackDepth > 0);
if (!emit1(JSOP_DUP)) {
// [stack] V V
@ -3085,7 +3081,7 @@ bool BytecodeEmitter::emitIteratorCloseInScope(
template <typename InnerEmitter>
bool BytecodeEmitter::wrapWithDestructuringTryNote(int32_t iterDepth,
InnerEmitter emitter) {
MOZ_ASSERT(bytecodeSection().stackDepth() >= iterDepth);
MOZ_ASSERT(this->stackDepth >= iterDepth);
// Pad a nop at the beginning of the bytecode covered by the trynote so
// that when unwinding environments, we may unwind to the scope
@ -3096,11 +3092,11 @@ bool BytecodeEmitter::wrapWithDestructuringTryNote(int32_t iterDepth,
return false;
}
ptrdiff_t start = bytecodeSection().offset();
ptrdiff_t start = offset();
if (!emitter(this)) {
return false;
}
ptrdiff_t end = bytecodeSection().offset();
ptrdiff_t end = offset();
if (start != end) {
return addTryNote(JSTRY_DESTRUCTURING, iterDepth, start, end);
}
@ -3206,7 +3202,7 @@ bool BytecodeEmitter::emitInitializer(ParseNode* initializer,
bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
DestructuringFlavor flav) {
MOZ_ASSERT(pattern->isKind(ParseNodeKind::ArrayExpr));
MOZ_ASSERT(bytecodeSection().stackDepth() != 0);
MOZ_ASSERT(this->stackDepth != 0);
// Here's pseudo code for |let [a, b, , c=y, ...d] = x;|
//
@ -3330,7 +3326,7 @@ bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
// JSTRY_DESTRUCTURING expects the iterator and the done value
// to be the second to top and the top of the stack, respectively.
// IteratorClose is called upon exception only if done is false.
int32_t tryNoteDepth = bytecodeSection().stackDepth();
int32_t tryNoteDepth = stackDepth;
for (ParseNode* member : pattern->contents()) {
bool isFirst = member == pattern->head();
@ -3639,7 +3635,7 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr));
// [stack] ... RHS
MOZ_ASSERT(bytecodeSection().stackDepth() > 0);
MOZ_ASSERT(this->stackDepth > 0);
if (!emit1(JSOP_CHECKOBJCOERCIBLE)) {
// [stack] ... RHS
@ -3819,7 +3815,7 @@ bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) {
MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr));
MOZ_ASSERT(pattern->last()->isKind(ParseNodeKind::Spread));
ptrdiff_t offset = bytecodeSection().offset();
ptrdiff_t offset = this->offset();
if (!emitNewInit()) {
return false;
}
@ -4694,11 +4690,11 @@ MOZ_MUST_USE bool BytecodeEmitter::emitGoSub(JumpList* jump) {
}
uint32_t resumeIndex;
if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) {
if (!allocateResumeIndex(offset(), &resumeIndex)) {
return false;
}
SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex);
SET_RESUMEINDEX(code(off), resumeIndex);
return true;
}
@ -4903,7 +4899,7 @@ bool BytecodeEmitter::emitWith(BinaryNode* withNode) {
}
bool BytecodeEmitter::emitCopyDataProperties(CopyOption option) {
DebugOnly<int32_t> depth = bytecodeSection().stackDepth();
DebugOnly<int32_t> depth = this->stackDepth;
uint32_t argc;
if (option == CopyOption::Filtered) {
@ -4958,15 +4954,15 @@ bool BytecodeEmitter::emitCopyDataProperties(CopyOption option) {
return false;
}
MOZ_ASSERT(depth - int(argc) == bytecodeSection().stackDepth());
MOZ_ASSERT(depth - int(argc) == this->stackDepth);
return true;
}
bool BytecodeEmitter::emitBigIntOp(BigInt* bigint) {
if (!perScriptData().numberList().append(BigIntValue(bigint))) {
if (!numberList.append(BigIntValue(bigint))) {
return false;
}
return emitIndex32(JSOP_BIGINT, perScriptData().numberList().length() - 1);
return emitIndex32(JSOP_BIGINT, numberList.length() - 1);
}
bool BytecodeEmitter::emitIterator() {
@ -5149,11 +5145,11 @@ bool BytecodeEmitter::emitSpread(bool allowSelfHosted) {
// when we reach this point on the loop backedge (if spreading produces at
// least one value), we've additionally pushed a RESULT iteration value.
// Increment manually to reflect this.
bytecodeSection().setStackDepth(bytecodeSection().stackDepth() + 1);
this->stackDepth++;
{
#ifdef DEBUG
auto loopDepth = bytecodeSection().stackDepth();
auto loopDepth = this->stackDepth;
#endif
// Emit code to assign result.value to the iteration variable.
@ -5166,7 +5162,7 @@ bool BytecodeEmitter::emitSpread(bool allowSelfHosted) {
return false;
}
MOZ_ASSERT(bytecodeSection().stackDepth() == loopDepth - 1);
MOZ_ASSERT(this->stackDepth == loopDepth - 1);
// Spread operations can't contain |continue|, so don't bother setting loop
// and enclosing "update" offsets, as we do with for-loops.
@ -5203,7 +5199,7 @@ bool BytecodeEmitter::emitSpread(bool allowSelfHosted) {
return false;
}
MOZ_ASSERT(bytecodeSection().stackDepth() == loopDepth);
MOZ_ASSERT(this->stackDepth == loopDepth);
}
// Let Ion know where the closing jump of this loop is.
@ -5216,8 +5212,8 @@ bool BytecodeEmitter::emitSpread(bool allowSelfHosted) {
MOZ_ASSERT(loopInfo.breaks.offset == -1);
MOZ_ASSERT(loopInfo.continues.offset == -1);
if (!addTryNote(JSTRY_FOR_OF, bytecodeSection().stackDepth(),
loopInfo.headOffset(), loopInfo.breakTargetOffset())) {
if (!addTryNote(JSTRY_FOR_OF, stackDepth, loopInfo.headOffset(),
loopInfo.breakTargetOffset())) {
return false;
}
@ -5238,7 +5234,7 @@ bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) {
MOZ_ASSERT(forHead->isKind(ParseNodeKind::ForIn) ||
forHead->isKind(ParseNodeKind::ForOf));
MOZ_ASSERT(bytecodeSection().stackDepth() >= 1,
MOZ_ASSERT(this->stackDepth >= 1,
"must have a per-iteration value for initializing");
ParseNode* target = forHead->kid1();
@ -5286,14 +5282,14 @@ bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) {
// iteration value *before* initializing. Thus the initializing
// value may be buried under a bind-specific value on the stack.
// Swap it to the top of the stack.
MOZ_ASSERT(bytecodeSection().stackDepth() >= 2);
MOZ_ASSERT(stackDepth >= 2);
if (!emit1(JSOP_SWAP)) {
return false;
}
} else {
// In cases of emitting a frame slot or environment slot,
// nothing needs be done.
MOZ_ASSERT(bytecodeSection().stackDepth() >= 1);
MOZ_ASSERT(stackDepth >= 1);
}
if (!noe.emitAssignment()) {
return false;
@ -5971,7 +5967,7 @@ bool BytecodeEmitter::emitReturn(UnaryNode* returnNode) {
* In this case we mutate JSOP_RETURN into JSOP_SETRVAL and add an
* extra JSOP_RETRVAL after the fixups.
*/
ptrdiff_t top = bytecodeSection().offset();
ptrdiff_t top = offset();
bool needsFinalYield =
sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield();
@ -6032,13 +6028,12 @@ bool BytecodeEmitter::emitReturn(UnaryNode* returnNode) {
return false;
}
} else if (isDerivedClassConstructor) {
MOZ_ASSERT(bytecodeSection().code()[top] == JSOP_SETRVAL);
MOZ_ASSERT(code()[top] == JSOP_SETRVAL);
if (!emit1(JSOP_RETRVAL)) {
return false;
}
} else if (top + static_cast<ptrdiff_t>(JSOP_RETURN_LENGTH) !=
bytecodeSection().offset()) {
bytecodeSection().code()[top] = JSOP_SETRVAL;
} else if (top + static_cast<ptrdiff_t>(JSOP_RETURN_LENGTH) != offset()) {
code()[top] = JSOP_SETRVAL;
if (!emit1(JSOP_RETRVAL)) {
return false;
}
@ -6218,7 +6213,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
}
int32_t savedDepthTemp;
int32_t startDepth = bytecodeSection().stackDepth();
int32_t startDepth = stackDepth;
MOZ_ASSERT(startDepth >= 3);
TryEmitter tryCatch(this, TryEmitter::Kind::TryCatchFinally,
@ -6250,7 +6245,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
return false;
}
MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth);
MOZ_ASSERT(this->stackDepth == startDepth);
// Step 7.a.vi.
// Step 7.b.ii.7.
@ -6283,7 +6278,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
return false;
}
MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth);
MOZ_ASSERT(stackDepth == startDepth);
if (!emit1(JSOP_EXCEPTION)) {
// [stack] NEXT ITER RESULT EXCEPTION
@ -6302,7 +6297,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
return false;
}
savedDepthTemp = bytecodeSection().stackDepth();
savedDepthTemp = stackDepth;
InternalIfEmitter ifThrowMethodIsNotDefined(this);
if (!emitPushNotUndefinedOrNull()) {
// [stack] NEXT ITER RESULT EXCEPTION ITER THROW
@ -6353,7 +6348,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
// [stack] NEXT ITER RESULT
return false;
}
MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth);
MOZ_ASSERT(this->stackDepth == startDepth);
JumpList checkResult;
// Note that there is no GOSUB to the finally block here. If the iterator has
@ -6364,7 +6359,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
return false;
}
bytecodeSection().setStackDepth(savedDepthTemp);
stackDepth = savedDepthTemp;
if (!ifThrowMethodIsNotDefined.emitElse()) {
// [stack] NEXT ITER RESULT EXCEPTION ITER THROW
return false;
@ -6389,12 +6384,12 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
return false;
}
bytecodeSection().setStackDepth(savedDepthTemp);
stackDepth = savedDepthTemp;
if (!ifThrowMethodIsNotDefined.emitEnd()) {
return false;
}
bytecodeSection().setStackDepth(startDepth);
stackDepth = startDepth;
if (!tryCatch.emitFinally()) {
return false;
}
@ -6521,7 +6516,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
// [stack] NEXT ITER OLDRESULT FTYPE FVALUE
return false;
}
savedDepthTemp = bytecodeSection().stackDepth();
savedDepthTemp = this->stackDepth;
if (!ifReturnDone.emitElse()) {
// [stack] NEXT ITER OLDRESULT FTYPE FVALUE RESULT
return false;
@ -6543,7 +6538,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
return false;
}
}
bytecodeSection().setStackDepth(savedDepthTemp);
this->stackDepth = savedDepthTemp;
if (!ifReturnDone.emitEnd()) {
return false;
}
@ -6618,7 +6613,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
// [stack] NEXT ITER RESULT
return false;
}
MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth);
MOZ_ASSERT(this->stackDepth == startDepth);
// Steps 7.a.iv-v.
// Steps 7.b.ii.5-6.
@ -6663,7 +6658,7 @@ bool BytecodeEmitter::emitYieldStar(ParseNode* iter) {
return false;
}
MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth - 2);
MOZ_ASSERT(this->stackDepth == startDepth - 2);
return true;
}
@ -6712,7 +6707,7 @@ bool BytecodeEmitter::emitExpressionStatement(UnaryNode* exprStmt) {
if (innermostNestableControl &&
innermostNestableControl->is<LabelControl>() &&
innermostNestableControl->as<LabelControl>().startOffset() >=
bytecodeSection().offset()) {
offset()) {
useful = true;
}
}
@ -8187,8 +8182,8 @@ bool BytecodeEmitter::replaceNewInitWithNewObject(JSObject* obj,
JSOP_NEWINIT_LENGTH == JSOP_NEWOBJECT_LENGTH,
"newinit and newobject must have equal length to edit in-place");
uint32_t index = perScriptData().objectList().add(objbox);
jsbytecode* code = bytecodeSection().code(offset);
uint32_t index = objectList.add(objbox);
jsbytecode* code = this->code(offset);
MOZ_ASSERT(code[0] == JSOP_NEWINIT);
code[0] = JSOP_NEWOBJECT;
@ -9238,8 +9233,7 @@ bool BytecodeEmitter::emitTree(
break;
case ParseNodeKind::RegExpExpr:
if (!emitRegExp(perScriptData().objectList().add(
pn->as<RegExpLiteral>().objbox()))) {
if (!emitRegExp(objectList.add(pn->as<RegExpLiteral>().objbox()))) {
return false;
}
break;
@ -9340,13 +9334,11 @@ static bool AllocSrcNote(JSContext* cx, SrcNotesVector& notes,
bool BytecodeEmitter::addTryNote(JSTryNoteKind kind, uint32_t stackDepth,
size_t start, size_t end) {
MOZ_ASSERT(!inPrologue());
return bytecodeSection().tryNoteList().append(kind, stackDepth, start, end);
return tryNoteList.append(kind, stackDepth, start, end);
}
bool BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp) {
// Prologue shouldn't have source notes.
MOZ_ASSERT(!inPrologue());
SrcNotesVector& notes = bytecodeSection().notes();
SrcNotesVector& notes = this->notes();
unsigned index;
if (!AllocSrcNote(cx, notes, &index)) {
return false;
@ -9356,9 +9348,9 @@ bool BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp) {
* Compute delta from the last annotated bytecode's offset. If it's too
* big to fit in sn, allocate one or more xdelta notes and reset sn.
*/
ptrdiff_t offset = bytecodeSection().offset();
ptrdiff_t delta = offset - bytecodeSection().lastNoteOffset();
bytecodeSection().setLastNoteOffset(offset);
ptrdiff_t offset = this->offset();
ptrdiff_t delta = offset - lastNoteOffset();
lastNoteOffset_ = offset;
if (delta >= SN_DELTA_LIMIT) {
do {
ptrdiff_t xdelta = Min(delta, SN_XDELTA_MASK);
@ -9428,7 +9420,7 @@ bool BytecodeEmitter::setSrcNoteOffset(unsigned index, unsigned which,
return false;
}
SrcNotesVector& notes = bytecodeSection().notes();
SrcNotesVector& notes = this->notes();
/* Find the offset numbered which (i.e., skip exactly which offsets). */
jssrcnote* sn = &notes[index];
@ -9466,10 +9458,10 @@ bool BytecodeEmitter::setSrcNoteOffset(unsigned index, unsigned which,
}
void BytecodeEmitter::copySrcNotes(jssrcnote* destination, uint32_t nsrcnotes) {
unsigned count = bytecodeSection().notes().length();
unsigned count = notes_.length();
// nsrcnotes includes SN_MAKE_TERMINATOR in addition to the srcnotes.
MOZ_ASSERT(nsrcnotes == count + 1);
PodCopy(destination, bytecodeSection().notes().begin(), count);
PodCopy(destination, notes_.begin(), count);
SN_MAKE_TERMINATOR(&destination[count]);
}

View File

@ -124,249 +124,29 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
Rooted<LazyScript*> lazyScript;
private:
// Bytecode and all data directly associated with specific opcode/index inside
// bytecode is stored in this class.
class BytecodeSection {
public:
BytecodeSection(JSContext* cx, uint32_t lineNum);
BytecodeVector code_; /* bytecode */
SrcNotesVector notes_; /* source notes, see below */
// ---- Bytecode ----
// Code offset for last source note
ptrdiff_t lastNoteOffset_ = 0;
BytecodeVector& code() { return code_; }
const BytecodeVector& code() const { return code_; }
// Line number for srcnotes.
//
// WARNING: If this becomes out of sync with already-emitted srcnotes,
// we can get undefined behavior.
uint32_t currentLine_ = 0;
jsbytecode* code(ptrdiff_t offset) { return code_.begin() + offset; }
ptrdiff_t offset() const { return code_.end() - code_.begin(); }
// Zero-based column index on currentLine of last SRC_COLSPAN-annotated
// opcode.
//
// WARNING: If this becomes out of sync with already-emitted srcnotes,
// we can get undefined behavior.
uint32_t lastColumn_ = 0;
// ---- Source notes ----
uint32_t lastSeparatorOffet_ = 0;
uint32_t lastSeparatorLine_ = 0;
uint32_t lastSeparatorColumn_ = 0;
SrcNotesVector& notes() { return notes_; }
const SrcNotesVector& notes() const { return notes_; }
ptrdiff_t lastNoteOffset() const { return lastNoteOffset_; }
void setLastNoteOffset(ptrdiff_t offset) { lastNoteOffset_ = offset; }
// ---- Jump ----
ptrdiff_t lastTargetOffset() const { return lastTarget_.offset; }
void setLastTargetOffset(ptrdiff_t offset) { lastTarget_.offset = offset; }
// Check if the last emitted opcode is a jump target.
bool lastOpcodeIsJumpTarget() const {
return offset() - lastTarget_.offset == ptrdiff_t(JSOP_JUMPTARGET_LENGTH);
}
// JumpTarget should not be part of the emitted statement, as they can be
// aliased by multiple statements. If we included the jump target as part of
// the statement we might have issues where the enclosing statement might
// not contain all the opcodes of the enclosed statements.
ptrdiff_t lastNonJumpTargetOffset() const {
return lastOpcodeIsJumpTarget() ? lastTarget_.offset : offset();
}
// ---- Stack ----
int32_t stackDepth() const { return stackDepth_; }
void setStackDepth(int32_t depth) { stackDepth_ = depth; }
uint32_t maxStackDepth() const { return maxStackDepth_; }
void updateDepth(ptrdiff_t target);
// ---- Try notes ----
CGTryNoteList& tryNoteList() { return tryNoteList_; };
const CGTryNoteList& tryNoteList() const { return tryNoteList_; };
// ---- Scope ----
CGScopeNoteList& scopeNoteList() { return scopeNoteList_; };
const CGScopeNoteList& scopeNoteList() const { return scopeNoteList_; };
// ---- Generator ----
CGResumeOffsetList& resumeOffsetList() { return resumeOffsetList_; }
const CGResumeOffsetList& resumeOffsetList() const {
return resumeOffsetList_;
}
uint32_t numYields() const { return numYields_; }
void addNumYields() { numYields_++; }
// ---- Line and column ----
uint32_t currentLine() const { return currentLine_; }
uint32_t lastColumn() const { return lastColumn_; }
void setCurrentLine(uint32_t line) {
currentLine_ = line;
lastColumn_ = 0;
}
void setLastColumn(uint32_t column) { lastColumn_ = column; }
void updateSeparatorPosition() {
lastSeparatorOffet_ = code().length();
lastSeparatorLine_ = currentLine_;
lastSeparatorColumn_ = lastColumn_;
}
void updateSeparatorPositionIfPresent() {
if (lastSeparatorOffet_ == code().length()) {
lastSeparatorLine_ = currentLine_;
lastSeparatorColumn_ = lastColumn_;
}
}
bool isDuplicateLocation() const {
return lastSeparatorLine_ == currentLine_ &&
lastSeparatorColumn_ == lastColumn_;
}
// ---- JIT ----
size_t numICEntries() const { return numICEntries_; }
void addNumICEntries() { numICEntries_++; }
void setNumICEntries(size_t entries) { numICEntries_ = entries; }
uint16_t typesetCount() const { return typesetCount_; }
void addTypesetCount() { typesetCount_++; }
private:
// ---- Bytecode ----
// Bytecode.
BytecodeVector code_;
// ---- Source notes ----
// Source notes
SrcNotesVector notes_;
// Code offset for last source note
ptrdiff_t lastNoteOffset_ = 0;
// ---- Jump ----
// Last jump target emitted.
JumpTarget lastTarget_ = {-1 - ptrdiff_t(JSOP_JUMPTARGET_LENGTH)};
// ---- Stack ----
// Maximum number of expression stack slots so far.
uint32_t maxStackDepth_ = 0;
// Current stack depth in script frame.
int32_t stackDepth_ = 0;
// ---- Try notes ----
// List of emitted try notes.
CGTryNoteList tryNoteList_;
// ---- Scope ----
// List of emitted block scope notes.
CGScopeNoteList scopeNoteList_;
// ---- Generator ----
// Certain ops (yield, await, gosub) have an entry in the script's
// resumeOffsets list. This can be used to map from the op's resumeIndex to
// the bytecode offset of the next pc. This indirection makes it easy to
// resume in the JIT (because BaselineScript stores a resumeIndex => native
// code array).
CGResumeOffsetList resumeOffsetList_;
// Number of yield instructions emitted. Does not include JSOP_AWAIT.
uint32_t numYields_ = 0;
// ---- Line and column ----
// Line number for srcnotes.
//
// WARNING: If this becomes out of sync with already-emitted srcnotes,
// we can get undefined behavior.
uint32_t currentLine_;
// Zero-based column index on currentLine_ of last SRC_COLSPAN-annotated
// opcode.
//
// WARNING: If this becomes out of sync with already-emitted srcnotes,
// we can get undefined behavior.
uint32_t lastColumn_ = 0;
// The offset, line and column numbers of the last opcode for the
// breakpoint for step execution.
uint32_t lastSeparatorOffet_ = 0;
uint32_t lastSeparatorLine_ = 0;
uint32_t lastSeparatorColumn_ = 0;
// ---- JIT ----
// Number of JOF_IC opcodes emitted.
size_t numICEntries_ = 0;
// Number of JOF_TYPESET opcodes generated.
uint16_t typesetCount_ = 0;
};
BytecodeSection bytecodeSection_;
public:
BytecodeSection& bytecodeSection() { return bytecodeSection_; }
const BytecodeSection& bytecodeSection() const { return bytecodeSection_; }
private:
// Data that is not directly associated with specific opcode/index inside
// bytecode, but referred from bytecode is stored in this class.
class PerScriptData {
public:
explicit PerScriptData(JSContext* cx);
MOZ_MUST_USE bool init(JSContext* cx);
// ---- Scope ----
CGScopeList& scopeList() { return scopeList_; }
const CGScopeList& scopeList() const { return scopeList_; }
// ---- Literals ----
CGNumberList& numberList() { return numberList_; }
const CGNumberList& numberList() const { return numberList_; }
CGObjectList& objectList() { return objectList_; }
const CGObjectList& objectList() const { return objectList_; }
PooledMapPtr<AtomIndexMap>& atomIndices() { return atomIndices_; }
const PooledMapPtr<AtomIndexMap>& atomIndices() const {
return atomIndices_;
}
private:
// ---- Scope ----
// List of emitted scopes.
CGScopeList scopeList_;
// ---- Literals ----
// List of double and bigint values used by script.
CGNumberList numberList_;
// List of emitted objects.
CGObjectList objectList_;
// Map from atom to index.
PooledMapPtr<AtomIndexMap> atomIndices_;
};
PerScriptData perScriptData_;
public:
PerScriptData& perScriptData() { return perScriptData_; }
const PerScriptData& perScriptData() const { return perScriptData_; }
private:
// switchToMain sets this to the bytecode offset of the main section.
mozilla::Maybe<uint32_t> mainOffset_ = {};
@ -374,14 +154,22 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
const FieldInitializers fieldInitializers_;
public:
// Last jump target emitted.
JumpTarget lastTarget = {-1 - ptrdiff_t(JSOP_JUMPTARGET_LENGTH)};
// Private storage for parser wrapper. DO NOT REFERENCE INTERNALLY. May not be
// initialized. Use |parser| instead.
mozilla::Maybe<EitherParser> ep_ = {};
BCEParserHandle* parser = nullptr;
PooledMapPtr<AtomIndexMap> atomIndices; /* literals indexed for mapping */
unsigned firstLine = 0; /* first line, for JSScript::initFromEmitter */
uint32_t maxFixedSlots = 0; /* maximum number of fixed frame slots so far */
uint32_t maxStackDepth =
0; /* maximum number of expression stack slots so far */
int32_t stackDepth = 0; /* current stack depth in script frame */
uint32_t bodyScopeIndex =
UINT32_MAX; /* index into scopeList of the body scope */
@ -407,6 +195,28 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
return innermostEmitterScope_;
}
CGNumberList numberList; /* double and bigint values used by script */
CGObjectList objectList; /* list of emitted objects */
CGScopeList scopeList; /* list of emitted scopes */
CGTryNoteList tryNoteList; /* list of emitted try notes */
CGScopeNoteList scopeNoteList; /* list of emitted block scope notes */
// Certain ops (yield, await, gosub) have an entry in the script's
// resumeOffsets list. This can be used to map from the op's resumeIndex to
// the bytecode offset of the next pc. This indirection makes it easy to
// resume in the JIT (because BaselineScript stores a resumeIndex => native
// code array).
CGResumeOffsetList resumeOffsetList;
// Number of JOF_IC opcodes emitted.
size_t numICEntries = 0;
// Number of yield instructions emitted. Does not include JSOP_AWAIT.
uint32_t numYields = 0;
// Number of JOF_TYPESET opcodes generated.
uint16_t typesetCount = 0;
// Script contains singleton initializer JSOP_OBJECT.
bool hasSingletons = false;
@ -550,26 +360,24 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
varEmitterScope = emitterScope;
}
Scope* outermostScope() const {
return perScriptData().scopeList().vector[0];
}
Scope* outermostScope() const { return scopeList.vector[0]; }
Scope* innermostScope() const;
Scope* bodyScope() const {
MOZ_ASSERT(bodyScopeIndex < perScriptData().scopeList().length());
return perScriptData().scopeList().vector[bodyScopeIndex];
MOZ_ASSERT(bodyScopeIndex < scopeList.length());
return scopeList.vector[bodyScopeIndex];
}
MOZ_ALWAYS_INLINE
MOZ_MUST_USE bool makeAtomIndex(JSAtom* atom, uint32_t* indexp) {
MOZ_ASSERT(perScriptData().atomIndices());
AtomIndexMap::AddPtr p = perScriptData().atomIndices()->lookupForAdd(atom);
MOZ_ASSERT(atomIndices);
AtomIndexMap::AddPtr p = atomIndices->lookupForAdd(atom);
if (p) {
*indexp = p->value();
return true;
}
uint32_t index = perScriptData().atomIndices()->count();
if (!perScriptData().atomIndices()->add(p, atom, index)) {
uint32_t index = atomIndices->count();
if (!atomIndices->add(p, atom, index)) {
ReportOutOfMemory(cx);
return false;
}
@ -592,13 +400,45 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
void tellDebuggerAboutCompiledScript(JSContext* cx);
BytecodeVector& code() { return code_; }
const BytecodeVector& code() const { return code_; }
jsbytecode* code(ptrdiff_t offset) { return code_.begin() + offset; }
ptrdiff_t offset() const { return code_.end() - code_.begin(); }
uint32_t mainOffset() const { return *mainOffset_; }
bool inPrologue() const { return mainOffset_.isNothing(); }
void switchToMain() {
MOZ_ASSERT(inPrologue());
mainOffset_.emplace(bytecodeSection().code().length());
mainOffset_.emplace(code_.length());
}
SrcNotesVector& notes() {
// Prologue shouldn't have source notes.
MOZ_ASSERT(!inPrologue());
return notes_;
}
ptrdiff_t lastNoteOffset() const { return lastNoteOffset_; }
unsigned currentLine() const { return currentLine_; }
void setCurrentLine(uint32_t line) {
currentLine_ = line;
lastColumn_ = 0;
}
// Check if the last emitted opcode is a jump target.
bool lastOpcodeIsJumpTarget() const {
return offset() - lastTarget.offset == ptrdiff_t(JSOP_JUMPTARGET_LENGTH);
}
// JumpTarget should not be part of the emitted statement, as they can be
// aliased by multiple statements. If we included the jump target as part of
// the statement we might have issues where the enclosing statement might
// not contain all the opcodes of the enclosed statements.
ptrdiff_t lastNonJumpTargetOffset() const {
return lastOpcodeIsJumpTarget() ? lastTarget.offset : offset();
}
void setFunctionBodyEndPos(uint32_t pos) {
@ -669,10 +509,12 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
MOZ_MUST_USE bool emitFunctionScript(FunctionNode* funNode,
TopLevelFunction isTopLevel);
void updateDepth(ptrdiff_t target);
MOZ_MUST_USE bool markStepBreakpoint();
MOZ_MUST_USE bool markSimpleBreakpoint();
MOZ_MUST_USE bool updateLineNumberNotes(uint32_t offset);
MOZ_MUST_USE bool updateSourceCoordNotes(uint32_t offset);
void updateSeparatorPosition();
JSOp strictifySetNameOp(JSOp op);

View File

@ -75,7 +75,7 @@ bool CForEmitter::emitBody(Cond cond, const Maybe<uint32_t>& bodyPos) {
return false;
}
biasedTop_ = bce_->bytecodeSection().offset();
biasedTop_ = bce_->offset();
if (cond_ == Cond::Present) {
// Goto the loop condition, which branches back to iterate.
@ -163,11 +163,11 @@ bool CForEmitter::emitCond(const Maybe<uint32_t>& forPos,
// Restore the absolute line number for source note readers.
if (endPos) {
uint32_t lineNum = bce_->parser->errorReporter().lineAt(*endPos);
if (bce_->bytecodeSection().currentLine() != lineNum) {
if (bce_->currentLine() != lineNum) {
if (!bce_->newSrcNote2(SRC_SETLINE, ptrdiff_t(lineNum))) {
return false;
}
bce_->bytecodeSection().setCurrentLine(lineNum);
bce_->setCurrentLine(lineNum);
}
}
}
@ -176,7 +176,7 @@ bool CForEmitter::emitCond(const Maybe<uint32_t>& forPos,
tdzCache_.reset();
}
condOffset_ = bce_->bytecodeSection().offset();
condOffset_ = bce_->offset();
if (cond_ == Cond::Present) {
if (!loopInfo_->emitLoopEntry(bce_, condPos)) {
@ -228,8 +228,7 @@ bool CForEmitter::emitEnd() {
return false;
}
if (!bce_->addTryNote(JSTRY_LOOP, bce_->bytecodeSection().stackDepth(),
loopInfo_->headOffset(),
if (!bce_->addTryNote(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
loopInfo_->breakTargetOffset())) {
return false;
}

View File

@ -75,8 +75,7 @@ bool DoWhileEmitter::emitEnd() {
return false;
}
if (!bce_->addTryNote(JSTRY_LOOP, bce_->bytecodeSection().stackDepth(),
loopInfo_->headOffset(),
if (!bce_->addTryNote(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
loopInfo_->breakTargetOffset())) {
return false;
}

View File

@ -342,8 +342,8 @@ bool EmitterScope::internScope(BytecodeEmitter* bce, ScopeCreator createScope) {
return false;
}
hasEnvironment_ = scope->hasEnvironment();
scopeIndex_ = bce->perScriptData().scopeList().length();
return bce->perScriptData().scopeList().append(scope);
scopeIndex_ = bce->scopeList.length();
return bce->scopeList.append(scope);
}
template <typename ScopeCreator>
@ -351,18 +351,18 @@ bool EmitterScope::internBodyScope(BytecodeEmitter* bce,
ScopeCreator createScope) {
MOZ_ASSERT(bce->bodyScopeIndex == UINT32_MAX,
"There can be only one body scope");
bce->bodyScopeIndex = bce->perScriptData().scopeList().length();
bce->bodyScopeIndex = bce->scopeList.length();
return internScope(bce, createScope);
}
bool EmitterScope::appendScopeNote(BytecodeEmitter* bce) {
MOZ_ASSERT(ScopeKindIsInBody(scope(bce)->kind()) && enclosingInFrame(),
"Scope notes are not needed for body-level scopes.");
noteIndex_ = bce->bytecodeSection().scopeNoteList().length();
return bce->bytecodeSection().scopeNoteList().append(
index(), bce->bytecodeSection().offset(),
enclosingInFrame() ? enclosingInFrame()->noteIndex()
: ScopeNote::NoScopeNoteIndex);
noteIndex_ = bce->scopeNoteList.length();
return bce->scopeNoteList.append(index(), bce->offset(),
enclosingInFrame()
? enclosingInFrame()->noteIndex()
: ScopeNote::NoScopeNoteIndex);
}
bool EmitterScope::deadZoneFrameSlotRange(BytecodeEmitter* bce,
@ -1057,10 +1057,9 @@ bool EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal) {
if (ScopeKindIsInBody(kind)) {
// The extra function var scope is never popped once it's pushed,
// so its scope note extends until the end of any possible code.
uint32_t offset = kind == ScopeKind::FunctionBodyVar
? UINT32_MAX
: bce->bytecodeSection().offset();
bce->bytecodeSection().scopeNoteList().recordEnd(noteIndex_, offset);
uint32_t offset =
kind == ScopeKind::FunctionBodyVar ? UINT32_MAX : bce->offset();
bce->scopeNoteList.recordEnd(noteIndex_, offset);
}
}
@ -1068,7 +1067,7 @@ bool EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal) {
}
Scope* EmitterScope::scope(const BytecodeEmitter* bce) const {
return bce->perScriptData().scopeList().vector[index()];
return bce->scopeList.vector[index()];
}
NameLocation EmitterScope::lookup(BytecodeEmitter* bce, JSAtom* name) {

View File

@ -29,7 +29,7 @@ bool ExpressionStatementEmitter::prepareForExpr(
}
#ifdef DEBUG
depth_ = bce_->bytecodeSection().stackDepth();
depth_ = bce_->stackDepth;
state_ = State::Expr;
#endif
return true;
@ -37,7 +37,7 @@ bool ExpressionStatementEmitter::prepareForExpr(
bool ExpressionStatementEmitter::emitEnd() {
MOZ_ASSERT(state_ == State::Expr);
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_ + 1);
MOZ_ASSERT(bce_->stackDepth == depth_ + 1);
// [stack] VAL

View File

@ -94,7 +94,7 @@ bool ForInEmitter::emitInitialize() {
}
#ifdef DEBUG
loopDepth_ = bce_->bytecodeSection().stackDepth();
loopDepth_ = bce_->stackDepth;
#endif
MOZ_ASSERT(loopDepth_ >= 2);
@ -112,7 +112,7 @@ bool ForInEmitter::emitInitialize() {
bool ForInEmitter::emitBody() {
MOZ_ASSERT(state_ == State::Initialize);
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == loopDepth_,
MOZ_ASSERT(bce_->stackDepth == loopDepth_,
"iterator and iterval must be left on the stack");
#ifdef DEBUG
@ -124,7 +124,7 @@ bool ForInEmitter::emitBody() {
bool ForInEmitter::emitEnd(const Maybe<uint32_t>& forPos) {
MOZ_ASSERT(state_ == State::Body);
loopInfo_->setContinueTarget(bce_->bytecodeSection().offset());
loopInfo_->setContinueTarget(bce_->offset());
if (forPos) {
// Make sure this code is attributed to the "for".
@ -171,9 +171,8 @@ bool ForInEmitter::emitEnd(const Maybe<uint32_t>& forPos) {
return false;
}
if (!bce_->addTryNote(JSTRY_FOR_IN, bce_->bytecodeSection().stackDepth(),
loopInfo_->headOffset(),
bce_->bytecodeSection().offset())) {
if (!bce_->addTryNote(JSTRY_FOR_IN, bce_->stackDepth, loopInfo_->headOffset(),
bce_->offset())) {
return false;
}

View File

@ -58,7 +58,7 @@ bool ForOfEmitter::emitInitialize(const Maybe<uint32_t>& forPos) {
}
}
int32_t iterDepth = bce_->bytecodeSection().stackDepth();
int32_t iterDepth = bce_->stackDepth;
// For-of loops have the iterator next method, the iterator itself, and
// the result.value on the stack.
@ -111,7 +111,7 @@ bool ForOfEmitter::emitInitialize(const Maybe<uint32_t>& forPos) {
}
#ifdef DEBUG
loopDepth_ = bce_->bytecodeSection().stackDepth();
loopDepth_ = bce_->stackDepth;
#endif
// Make sure this code is attributed to the "for".
@ -195,7 +195,7 @@ bool ForOfEmitter::emitInitialize(const Maybe<uint32_t>& forPos) {
bool ForOfEmitter::emitBody() {
MOZ_ASSERT(state_ == State::Initialize);
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == loopDepth_,
MOZ_ASSERT(bce_->stackDepth == loopDepth_,
"the stack must be balanced around the initializing "
"operation");
@ -218,14 +218,14 @@ bool ForOfEmitter::emitBody() {
bool ForOfEmitter::emitEnd(const Maybe<uint32_t>& iteratedPos) {
MOZ_ASSERT(state_ == State::Body);
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == loopDepth_,
MOZ_ASSERT(bce_->stackDepth == loopDepth_,
"the stack must be balanced around the for-of body");
if (!loopInfo_->emitEndCodeNeedingIteratorClose(bce_)) {
return false;
}
loopInfo_->setContinueTarget(bce_->bytecodeSection().offset());
loopInfo_->setContinueTarget(bce_->offset());
// We use the iterated value's position to attribute JSOP_LOOPENTRY,
// which corresponds to the iteration protocol.
@ -244,7 +244,7 @@ bool ForOfEmitter::emitEnd(const Maybe<uint32_t>& iteratedPos) {
return false;
}
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == loopDepth_);
MOZ_ASSERT(bce_->stackDepth == loopDepth_);
// Let Ion know where the closing jump of this loop is.
if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::ForOf::BackJumpOffset,
@ -256,8 +256,7 @@ bool ForOfEmitter::emitEnd(const Maybe<uint32_t>& iteratedPos) {
return false;
}
if (!bce_->addTryNote(JSTRY_FOR_OF, bce_->bytecodeSection().stackDepth(),
loopInfo_->headOffset(),
if (!bce_->addTryNote(JSTRY_FOR_OF, bce_->stackDepth, loopInfo_->headOffset(),
loopInfo_->breakTargetOffset())) {
return false;
}

View File

@ -30,7 +30,7 @@ bool ForOfLoopControl::emitBeginCodeNeedingIteratorClose(BytecodeEmitter* bce) {
}
MOZ_ASSERT(numYieldsAtBeginCodeNeedingIterClose_ == UINT32_MAX);
numYieldsAtBeginCodeNeedingIterClose_ = bce->bytecodeSection().numYields();
numYieldsAtBeginCodeNeedingIterClose_ = bce->numYields;
return true;
}
@ -45,7 +45,7 @@ bool ForOfLoopControl::emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce) {
// [stack] ITER ... EXCEPTION
return false;
}
unsigned slotFromTop = bce->bytecodeSection().stackDepth() - iterDepth_;
unsigned slotFromTop = bce->stackDepth - iterDepth_;
if (!bce->emitDupAt(slotFromTop)) {
// [stack] ITER ... EXCEPTION ITER
return false;
@ -69,8 +69,7 @@ bool ForOfLoopControl::emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce) {
return false;
}
MOZ_ASSERT(slotFromTop ==
unsigned(bce->bytecodeSection().stackDepth() - iterDepth_));
MOZ_ASSERT(slotFromTop == unsigned(bce->stackDepth - iterDepth_));
if (!bce->emitDupAt(slotFromTop)) {
// [stack] ITER ... EXCEPTION ITER
return false;
@ -93,7 +92,7 @@ bool ForOfLoopControl::emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce) {
// If any yields were emitted, then this for-of loop is inside a star
// generator and must handle the case of Generator.return. Like in
// yield*, it is handled with a finally block.
uint32_t numYieldsEmitted = bce->bytecodeSection().numYields();
uint32_t numYieldsEmitted = bce->numYields;
if (numYieldsEmitted > numYieldsAtBeginCodeNeedingIterClose_) {
if (!tryCatch_->emitFinally()) {
return false;
@ -136,12 +135,12 @@ bool ForOfLoopControl::emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce) {
bool ForOfLoopControl::emitIteratorCloseInInnermostScopeWithTryNote(
BytecodeEmitter* bce,
CompletionKind completionKind /* = CompletionKind::Normal */) {
ptrdiff_t start = bce->bytecodeSection().offset();
ptrdiff_t start = bce->offset();
if (!emitIteratorCloseInScope(bce, *bce->innermostEmitterScope(),
completionKind)) {
return false;
}
ptrdiff_t end = bce->bytecodeSection().offset();
ptrdiff_t end = bce->offset();
return bce->addTryNote(JSTRY_FOR_OF_ITERCLOSE, 0, start, end);
}
@ -194,7 +193,7 @@ bool ForOfLoopControl::emitPrepareForNonLocalJumpFromScope(
return false;
}
*tryNoteStart = bce->bytecodeSection().offset();
*tryNoteStart = bce->offset();
if (!emitIteratorCloseInScope(bce, currentScope, CompletionKind::Normal)) {
// [stack] UNDEF
return false;

View File

@ -220,7 +220,7 @@ bool FunctionEmitter::emitAsmJSModule() {
bool FunctionEmitter::emitFunction() {
// Make the function object a literal in the outer script's pool.
unsigned index = bce_->perScriptData().objectList().add(funbox_);
unsigned index = bce_->objectList.add(funbox_);
// [stack]

View File

@ -41,10 +41,10 @@ bool BranchEmitterBase::emitThenInternal(SrcNoteType type) {
// To restore stack depth in else part, save depth of the then part.
#ifdef DEBUG
// If DEBUG, this is also necessary to calculate |pushed_|.
thenDepth_ = bce_->bytecodeSection().stackDepth();
thenDepth_ = bce_->stackDepth;
#else
if (type == SRC_COND || type == SRC_IF_ELSE) {
thenDepth_ = bce_->bytecodeSection().stackDepth();
thenDepth_ = bce_->stackDepth;
}
#endif
@ -59,10 +59,10 @@ bool BranchEmitterBase::emitThenInternal(SrcNoteType type) {
void BranchEmitterBase::calculateOrCheckPushed() {
#ifdef DEBUG
if (!calculatedPushed_) {
pushed_ = bce_->bytecodeSection().stackDepth() - thenDepth_;
pushed_ = bce_->stackDepth - thenDepth_;
calculatedPushed_ = true;
} else {
MOZ_ASSERT(pushed_ == bce_->bytecodeSection().stackDepth() - thenDepth_);
MOZ_ASSERT(pushed_ == bce_->stackDepth - thenDepth_);
}
#endif
}
@ -92,7 +92,7 @@ bool BranchEmitterBase::emitElseInternal() {
jumpAroundThen_ = JumpList();
// Restore stack depth of the then part.
bce_->bytecodeSection().setStackDepth(thenDepth_);
bce_->stackDepth = thenDepth_;
// Enclose else-branch with TDZCheckCache.
if (kind_ == Kind::MayContainLexicalAccessInBranch) {

View File

@ -27,7 +27,7 @@ bool LabelEmitter::emitLabel(JSAtom* name) {
return false;
}
controlInfo_.emplace(bce_, name, bce_->bytecodeSection().offset());
controlInfo_.emplace(bce_, name, bce_->offset());
#ifdef DEBUG
state_ = State::Label;
@ -39,8 +39,8 @@ bool LabelEmitter::emitEnd() {
MOZ_ASSERT(state_ == State::Label);
// Patch the JSOP_LABEL offset.
jsbytecode* labelpc = bce_->bytecodeSection().code(top_);
int32_t offset = bce_->bytecodeSection().lastNonJumpTargetOffset() - top_;
jsbytecode* labelpc = bce_->code(top_);
int32_t offset = bce_->lastNonJumpTargetOffset() - top_;
MOZ_ASSERT(*labelpc == JSOP_LABEL);
SET_CODE_OFFSET(labelpc, offset);

View File

@ -412,7 +412,7 @@ bool ObjectEmitter::emitObject(size_t propertyCount) {
// Emit code for {p:a, '%q':b, 2:c} that is equivalent to constructing
// a new object and defining (in source order) each property on the object
// (or mutating the object's [[Prototype]], in the case of __proto__).
top_ = bce_->bytecodeSection().offset();
top_ = bce_->offset();
if (!bce_->emitNewInit()) {
// [stack] OBJ
return false;

View File

@ -151,7 +151,7 @@ bool SwitchEmitter::emitCond() {
// After entering the scope if necessary, push the switch control.
controlInfo_.emplace(bce_, StatementKind::Switch);
top_ = bce_->bytecodeSection().offset();
top_ = bce_->offset();
if (!caseOffsets_.resize(caseCount_)) {
ReportOutOfMemory(bce_->cx);
@ -164,7 +164,7 @@ bool SwitchEmitter::emitCond() {
return false;
}
MOZ_ASSERT(top_ == bce_->bytecodeSection().offset());
MOZ_ASSERT(top_ == bce_->offset());
if (!bce_->emitN(JSOP_CONDSWITCH, 0)) {
return false;
}
@ -181,7 +181,7 @@ bool SwitchEmitter::emitTable(const TableGenerator& tableGen) {
// After entering the scope if necessary, push the switch control.
controlInfo_.emplace(bce_, StatementKind::Switch);
top_ = bce_->bytecodeSection().offset();
top_ = bce_->offset();
// The note has one offset that tells total switch code length.
if (!bce_->newSrcNote2(SRC_TABLESWITCH, 0, &noteIndex_)) {
@ -193,14 +193,14 @@ bool SwitchEmitter::emitTable(const TableGenerator& tableGen) {
return false;
}
MOZ_ASSERT(top_ == bce_->bytecodeSection().offset());
MOZ_ASSERT(top_ == bce_->offset());
if (!bce_->emitN(JSOP_TABLESWITCH,
JSOP_TABLESWITCH_LENGTH - sizeof(jsbytecode))) {
return false;
}
// Skip default offset.
jsbytecode* pc = bce_->bytecodeSection().code(top_ + JUMP_OFFSET_LEN);
jsbytecode* pc = bce_->code(top_ + JUMP_OFFSET_LEN);
// Fill in switch bounds, which we know fit in 16-bit offsets.
SET_JUMP_OFFSET(pc, tableGen.low());
@ -223,9 +223,9 @@ bool SwitchEmitter::emitCaseOrDefaultJump(uint32_t caseIndex, bool isDefault) {
if (caseIndex > 0) {
// Link the last JSOP_CASE's SRC_NEXTCASE to current JSOP_CASE for the
// benefit of IonBuilder.
if (!bce_->setSrcNoteOffset(
caseNoteIndex_, SrcNote::NextCase::NextCaseOffset,
bce_->bytecodeSection().offset() - lastCaseOffset_)) {
if (!bce_->setSrcNoteOffset(caseNoteIndex_,
SrcNote::NextCase::NextCaseOffset,
bce_->offset() - lastCaseOffset_)) {
return false;
}
}
@ -243,12 +243,11 @@ bool SwitchEmitter::emitCaseOrDefaultJump(uint32_t caseIndex, bool isDefault) {
if (caseIndex == 0) {
// Switch note's second offset is to first JSOP_CASE.
unsigned noteCount = bce_->bytecodeSection().notes().length();
unsigned noteCount = bce_->notes().length();
if (!bce_->setSrcNoteOffset(noteIndex_, 1, lastCaseOffset_ - top_)) {
return false;
}
unsigned noteCountDelta =
bce_->bytecodeSection().notes().length() - noteCount;
unsigned noteCountDelta = bce_->notes().length() - noteCount;
if (noteCountDelta != 0) {
caseNoteIndex_ += noteCountDelta;
}
@ -399,7 +398,7 @@ bool SwitchEmitter::emitEnd() {
defaultJumpTargetOffset_);
} else {
// Fill in the default jump target.
pc = bce_->bytecodeSection().code(top_);
pc = bce_->code(top_);
SET_JUMP_OFFSET(pc, defaultJumpTargetOffset_.offset - top_);
pc += JUMP_OFFSET_LEN;
}
@ -409,9 +408,8 @@ bool SwitchEmitter::emitEnd() {
static_assert(unsigned(SrcNote::TableSwitch::EndOffset) ==
unsigned(SrcNote::CondSwitch::EndOffset),
"{TableSwitch,CondSwitch}::EndOffset should be same");
if (!bce_->setSrcNoteOffset(
noteIndex_, SrcNote::TableSwitch::EndOffset,
bce_->bytecodeSection().lastNonJumpTargetOffset() - top_)) {
if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::TableSwitch::EndOffset,
bce_->lastNonJumpTargetOffset() - top_)) {
return false;
}

View File

@ -53,7 +53,7 @@ bool TryEmitter::emitTry() {
// For that we store in a try note associated with the catch or
// finally block the stack depth upon the try entry. The interpreter
// uses this depth to properly unwind the stack and the scope chain.
depth_ = bce_->bytecodeSection().stackDepth();
depth_ = bce_->stackDepth;
// Record the try location, then emit the try block.
if (!bce_->newSrcNote(SRC_TRY, &noteIndex_)) {
@ -62,7 +62,7 @@ bool TryEmitter::emitTry() {
if (!bce_->emit1(JSOP_TRY)) {
return false;
}
tryStart_ = bce_->bytecodeSection().offset();
tryStart_ = bce_->offset();
#ifdef DEBUG
state_ = State::Try;
@ -72,7 +72,7 @@ bool TryEmitter::emitTry() {
bool TryEmitter::emitTryEnd() {
MOZ_ASSERT(state_ == State::Try);
MOZ_ASSERT(depth_ == bce_->bytecodeSection().stackDepth());
MOZ_ASSERT(depth_ == bce_->stackDepth);
// GOSUB to finally, if present.
if (hasFinally() && controlInfo_) {
@ -82,9 +82,8 @@ bool TryEmitter::emitTryEnd() {
}
// Source note points to the jump at the end of the try block.
if (!bce_->setSrcNoteOffset(
noteIndex_, SrcNote::Try::EndOfTryJumpOffset,
bce_->bytecodeSection().offset() - tryStart_ + JSOP_TRY_LENGTH)) {
if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::Try::EndOfTryJumpOffset,
bce_->offset() - tryStart_ + JSOP_TRY_LENGTH)) {
return false;
}
@ -106,7 +105,7 @@ bool TryEmitter::emitCatch() {
return false;
}
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_);
MOZ_ASSERT(bce_->stackDepth == depth_);
if (controlKind_ == ControlKind::Syntactic) {
// Clear the frame's return value that might have been set by the
@ -139,7 +138,7 @@ bool TryEmitter::emitCatchEnd() {
if (!bce_->emitGoSub(&controlInfo_->gosubs)) {
return false;
}
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_);
MOZ_ASSERT(bce_->stackDepth == depth_);
// Jump over the finally block.
if (!bce_->emitJump(JSOP_GOTO, &catchAndFinallyJump_)) {
@ -178,7 +177,7 @@ bool TryEmitter::emitFinally(
}
}
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_);
MOZ_ASSERT(bce_->stackDepth == depth_);
if (!bce_->emitJumpTarget(&finallyStart_)) {
return false;
@ -254,7 +253,7 @@ bool TryEmitter::emitEnd() {
}
}
MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_);
MOZ_ASSERT(bce_->stackDepth == depth_);
// ReconstructPCStack needs a NOP here to mark the end of the last
// catch block.

View File

@ -100,8 +100,7 @@ bool WhileEmitter::emitEnd() {
return false;
}
if (!bce_->addTryNote(JSTRY_LOOP, bce_->bytecodeSection().stackDepth(),
loopInfo_->headOffset(),
if (!bce_->addTryNote(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
loopInfo_->breakTargetOffset())) {
return false;
}

View File

@ -3238,12 +3238,12 @@ PrivateScriptData* PrivateScriptData::new_(JSContext* cx, uint32_t nscopes,
/* static */ bool PrivateScriptData::InitFromEmitter(
JSContext* cx, js::HandleScript script, frontend::BytecodeEmitter* bce) {
uint32_t nscopes = bce->perScriptData().scopeList().length();
uint32_t nconsts = bce->perScriptData().numberList().length();
uint32_t nobjects = bce->perScriptData().objectList().length;
uint32_t ntrynotes = bce->bytecodeSection().tryNoteList().length();
uint32_t nscopenotes = bce->bytecodeSection().scopeNoteList().length();
uint32_t nresumeoffsets = bce->bytecodeSection().resumeOffsetList().length();
uint32_t nscopes = bce->scopeList.length();
uint32_t nconsts = bce->numberList.length();
uint32_t nobjects = bce->objectList.length;
uint32_t ntrynotes = bce->tryNoteList.length();
uint32_t nscopenotes = bce->scopeNoteList.length();
uint32_t nresumeoffsets = bce->resumeOffsetList.length();
// Create and initialize PrivateScriptData
if (!JSScript::createPrivateScriptData(cx, script, nscopes, nconsts, nobjects,
@ -3254,22 +3254,22 @@ PrivateScriptData* PrivateScriptData::new_(JSContext* cx, uint32_t nscopes,
js::PrivateScriptData* data = script->data_;
if (nscopes) {
bce->perScriptData().scopeList().finish(data->scopes());
bce->scopeList.finish(data->scopes());
}
if (nconsts) {
bce->perScriptData().numberList().finish(data->consts());
bce->numberList.finish(data->consts());
}
if (nobjects) {
bce->perScriptData().objectList().finish(data->objects());
bce->objectList.finish(data->objects());
}
if (ntrynotes) {
bce->bytecodeSection().tryNoteList().finish(data->tryNotes());
bce->tryNoteList.finish(data->tryNotes());
}
if (nscopenotes) {
bce->bytecodeSection().scopeNoteList().finish(data->scopeNotes());
bce->scopeNoteList.finish(data->scopeNotes());
}
if (nresumeoffsets) {
bce->bytecodeSection().resumeOffsetList().finish(data->resumeOffsets());
bce->resumeOffsetList.finish(data->resumeOffsets());
}
return true;
@ -3565,12 +3565,11 @@ bool JSScript::fullyInitFromEmitter(JSContext* cx, HandleScript script,
mozilla::MakeScopeExit([&] { script->freeScriptData(); });
/* The counts of indexed things must be checked during code generation. */
MOZ_ASSERT(bce->perScriptData().atomIndices()->count() <= INDEX_LIMIT);
MOZ_ASSERT(bce->perScriptData().objectList().length <= INDEX_LIMIT);
MOZ_ASSERT(bce->atomIndices->count() <= INDEX_LIMIT);
MOZ_ASSERT(bce->objectList.length <= INDEX_LIMIT);
uint64_t nslots =
bce->maxFixedSlots +
static_cast<uint64_t>(bce->bytecodeSection().maxStackDepth());
bce->maxFixedSlots + static_cast<uint64_t>(bce->maxStackDepth);
if (nslots > UINT32_MAX) {
bce->reportError(nullptr, JSMSG_NEED_DIET, js_script_str);
return false;
@ -3582,7 +3581,7 @@ bool JSScript::fullyInitFromEmitter(JSContext* cx, HandleScript script,
script->nfixed_ = bce->maxFixedSlots;
script->nslots_ = nslots;
script->bodyScopeIndex_ = bce->bodyScopeIndex;
script->numBytecodeTypeSets_ = bce->bytecodeSection().typesetCount();
script->numBytecodeTypeSets_ = bce->typesetCount;
// Initialize script flags from BytecodeEmitter
script->setFlag(ImmutableFlags::Strict, bce->sc->strict());
@ -3629,7 +3628,7 @@ bool JSScript::fullyInitFromEmitter(JSContext* cx, HandleScript script,
// Part of the parse result the scope containing each inner function must
// be stored in the inner function itself. Do this now that compilation is
// complete and can no longer fail.
bce->perScriptData().objectList().finishInnerFunctions();
bce->objectList.finishInnerFunctions();
#ifdef JS_STRUCTURED_SPEW
// We want this to happen after line number initialization to allow filtering
@ -4523,12 +4522,12 @@ bool JSScript::hasBreakpointsAt(jsbytecode* pc) {
/* static */ bool SharedScriptData::InitFromEmitter(
JSContext* cx, js::HandleScript script, frontend::BytecodeEmitter* bce) {
uint32_t natoms = bce->perScriptData().atomIndices()->count();
uint32_t codeLength = bce->bytecodeSection().code().length();
uint32_t natoms = bce->atomIndices->count();
uint32_t codeLength = bce->code().length();
// The + 1 is to account for the final SN_MAKE_TERMINATOR that is appended
// when the notes are copied to their final destination by copySrcNotes.
uint32_t noteLength = bce->bytecodeSection().notes().length() + 1;
uint32_t noteLength = bce->notes().length() + 1;
// Create and initialize SharedScriptData
if (!script->createSharedScriptData(cx, codeLength, noteLength, natoms)) {
@ -4538,9 +4537,9 @@ bool JSScript::hasBreakpointsAt(jsbytecode* pc) {
js::SharedScriptData* data = script->scriptData_;
// Initialize trailing arrays
std::copy_n(bce->bytecodeSection().code().begin(), codeLength, data->code());
std::copy_n(bce->code().begin(), codeLength, data->code());
bce->copySrcNotes(data->notes(), noteLength);
InitAtomMap(*bce->perScriptData().atomIndices(), data->atoms());
InitAtomMap(*bce->atomIndices, data->atoms());
return true;
}