Bug 1485347 - Part 3: Use mozilla::Span for JSScript::data arrays. r=jandem

Replace various custom data-types in JSScript interfaces with
mozilla::Span. This abstracts implementation details and supports
range-based for-loops. Underlying storage is unchanged, but this sets us
up to be able to more easily change it.

MozReview-Commit-ID: FDfIYsAxTA8
This commit is contained in:
Ted Campbell 2018-08-22 23:02:43 -04:00
Родитель 8b400ea6ce
Коммит 7d5a651b91
16 изменённых файлов: 323 добавлений и 327 удалений

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

@ -15,6 +15,7 @@
#include "mozilla/FloatingPoint.h"
#include "mozilla/Maybe.h"
#include "mozilla/PodOperations.h"
#include "mozilla/ReverseIterator.h"
#include <string.h>
@ -9630,12 +9631,12 @@ BytecodeEmitter::copySrcNotes(jssrcnote* destination, uint32_t nsrcnotes)
}
void
CGNumberList::finish(ConstArray* array)
CGNumberList::finish(mozilla::Span<GCPtrValue> array)
{
MOZ_ASSERT(length() == array->length);
MOZ_ASSERT(length() == array.size());
for (unsigned i = 0; i < length(); i++) {
array->vector[i] = DoubleValue(list[i]);
array[i].init(DoubleValue(list[i]));
}
}
@ -9657,32 +9658,31 @@ CGObjectList::add(ObjectBox* objbox)
}
void
CGObjectList::finish(ObjectArray* array)
CGObjectList::finish(mozilla::Span<GCPtrObject> array)
{
MOZ_ASSERT(length <= INDEX_LIMIT);
MOZ_ASSERT(length == array->length);
MOZ_ASSERT(length == array.size());
js::GCPtrObject* cursor = array->vector + array->length;
ObjectBox* objbox = lastbox;
do {
--cursor;
MOZ_ASSERT(!*cursor);
for (GCPtrObject& obj : mozilla::Reversed(array)) {
MOZ_ASSERT(obj == nullptr);
MOZ_ASSERT(objbox->object->isTenured());
if (objbox->isFunctionBox()) {
objbox->asFunctionBox()->finish();
}
*cursor = objbox->object;
} while ((objbox = objbox->emitLink) != nullptr);
MOZ_ASSERT(cursor == array->vector);
obj.init(objbox->object);
objbox = objbox->emitLink;
}
}
void
CGScopeList::finish(ScopeArray* array)
CGScopeList::finish(mozilla::Span<GCPtrScope> array)
{
MOZ_ASSERT(length() <= INDEX_LIMIT);
MOZ_ASSERT(length() == array->length);
MOZ_ASSERT(length() == array.size());
for (uint32_t i = 0; i < length(); i++) {
array->vector[i].init(vector[i]);
array[i].init(vector[i]);
}
}
@ -9703,12 +9703,12 @@ CGTryNoteList::append(JSTryNoteKind kind, uint32_t stackDepth, size_t start, siz
}
void
CGTryNoteList::finish(TryNoteArray* array)
CGTryNoteList::finish(mozilla::Span<JSTryNote> array)
{
MOZ_ASSERT(length() == array->length);
MOZ_ASSERT(length() == array.size());
for (unsigned i = 0; i < length(); i++) {
array->vector[i] = list[i];
array[i] = list[i];
}
}
@ -9737,9 +9737,9 @@ CGScopeNoteList::recordEnd(uint32_t index, uint32_t offset, bool inPrologue)
}
void
CGScopeNoteList::finish(ScopeNoteArray* array, uint32_t prologueLength)
CGScopeNoteList::finish(mozilla::Span<ScopeNote> array, uint32_t prologueLength)
{
MOZ_ASSERT(length() == array->length);
MOZ_ASSERT(length() == array.size());
for (unsigned i = 0; i < length(); i++) {
if (!list[i].startInPrologue) {
@ -9750,14 +9750,14 @@ CGScopeNoteList::finish(ScopeNoteArray* array, uint32_t prologueLength)
}
MOZ_ASSERT(list[i].end >= list[i].start);
list[i].length = list[i].end - list[i].start;
array->vector[i] = list[i];
array[i] = list[i];
}
}
void
CGYieldAndAwaitOffsetList::finish(YieldAndAwaitOffsetArray& array, uint32_t prologueLength)
CGYieldAndAwaitOffsetList::finish(mozilla::Span<uint32_t> array, uint32_t prologueLength)
{
MOZ_ASSERT(length() == array.length());
MOZ_ASSERT(length() == array.size());
for (unsigned i = 0; i < length(); i++) {
array[i] = prologueLength + list[i];

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

@ -10,6 +10,7 @@
#define frontend_BytecodeEmitter_h
#include "mozilla/Attributes.h"
#include "mozilla/Span.h"
#include "ds/InlineTable.h"
#include "frontend/BCEParserHandle.h"
@ -34,7 +35,7 @@ class CGNumberList {
return list.append(v);
}
size_t length() const { return list.length(); }
void finish(ConstArray* array);
void finish(mozilla::Span<GCPtrValue> array);
};
struct CGObjectList {
@ -44,7 +45,7 @@ struct CGObjectList {
CGObjectList() : length(0), lastbox(nullptr) {}
unsigned add(ObjectBox* objbox);
void finish(ObjectArray* array);
void finish(mozilla::Span<GCPtrObject> array);
};
struct MOZ_STACK_CLASS CGScopeList {
@ -56,7 +57,7 @@ struct MOZ_STACK_CLASS CGScopeList {
bool append(Scope* scope) { return vector.append(scope); }
uint32_t length() const { return vector.length(); }
void finish(ScopeArray* array);
void finish(mozilla::Span<GCPtrScope> array);
};
struct CGTryNoteList {
@ -65,7 +66,7 @@ struct CGTryNoteList {
MOZ_MUST_USE bool append(JSTryNoteKind kind, uint32_t stackDepth, size_t start, size_t end);
size_t length() const { return list.length(); }
void finish(TryNoteArray* array);
void finish(mozilla::Span<JSTryNote> array);
};
struct CGScopeNote : public ScopeNote
@ -89,7 +90,7 @@ struct CGScopeNoteList {
uint32_t parent);
void recordEnd(uint32_t index, uint32_t offset, bool inPrologue);
size_t length() const { return list.length(); }
void finish(ScopeNoteArray* array, uint32_t prologueLength);
void finish(mozilla::Span<ScopeNote> array, uint32_t prologueLength);
};
struct CGYieldAndAwaitOffsetList {
@ -100,7 +101,7 @@ struct CGYieldAndAwaitOffsetList {
MOZ_MUST_USE bool append(uint32_t offset) { return list.append(offset); }
size_t length() const { return list.length(); }
void finish(YieldAndAwaitOffsetArray& array, uint32_t prologueLength);
void finish(mozilla::Span<uint32_t> array, uint32_t prologueLength);
};
// Have a few inline elements, so as to avoid heap allocation for tiny

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

@ -489,21 +489,20 @@ HasLiveStackValueAtDepth(JSScript* script, jsbytecode* pc, uint32_t stackDepth)
return false;
}
JSTryNote* tn = script->trynotes()->vector;
JSTryNote* tnEnd = tn + script->trynotes()->length;
uint32_t pcOffset = uint32_t(pc - script->main());
for (; tn != tnEnd; ++tn) {
if (pcOffset < tn->start) {
for (const JSTryNote& tn : script->trynotes()) {
if (pcOffset < tn.start) {
continue;
}
if (pcOffset >= tn->start + tn->length) {
if (pcOffset >= tn.start + tn.length) {
continue;
}
switch (tn->kind) {
switch (tn.kind) {
case JSTRY_FOR_IN:
// For-in loops have only the iterator on stack.
if (stackDepth == tn->stackDepth) {
if (stackDepth == tn.stackDepth) {
return true;
}
break;
@ -513,7 +512,7 @@ HasLiveStackValueAtDepth(JSScript* script, jsbytecode* pc, uint32_t stackDepth)
// result.value on stack.
// The iterator is below the result.value, the next method below
// the iterator.
if (stackDepth == tn->stackDepth - 1 || stackDepth == tn->stackDepth - 2) {
if (stackDepth == tn.stackDepth - 1 || stackDepth == tn.stackDepth - 2) {
return true;
}
break;
@ -521,7 +520,7 @@ HasLiveStackValueAtDepth(JSScript* script, jsbytecode* pc, uint32_t stackDepth)
case JSTRY_DESTRUCTURING_ITERCLOSE:
// Destructuring code that need to call IteratorClose have both
// the iterator and the "done" value on the stack.
if (stackDepth == tn->stackDepth || stackDepth == tn->stackDepth - 1) {
if (stackDepth == tn.stackDepth || stackDepth == tn.stackDepth - 1) {
return true;
}
break;

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

@ -117,14 +117,12 @@ BytecodeAnalysis::init(TempAllocator& alloc, GSNCache& gsn)
}
case JSOP_TRY: {
JSTryNote* tn = script_->trynotes()->vector;
JSTryNote* tnlimit = tn + script_->trynotes()->length;
for (; tn < tnlimit; tn++) {
unsigned startOffset = script_->mainOffset() + tn->start;
for (const JSTryNote& tn : script_->trynotes()) {
unsigned startOffset = script_->mainOffset() + tn.start;
if (startOffset == offset + 1) {
unsigned catchOffset = startOffset + tn->length;
unsigned catchOffset = startOffset + tn.length;
if (tn->kind != JSTRY_FOR_IN) {
if (tn.kind != JSTRY_FOR_IN) {
infos_[catchOffset].init(stackDepth);
infos_[catchOffset].jumpTarget = true;
}

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

@ -564,10 +564,8 @@ ControlFlowGenerator::processTry()
// Try-finally is not yet supported.
if (!checkedTryFinally_) {
JSTryNote* tn = script->trynotes()->vector;
JSTryNote* tnlimit = tn + script->trynotes()->length;
for (; tn < tnlimit; tn++) {
if (tn->kind == JSTRY_FINALLY) {
for (const JSTryNote& tn : script->trynotes()) {
if (tn.kind == JSTRY_FINALLY) {
return ControlStatus::Abort;
}
}

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

@ -105,7 +105,7 @@ NumArgAndLocalSlots(const InlineFrameIterator& frame)
}
static void
CloseLiveIteratorIon(JSContext* cx, const InlineFrameIterator& frame, JSTryNote* tn)
CloseLiveIteratorIon(JSContext* cx, const InlineFrameIterator& frame, const JSTryNote* tn)
{
MOZ_ASSERT(tn->kind == JSTRY_FOR_IN ||
tn->kind == JSTRY_DESTRUCTURING_ITERCLOSE);
@ -223,7 +223,7 @@ HandleExceptionIon(JSContext* cx, const InlineFrameIterator& frame, ResumeFromEx
bool inForOfIterClose = false;
for (TryNoteIterIon tni(cx, frame); !tni.done(); ++tni) {
JSTryNote* tn = *tni;
const JSTryNote* tn = *tni;
switch (tn->kind) {
case JSTRY_FOR_IN:
@ -305,7 +305,7 @@ ForcedReturn(JSContext* cx, const JSJitFrameIter& frame, jsbytecode* pc,
}
static inline void
BaselineFrameAndStackPointersFromTryNote(JSTryNote* tn, const JSJitFrameIter& frame,
BaselineFrameAndStackPointersFromTryNote(const JSTryNote* tn, const JSJitFrameIter& frame,
uint8_t** framePointer, uint8_t** stackPointer)
{
JSScript* script = frame.baselineFrame()->script();
@ -315,7 +315,7 @@ BaselineFrameAndStackPointersFromTryNote(JSTryNote* tn, const JSJitFrameIter& fr
}
static void
SettleOnTryNote(JSContext* cx, JSTryNote* tn, const JSJitFrameIter& frame,
SettleOnTryNote(JSContext* cx, const JSTryNote* tn, const JSJitFrameIter& frame,
EnvironmentIter& ei, ResumeFromException* rfe, jsbytecode** pc)
{
RootedScript script(cx, frame.baselineFrame()->script());
@ -376,7 +376,7 @@ CloseLiveIteratorsBaselineForUncatchableException(JSContext* cx, const JSJitFram
{
bool inForOfIterClose = false;
for (TryNoteIterBaseline tni(cx, frame.baselineFrame(), pc); !tni.done(); ++tni) {
JSTryNote* tn = *tni;
const JSTryNote* tn = *tni;
switch (tn->kind) {
case JSTRY_FOR_IN: {
// See corresponding comment in ProcessTryNotes.
@ -415,7 +415,7 @@ ProcessTryNotesBaseline(JSContext* cx, const JSJitFrameIter& frame, EnvironmentI
bool inForOfIterClose = false;
for (TryNoteIterBaseline tni(cx, frame.baselineFrame(), *pc); !tni.done(); ++tni) {
JSTryNote* tn = *tni;
const JSTryNote* tn = *tni;
MOZ_ASSERT(cx->isExceptionPending());
switch (tn->kind) {

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

@ -3072,17 +3072,15 @@ TryNotes(JSContext* cx, HandleScript script, Sprinter* sp)
return false;
}
JSTryNote* tn = script->trynotes()->vector;
JSTryNote* tnlimit = tn + script->trynotes()->length;
do {
uint32_t startOff = script->pcToOffset(script->main()) + tn->start;
for (const JSTryNote& tn : script->trynotes()) {
uint32_t startOff = script->pcToOffset(script->main()) + tn.start;
if (!sp->jsprintf(" %-16s %6u %8u %8u\n",
TryNoteName(static_cast<JSTryNoteKind>(tn->kind)),
tn->stackDepth, startOff, startOff + tn->length))
TryNoteName(static_cast<JSTryNoteKind>(tn.kind)),
tn.stackDepth, startOff, startOff + tn.length))
{
return false;
}
} while (++tn != tnlimit);
}
return true;
}
@ -3097,28 +3095,26 @@ ScopeNotes(JSContext* cx, HandleScript script, Sprinter* sp)
return false;
}
ScopeNoteArray* notes = script->scopeNotes();
for (uint32_t i = 0; i < notes->length; i++) {
const ScopeNote* note = &notes->vector[i];
if (note->index == ScopeNote::NoScopeIndex) {
for (const ScopeNote& note : script->scopeNotes()) {
if (note.index == ScopeNote::NoScopeIndex) {
if (!sp->jsprintf("%8s ", "(none)")) {
return false;
}
} else {
if (!sp->jsprintf("%8u ", note->index)) {
if (!sp->jsprintf("%8u ", note.index)) {
return false;
}
}
if (note->parent == ScopeNote::NoScopeIndex) {
if (note.parent == ScopeNote::NoScopeIndex) {
if (!sp->jsprintf("%8s ", "(none)")) {
return false;
}
} else {
if (!sp->jsprintf("%8u ", note->parent)) {
if (!sp->jsprintf("%8u ", note.parent)) {
return false;
}
}
if (!sp->jsprintf("%8u %8u\n", note->start, note->start + note->length)) {
if (!sp->jsprintf("%8u %8u\n", note.start, note.start + note.length)) {
return false;
}
}
@ -3189,9 +3185,7 @@ DisassembleScript(JSContext* cx, HandleScript script, HandleFunction fun,
}
if (recursive && script->hasObjects()) {
ObjectArray* objects = script->objects();
for (unsigned i = 0; i != objects->length; ++i) {
JSObject* obj = objects->vector[i];
for (JSObject* obj : script->objects()) {
if (obj->is<JSFunction>()) {
if (!sp->put("\n")) {
return false;

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

@ -13,6 +13,7 @@
#define __STDC_FORMAT_MACROS
#include "mozilla/Attributes.h"
#include "mozilla/ReverseIterator.h"
#include "mozilla/Sprintf.h"
#include "mozilla/Vector.h"
@ -945,19 +946,17 @@ BytecodeParser::parse()
// Note that there is no problem with code which is skipped by a thrown
// exception but is not caught by a later handler in the same function:
// no more code will execute, and it does not matter what is defined.
JSTryNote* tn = script_->trynotes()->vector;
JSTryNote* tnlimit = tn + script_->trynotes()->length;
for (; tn < tnlimit; tn++) {
uint32_t startOffset = script_->mainOffset() + tn->start;
for (const JSTryNote& tn : script_->trynotes()) {
uint32_t startOffset = script_->mainOffset() + tn.start;
if (startOffset == offset + 1) {
uint32_t catchOffset = startOffset + tn->length;
if (tn->kind == JSTRY_CATCH) {
uint32_t catchOffset = startOffset + tn.length;
if (tn.kind == JSTRY_CATCH) {
if (!addJump(catchOffset, &nextOffset, stackDepth, offsetStack,
pc, JumpKind::TryCatch))
{
return false;
}
} else if (tn->kind == JSTRY_FINALLY) {
} else if (tn.kind == JSTRY_FINALLY) {
if (!addJump(catchOffset, &nextOffset, stackDepth, offsetStack,
pc, JumpKind::TryFinally))
{
@ -1455,15 +1454,12 @@ Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
// with an offset. This simplifies code coverage analysis
// based on this disassembled output.
if (op == JSOP_TRY) {
TryNoteArray* trynotes = script->trynotes();
uint32_t i;
size_t mainOffset = script->mainOffset();
for(i = 0; i < trynotes->length; i++) {
JSTryNote note = trynotes->vector[i];
if (note.kind == JSTRY_CATCH && note.start + mainOffset == loc + 1) {
for (const JSTryNote& tn : script->trynotes()) {
if (tn.kind == JSTRY_CATCH && tn.start + mainOffset == loc + 1) {
if (!sp->jsprintf(" %u (%+d)",
unsigned(loc + note.length + 1),
int(note.length + 1)))
unsigned(loc + tn.length + 1),
int(tn.length + 1)))
{
return 0;
}
@ -3120,10 +3116,8 @@ GenerateLcovInfo(JSContext* cx, JS::Realm* realm, GenericPrinter& out)
if (!script->hasObjects()) {
continue;
}
size_t idx = script->objects()->length;
while (idx--) {
JSObject* obj = script->getObject(idx);
auto objects = script->objects();
for (JSObject* obj : mozilla::Reversed(objects)) {
// Only continue on JSFunction objects.
if (!obj->is<JSFunction>()) {
continue;

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

@ -6238,12 +6238,10 @@ DebuggerScript_getChildScripts(JSContext* cx, unsigned argc, Value* vp)
// and the calling function is stored as script->objects()->vector[0].
// It is not really a child script of this script, so skip it using
// innerObjectsStart().
ObjectArray* objects = script->objects();
RootedFunction fun(cx);
RootedScript funScript(cx);
RootedObject obj(cx), s(cx);
for (uint32_t i = 0; i < objects->length; i++) {
obj = objects->vector[i];
RootedObject s(cx);
for (const GCPtrObject& obj : script->objects()) {
if (obj->is<JSFunction>()) {
fun = &obj->as<JSFunction>();
// The inner function could be a wasm native.
@ -6429,13 +6427,11 @@ class FlowGraphSummary {
// was an incoming edge of the catch block. This is needed
// because we only report offsets of entry points which have
// valid incoming edges.
JSTryNote* tn = script->trynotes()->vector;
JSTryNote* tnlimit = tn + script->trynotes()->length;
for (; tn < tnlimit; tn++) {
uint32_t startOffset = script->mainOffset() + tn->start;
for (const JSTryNote& tn : script->trynotes()) {
uint32_t startOffset = script->mainOffset() + tn.start;
if (startOffset == r.frontOffset() + 1) {
uint32_t catchOffset = startOffset + tn->length;
if (tn->kind == JSTRY_CATCH || tn->kind == JSTRY_FINALLY) {
uint32_t catchOffset = startOffset + tn.length;
if (tn.kind == JSTRY_CATCH || tn.kind == JSTRY_FINALLY) {
addEdge(lineno, column, catchOffset);
}
}
@ -7455,17 +7451,14 @@ class DebuggerScriptIsInCatchScopeMatcher
size_t offset = offset_ - script->mainOffset();
if (script->hasTrynotes()) {
JSTryNote* tnBegin = script->trynotes()->vector;
JSTryNote* tnEnd = tnBegin + script->trynotes()->length;
while (tnBegin != tnEnd) {
if (tnBegin->start <= offset &&
offset <= tnBegin->start + tnBegin->length &&
tnBegin->kind == JSTRY_CATCH)
for (const JSTryNote& tn : script->trynotes()) {
if (tn.start <= offset &&
offset <= tn.start + tn.length &&
tn.kind == JSTRY_CATCH)
{
isInCatch_ = true;
return true;
}
++tnBegin;
}
}
isInCatch_ = false;

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

@ -3912,11 +3912,9 @@ RemoveReferencedNames(JSContext* cx, HandleScript script, PropertyNameSet& remai
}
if (script->hasObjects()) {
ObjectArray* objects = script->objects();
RootedFunction fun(cx);
RootedScript innerScript(cx);
for (size_t i = 0; i < objects->length; i++) {
JSObject* obj = objects->vector[i];
for (JSObject* obj : script->objects()) {
if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpreted()) {
fun = &obj->as<JSFunction>();
innerScript = JSFunction::getOrCreateScript(cx, fun);
@ -3984,11 +3982,9 @@ AnalyzeEntrainedVariablesInScript(JSContext* cx, HandleScript script, HandleScri
}
if (innerScript->hasObjects()) {
ObjectArray* objects = innerScript->objects();
RootedFunction fun(cx);
RootedScript innerInnerScript(cx);
for (size_t i = 0; i < objects->length; i++) {
JSObject* obj = objects->vector[i];
for (JSObject* obj : script->objects()) {
if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpreted()) {
fun = &obj->as<JSFunction>();
innerInnerScript = JSFunction::getOrCreateScript(cx, fun);
@ -4022,11 +4018,9 @@ js::AnalyzeEntrainedVariables(JSContext* cx, HandleScript script)
return true;
}
ObjectArray* objects = script->objects();
RootedFunction fun(cx);
RootedScript innerScript(cx);
for (size_t i = 0; i < objects->length; i++) {
JSObject* obj = objects->vector[i];
for (JSObject* obj : script->objects()) {
if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpreted()) {
fun = &obj->as<JSFunction>();
innerScript = JSFunction::getOrCreateScript(cx, fun);

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

@ -1303,7 +1303,7 @@ js::UnwindAllEnvironmentsInFrame(JSContext* cx, EnvironmentIter& ei)
// will have no pc location distinguishing the try block scope from the inner
// let block scope.
jsbytecode*
js::UnwindEnvironmentToTryPc(JSScript* script, JSTryNote* tn)
js::UnwindEnvironmentToTryPc(JSScript* script, const JSTryNote* tn)
{
jsbytecode* pc = script->main() + tn->start;
if (tn->kind == JSTRY_CATCH || tn->kind == JSTRY_FINALLY) {
@ -1327,7 +1327,7 @@ ForcedReturn(JSContext* cx, InterpreterRegs& regs)
}
static void
SettleOnTryNote(JSContext* cx, JSTryNote* tn, EnvironmentIter& ei, InterpreterRegs& regs)
SettleOnTryNote(JSContext* cx, const JSTryNote* tn, EnvironmentIter& ei, InterpreterRegs& regs)
{
// Unwind the environment to the beginning of the JSOP_TRY.
UnwindEnvironment(cx, ei, UnwindEnvironmentToTryPc(regs.fp()->script(), tn));
@ -1363,7 +1363,7 @@ UnwindIteratorsForUncatchableException(JSContext* cx, const InterpreterRegs& reg
// ProcessTryNotes.
bool inForOfIterClose = false;
for (TryNoteIterInterpreter tni(cx, regs); !tni.done(); ++tni) {
JSTryNote* tn = *tni;
const JSTryNote* tn = *tni;
switch (tn->kind) {
case JSTRY_FOR_IN: {
// See corresponding comment in ProcessTryNotes.
@ -1403,7 +1403,7 @@ ProcessTryNotes(JSContext* cx, EnvironmentIter& ei, InterpreterRegs& regs)
{
bool inForOfIterClose = false;
for (TryNoteIterInterpreter tni(cx, regs); !tni.done(); ++tni) {
JSTryNote* tn = *tni;
const JSTryNote* tn = *tni;
switch (tn->kind) {
case JSTRY_CATCH:

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

@ -345,17 +345,18 @@ UnwindAllEnvironmentsInFrame(JSContext* cx, EnvironmentIter& ei);
// Compute the pc needed to unwind the scope to the beginning of the block
// pointed to by the try note.
extern jsbytecode*
UnwindEnvironmentToTryPc(JSScript* script, JSTryNote* tn);
UnwindEnvironmentToTryPc(JSScript* script, const JSTryNote* tn);
template <class StackDepthOp>
class MOZ_STACK_CLASS TryNoteIter
{
RootedScript script_;
uint32_t pcOffset_;
JSTryNote* tn_;
JSTryNote* tnEnd_;
StackDepthOp getStackDepth_;
const JSTryNote* tn_;
const JSTryNote* tnEnd_;
void settle() {
for (; tn_ != tnEnd_; ++tn_) {
/* If pc is out of range, try the next one. */
@ -396,8 +397,11 @@ class MOZ_STACK_CLASS TryNoteIter
getStackDepth_(getStackDepth)
{
if (script->hasTrynotes()) {
tn_ = script->trynotes()->vector;
tnEnd_ = tn_ + script->trynotes()->length;
// NOTE: The Span is a temporary so we can't use begin()/end()
// here or the iterator will outlive the span.
auto trynotes = script->trynotes();
tn_ = trynotes.data();
tnEnd_ = tn_ + trynotes.size();
} else {
tn_ = tnEnd_ = nullptr;
}
@ -410,7 +414,7 @@ class MOZ_STACK_CLASS TryNoteIter
}
bool done() const { return tn_ == tnEnd_; }
JSTryNote* operator*() const { return tn_; }
const JSTryNote* operator*() const { return tn_; }
};
bool

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

@ -304,11 +304,10 @@ XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun, HandleScript scri
static inline uint32_t
FindScopeIndex(JSScript* script, Scope& scope)
{
ScopeArray* scopes = script->scopes();
GCPtrScope* vector = scopes->vector;
unsigned length = scopes->length;
auto scopes = script->scopes();
unsigned length = scopes.size();
for (uint32_t i = 0; i < length; ++i) {
if (vector[i] == &scope) {
if (scopes[i] == &scope) {
return i;
}
}
@ -358,7 +357,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
};
uint32_t length, lineno, column, nfixed, nslots;
uint32_t natoms, nsrcnotes, i;
uint32_t natoms, nsrcnotes;
uint32_t nconsts, nobjects, nscopes, nregexps, ntrynotes, nscopenotes, nyieldoffsets;
uint32_t prologueLength;
uint32_t funLength = 0;
@ -408,20 +407,20 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
nsrcnotes = script->numNotes();
if (script->hasConsts()) {
nconsts = script->consts()->length;
nconsts = script->consts().size();
}
if (script->hasObjects()) {
nobjects = script->objects()->length;
nobjects = script->objects().size();
}
nscopes = script->scopes()->length;
nscopes = script->scopes().size();
if (script->hasTrynotes()) {
ntrynotes = script->trynotes()->length;
ntrynotes = script->trynotes().size();
}
if (script->hasScopeNotes()) {
nscopenotes = script->scopeNotes()->length;
nscopenotes = script->scopeNotes().size();
}
if (script->hasYieldAndAwaitOffsets()) {
nyieldoffsets = script->yieldAndAwaitOffsets().length();
nyieldoffsets = script->yieldAndAwaitOffsets().size();
}
nTypeSets = script->nTypeSets();
@ -704,7 +703,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
MOZ_TRY(xdr->codeBytes(code, length));
MOZ_TRY(xdr->codeBytes(code + length, nsrcnotes));
for (i = 0; i != natoms; ++i) {
for (uint32_t i = 0; i != natoms; ++i) {
if (mode == XDR_DECODE) {
RootedAtom tmp(cx);
MOZ_TRY(XDRAtom(xdr, &tmp));
@ -723,27 +722,26 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
}
if (nconsts) {
GCPtrValue* vector = script->consts()->vector;
RootedValue val(cx);
for (i = 0; i != nconsts; ++i) {
for (GCPtrValue& elem : script->consts()) {
if (mode == XDR_ENCODE) {
val = vector[i];
val = elem.get();
}
MOZ_TRY(XDRScriptConst(xdr, &val));
if (mode == XDR_DECODE) {
vector[i].init(val);
elem.init(val);
}
}
}
{
MOZ_ASSERT(nscopes != 0);
GCPtrScope* vector = script->scopes()->vector;
GCPtrScope* vector = script->scopes().data();
RootedScope scope(cx);
RootedScope enclosing(cx);
ScopeKind scopeKind;
uint32_t enclosingScopeIndex = 0;
for (i = 0; i != nscopes; ++i) {
for (uint32_t i = 0; i != nscopes; ++i) {
if (mode == XDR_ENCODE) {
scope = vector[i];
scopeKind = scope->kind();
@ -834,87 +832,94 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
* all references to enclosing blocks (via FindScopeIndex below) happen
* after the enclosing block has been XDR'd.
*/
for (i = 0; i != nobjects; ++i) {
GCPtrObject* objp = &script->objects()->vector[i];
XDRClassKind classk;
if (nobjects) {
for (GCPtrObject& elem : script->objects()) {
XDRClassKind classk;
if (mode == XDR_ENCODE) {
JSObject* obj = *objp;
if (obj->is<RegExpObject>()) {
classk = CK_RegexpObject;
} else if (obj->is<JSFunction>()) {
classk = CK_JSFunction;
} else if (obj->is<PlainObject>() || obj->is<ArrayObject>()) {
classk = CK_JSObject;
} else {
MOZ_CRASH("Cannot encode this class of object.");
}
}
MOZ_TRY(xdr->codeEnum32(&classk));
switch (classk) {
case CK_RegexpObject: {
Rooted<RegExpObject*> regexp(cx);
if (mode == XDR_ENCODE) {
regexp = &(*objp)->as<RegExpObject>();
}
MOZ_TRY(XDRScriptRegExpObject(xdr, &regexp));
if (mode == XDR_DECODE) {
*objp = regexp;
}
break;
}
case CK_JSFunction: {
/* Code the nested function's enclosing scope. */
uint32_t funEnclosingScopeIndex = 0;
RootedScope funEnclosingScope(cx);
if (mode == XDR_ENCODE) {
RootedFunction function(cx, &(*objp)->as<JSFunction>());
if (function->isInterpretedLazy()) {
funEnclosingScope = function->lazyScript()->enclosingScope();
} else if (function->isInterpreted()) {
funEnclosingScope = function->nonLazyScript()->enclosingScope();
JSObject* obj = elem.get();
if (obj->is<RegExpObject>()) {
classk = CK_RegexpObject;
} else if (obj->is<JSFunction>()) {
classk = CK_JSFunction;
} else if (obj->is<PlainObject>() || obj->is<ArrayObject>()) {
classk = CK_JSObject;
} else {
MOZ_ASSERT(function->isAsmJSNative());
return xdr->fail(JS::TranscodeResult_Failure_AsmJSNotSupported);
MOZ_CRASH("Cannot encode this class of object.");
}
}
MOZ_TRY(xdr->codeEnum32(&classk));
switch (classk) {
case CK_RegexpObject: {
Rooted<RegExpObject*> regexp(cx);
if (mode == XDR_ENCODE) {
regexp = &elem->as<RegExpObject>();
}
MOZ_TRY(XDRScriptRegExpObject(xdr, &regexp));
if (mode == XDR_DECODE) {
elem.init(regexp);
}
break;
}
case CK_JSFunction: {
/* Code the nested function's enclosing scope. */
uint32_t funEnclosingScopeIndex = 0;
RootedScope funEnclosingScope(cx);
if (mode == XDR_ENCODE) {
RootedFunction function(cx, &elem->as<JSFunction>());
if (function->isInterpretedLazy()) {
funEnclosingScope = function->lazyScript()->enclosingScope();
} else if (function->isInterpreted()) {
funEnclosingScope = function->nonLazyScript()->enclosingScope();
} else {
MOZ_ASSERT(function->isAsmJSNative());
return xdr->fail(JS::TranscodeResult_Failure_AsmJSNotSupported);
}
funEnclosingScopeIndex = FindScopeIndex(script, *funEnclosingScope);
}
funEnclosingScopeIndex = FindScopeIndex(script, *funEnclosingScope);
MOZ_TRY(xdr->codeUint32(&funEnclosingScopeIndex));
if (mode == XDR_DECODE) {
funEnclosingScope = script->getScope(funEnclosingScopeIndex);
}
// Code nested function and script.
RootedFunction tmp(cx);
if (mode == XDR_ENCODE) {
tmp = &elem->as<JSFunction>();
}
MOZ_TRY(XDRInterpretedFunction(xdr, funEnclosingScope, sourceObject, &tmp));
if (mode == XDR_DECODE) {
elem.init(tmp);
}
break;
}
case CK_JSObject: {
/* Code object literal. */
RootedObject tmp(cx);
if (mode == XDR_ENCODE) {
tmp = elem.get();
}
MOZ_TRY(XDRObjectLiteral(xdr, &tmp));
if (mode == XDR_DECODE) {
elem.init(tmp);
}
break;
}
default: {
// Fail in debug, but only soft-fail in release
MOZ_ASSERT(false, "Bad XDR class kind");
return xdr->fail(JS::TranscodeResult_Failure_BadDecode);
}
}
MOZ_TRY(xdr->codeUint32(&funEnclosingScopeIndex));
if (mode == XDR_DECODE) {
MOZ_ASSERT(funEnclosingScopeIndex < script->scopes()->length);
funEnclosingScope = script->scopes()->vector[funEnclosingScopeIndex];
}
// Code nested function and script.
RootedFunction tmp(cx);
if (mode == XDR_ENCODE) {
tmp = &(*objp)->as<JSFunction>();
}
MOZ_TRY(XDRInterpretedFunction(xdr, funEnclosingScope, sourceObject, &tmp));
*objp = tmp;
break;
}
case CK_JSObject: {
/* Code object literal. */
RootedObject tmp(cx, *objp);
MOZ_TRY(XDRObjectLiteral(xdr, &tmp));
*objp = tmp;
break;
}
default: {
// Fail in debug, but only soft-fail in release
MOZ_ASSERT(false, "Bad XDR class kind");
return xdr->fail(JS::TranscodeResult_Failure_BadDecode);
}
}
}
@ -922,30 +927,28 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
// mismatch here indicates we will almost certainly crash in release.
MOZ_TRY(xdr->codeMarker(0xF83B989A));
if (ntrynotes != 0) {
JSTryNote* tnfirst = script->trynotes()->vector;
MOZ_ASSERT(script->trynotes()->length == ntrynotes);
JSTryNote* tn = tnfirst + ntrynotes;
do {
--tn;
MOZ_TRY(xdr->codeUint8(&tn->kind));
MOZ_TRY(xdr->codeUint32(&tn->stackDepth));
MOZ_TRY(xdr->codeUint32(&tn->start));
MOZ_TRY(xdr->codeUint32(&tn->length));
} while (tn != tnfirst);
if (ntrynotes) {
for (JSTryNote& elem : script->trynotes()) {
MOZ_TRY(xdr->codeUint8(&elem.kind));
MOZ_TRY(xdr->codeUint32(&elem.stackDepth));
MOZ_TRY(xdr->codeUint32(&elem.start));
MOZ_TRY(xdr->codeUint32(&elem.length));
}
}
for (i = 0; i < nscopenotes; ++i) {
ScopeNote* note = &script->scopeNotes()->vector[i];
MOZ_TRY(xdr->codeUint32(&note->index));
MOZ_TRY(xdr->codeUint32(&note->start));
MOZ_TRY(xdr->codeUint32(&note->length));
MOZ_TRY(xdr->codeUint32(&note->parent));
if (nscopenotes) {
for (ScopeNote& elem : script->scopeNotes()) {
MOZ_TRY(xdr->codeUint32(&elem.index));
MOZ_TRY(xdr->codeUint32(&elem.start));
MOZ_TRY(xdr->codeUint32(&elem.length));
MOZ_TRY(xdr->codeUint32(&elem.parent));
}
}
for (i = 0; i < nyieldoffsets; ++i) {
uint32_t* offset = &script->yieldAndAwaitOffsets()[i];
MOZ_TRY(xdr->codeUint32(offset));
if (nyieldoffsets) {
for (uint32_t& elem : script->yieldAndAwaitOffsets()) {
MOZ_TRY(xdr->codeUint32(&elem));
}
}
if (scriptBits & (1 << HasLazyScript)) {
@ -2967,25 +2970,25 @@ JSScript::partiallyInit(JSContext* cx, HandleScript script, uint32_t nscopes,
if (nconsts != 0) {
MOZ_ASSERT(reinterpret_cast<uintptr_t>(cursor) % sizeof(JS::Value) == 0);
script->consts()->length = nconsts;
script->consts()->vector = (GCPtrValue*)cursor;
cursor += nconsts * sizeof(script->consts()->vector[0]);
script->constsRaw()->length = nconsts;
script->constsRaw()->vector = (GCPtrValue*)cursor;
cursor += nconsts * sizeof(script->constsRaw()->vector[0]);
}
script->scopes()->length = nscopes;
script->scopes()->vector = (GCPtrScope*)cursor;
cursor += nscopes * sizeof(script->scopes()->vector[0]);
script->scopesRaw()->length = nscopes;
script->scopesRaw()->vector = (GCPtrScope*)cursor;
cursor += nscopes * sizeof(script->scopesRaw()->vector[0]);
if (nobjects != 0) {
script->objects()->length = nobjects;
script->objects()->vector = (GCPtrObject*)cursor;
cursor += nobjects * sizeof(script->objects()->vector[0]);
script->objectsRaw()->length = nobjects;
script->objectsRaw()->vector = (GCPtrObject*)cursor;
cursor += nobjects * sizeof(script->objectsRaw()->vector[0]);
}
if (ntrynotes != 0) {
script->trynotes()->length = ntrynotes;
script->trynotes()->vector = reinterpret_cast<JSTryNote*>(cursor);
size_t vectorSize = ntrynotes * sizeof(script->trynotes()->vector[0]);
script->trynotesRaw()->length = ntrynotes;
script->trynotesRaw()->vector = reinterpret_cast<JSTryNote*>(cursor);
size_t vectorSize = ntrynotes * sizeof(script->trynotesRaw()->vector[0]);
#ifdef DEBUG
memset(cursor, 0, vectorSize);
#endif
@ -2993,9 +2996,9 @@ JSScript::partiallyInit(JSContext* cx, HandleScript script, uint32_t nscopes,
}
if (nscopenotes != 0) {
script->scopeNotes()->length = nscopenotes;
script->scopeNotes()->vector = reinterpret_cast<ScopeNote*>(cursor);
size_t vectorSize = nscopenotes * sizeof(script->scopeNotes()->vector[0]);
script->scopeNotesRaw()->length = nscopenotes;
script->scopeNotesRaw()->vector = reinterpret_cast<ScopeNote*>(cursor);
size_t vectorSize = nscopenotes * sizeof(script->scopeNotesRaw()->vector[0]);
#ifdef DEBUG
memset(cursor, 0, vectorSize);
#endif
@ -3004,7 +3007,7 @@ JSScript::partiallyInit(JSContext* cx, HandleScript script, uint32_t nscopes,
if (nyieldoffsets != 0) {
yieldAndAwaitOffsets->init(reinterpret_cast<uint32_t*>(cursor), nyieldoffsets);
size_t vectorSize = nyieldoffsets * sizeof(script->yieldAndAwaitOffsets()[0]);
size_t vectorSize = nyieldoffsets * sizeof(script->yieldAndAwaitOffsetsRaw()[0]);
#ifdef DEBUG
memset(cursor, 0, vectorSize);
#endif
@ -3039,7 +3042,7 @@ JSScript::initFunctionPrototype(JSContext* cx, Handle<JSScript*> script,
if (!functionProtoScope) {
return false;
}
script->scopes()->vector[0].init(functionProtoScope);
script->scopesRaw()->vector[0].init(functionProtoScope);
uint32_t codeLength = 1;
uint32_t srcNotesLength = 1;
@ -3272,17 +3275,15 @@ JSScript::assertValidJumpTargets() const
// Check catch/finally blocks as jump targets.
if (hasTrynotes()) {
JSTryNote* tn = trynotes()->vector;
JSTryNote* tnlimit = tn + trynotes()->length;
for (; tn < tnlimit; tn++) {
jsbytecode* tryStart = mainEntry + tn->start;
for (const JSTryNote& tn : trynotes()) {
jsbytecode* tryStart = mainEntry + tn.start;
jsbytecode* tryPc = tryStart - 1;
if (tn->kind != JSTRY_CATCH && tn->kind != JSTRY_FINALLY) {
if (tn.kind != JSTRY_CATCH && tn.kind != JSTRY_FINALLY) {
continue;
}
MOZ_ASSERT(JSOp(*tryPc) == JSOP_TRY);
jsbytecode* tryTarget = tryStart + tn->length;
jsbytecode* tryTarget = tryStart + tn.length;
MOZ_ASSERT(mainEntry <= tryTarget && tryTarget < end);
MOZ_ASSERT(BytecodeIsJumpTarget(JSOp(*tryTarget)));
}
@ -3665,12 +3666,12 @@ js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
/* Some embeddings are not careful to use ExposeObjectToActiveJS as needed. */
MOZ_ASSERT(!src->sourceObject()->isMarkedGray());
uint32_t nconsts = src->hasConsts() ? src->consts()->length : 0;
uint32_t nobjects = src->hasObjects() ? src->objects()->length : 0;
uint32_t nscopes = src->scopes()->length;
uint32_t ntrynotes = src->hasTrynotes() ? src->trynotes()->length : 0;
uint32_t nscopenotes = src->hasScopeNotes() ? src->scopeNotes()->length : 0;
uint32_t nyieldoffsets = src->hasYieldAndAwaitOffsets() ? src->yieldAndAwaitOffsets().length() : 0;
uint32_t nconsts = src->hasConsts() ? src->consts().size() : 0;
uint32_t nobjects = src->hasObjects() ? src->objects().size() : 0;
uint32_t nscopes = src->scopes().size();
uint32_t ntrynotes = src->hasTrynotes() ? src->trynotes().size() : 0;
uint32_t nscopenotes = src->hasScopeNotes() ? src->scopeNotes().size() : 0;
uint32_t nyieldoffsets = src->hasYieldAndAwaitOffsets() ? src->yieldAndAwaitOffsets().size() : 0;
/* Script data */
@ -3689,11 +3690,10 @@ js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
{
MOZ_ASSERT(nscopes != 0);
MOZ_ASSERT(src->bodyScopeIndex() + 1 == scopes.length());
GCPtrScope* vector = src->scopes()->vector;
RootedScope original(cx);
RootedScope clone(cx);
for (uint32_t i = scopes.length(); i < nscopes; i++) {
original = vector[i];
for (const GCPtrScope& elem : src->scopes().From(scopes.length())) {
original = elem.get();
clone = Scope::clone(cx, original, scopes[FindScopeIndex(src, *original->enclosing())]);
if (!clone || !scopes.append(clone)) {
return false;
@ -3705,11 +3705,10 @@ js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
AutoObjectVector objects(cx);
if (nobjects != 0) {
GCPtrObject* vector = src->objects()->vector;
RootedObject obj(cx);
RootedObject clone(cx);
for (unsigned i = 0; i < nobjects; i++) {
obj = vector[i];
for (const GCPtrObject& elem : src->objects()) {
obj = elem.get();
clone = nullptr;
if (obj->is<RegExpObject>()) {
clone = CloneScriptRegExpObject(cx, obj->as<RegExpObject>());
@ -3796,35 +3795,35 @@ js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
dst->bitFields_.hideScriptFromDebugger_ = src->bitFields_.hideScriptFromDebugger_;
if (nconsts != 0) {
GCPtrValue* vector = Rebase<GCPtrValue>(dst, src, src->consts()->vector);
dst->consts()->vector = vector;
GCPtrValue* vector = Rebase<GCPtrValue>(dst, src, src->constsRaw()->vector);
dst->constsRaw()->vector = vector;
for (unsigned i = 0; i < nconsts; ++i) {
MOZ_ASSERT_IF(vector[i].isGCThing(), vector[i].toString()->isAtom());
}
}
if (nobjects != 0) {
GCPtrObject* vector = Rebase<GCPtrObject>(dst, src, src->objects()->vector);
dst->objects()->vector = vector;
GCPtrObject* vector = Rebase<GCPtrObject>(dst, src, src->objectsRaw()->vector);
dst->objectsRaw()->vector = vector;
for (unsigned i = 0; i < nobjects; ++i) {
vector[i].init(&objects[i]->as<NativeObject>());
}
}
{
GCPtrScope* vector = Rebase<GCPtrScope>(dst, src, src->scopes()->vector);
dst->scopes()->vector = vector;
GCPtrScope* vector = Rebase<GCPtrScope>(dst, src, src->scopesRaw()->vector);
dst->scopesRaw()->vector = vector;
for (uint32_t i = 0; i < nscopes; ++i) {
vector[i].init(scopes[i]);
}
}
if (ntrynotes != 0) {
dst->trynotes()->vector = Rebase<JSTryNote>(dst, src, src->trynotes()->vector);
dst->trynotesRaw()->vector = Rebase<JSTryNote>(dst, src, src->trynotesRaw()->vector);
}
if (nscopenotes != 0) {
dst->scopeNotes()->vector = Rebase<ScopeNote>(dst, src, src->scopeNotes()->vector);
dst->scopeNotesRaw()->vector = Rebase<ScopeNote>(dst, src, src->scopeNotesRaw()->vector);
}
if (nyieldoffsets != 0) {
dst->yieldAndAwaitOffsets().vector_ =
Rebase<uint32_t>(dst, src, src->yieldAndAwaitOffsets().vector_);
dst->yieldAndAwaitOffsetsRaw().vector_ =
Rebase<uint32_t>(dst, src, src->yieldAndAwaitOffsetsRaw().vector_);
}
return true;
@ -4173,18 +4172,19 @@ JSScript::traceChildren(JSTracer* trc)
scriptData()->traceChildren(trc);
}
if (ScopeArray* scopearray = scopes()) {
TraceRange(trc, scopearray->length, scopearray->vector, "scopes");
if (data) {
auto array = scopes();
TraceRange(trc, array.size(), array.data(), "scopes");
}
if (hasConsts()) {
ConstArray* constarray = consts();
TraceRange(trc, constarray->length, constarray->vector, "consts");
auto array = consts();
TraceRange(trc, array.size(), array.data(), "consts");
}
if (hasObjects()) {
ObjectArray* objarray = objects();
TraceRange(trc, objarray->length, objarray->vector, "objects");
auto array = objects();
TraceRange(trc, array.size(), array.data(), "objects");
}
MOZ_ASSERT_IF(sourceObject(), MaybeForwarded(sourceObject())->compartment() == compartment());
@ -4252,16 +4252,16 @@ JSScript::lookupScope(jsbytecode* pc)
size_t offset = pc - code();
ScopeNoteArray* notes = scopeNotes();
auto notes = scopeNotes();
Scope* scope = nullptr;
// Find the innermost block chain using a binary search.
size_t bottom = 0;
size_t top = notes->length;
size_t top = notes.size();
while (bottom < top) {
size_t mid = bottom + (top - bottom) / 2;
const ScopeNote* note = &notes->vector[mid];
const ScopeNote* note = &notes[mid];
if (note->start <= offset) {
// Block scopes are ordered in the list by their starting offset, and since
// blocks form a tree ones earlier in the list may cover the pc even if
@ -4270,7 +4270,7 @@ JSScript::lookupScope(jsbytecode* pc)
// the searched range for coverage.
size_t check = mid;
while (check >= bottom) {
const ScopeNote* checkNote = &notes->vector[check];
const ScopeNote* checkNote = &notes[check];
MOZ_ASSERT(checkNote->start <= offset);
if (offset < checkNote->start + checkNote->length) {
// We found a matching block chain but there may be inner ones
@ -4724,10 +4724,8 @@ JSScript::hasLoops()
if (!hasTrynotes()) {
return false;
}
JSTryNote* tn = trynotes()->vector;
JSTryNote* tnlimit = tn + trynotes()->length;
for (; tn < tnlimit; tn++) {
switch (tn->kind) {
for (const JSTryNote& tn : trynotes()) {
switch (tn.kind) {
case JSTRY_FOR_IN:
case JSTRY_FOR_OF:
case JSTRY_LOOP:

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

@ -13,6 +13,7 @@
#include "mozilla/Atomics.h"
#include "mozilla/Maybe.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Span.h"
#include "mozilla/Variant.h"
#include "jstypes.h"
@ -1825,8 +1826,7 @@ class JSScript : public js::gc::TenuredCell
js::VarScope* functionExtraBodyVarScope() const {
MOZ_ASSERT(functionHasExtraBodyVarScope());
for (uint32_t i = 0; i < scopes()->length; i++) {
js::Scope* scope = getScope(i);
for (js::Scope* scope : scopes()) {
if (scope->kind() == js::ScopeKind::FunctionBodyVar) {
return &scope->as<js::VarScope>();
}
@ -1835,8 +1835,7 @@ class JSScript : public js::gc::TenuredCell
}
bool needsBodyEnvironment() const {
for (uint32_t i = 0; i < scopes()->length; i++) {
js::Scope* scope = getScope(i);
for (js::Scope* scope : scopes()) {
if (ScopeKindIsInBody(scope->kind()) && scope->hasEnvironment()) {
return true;
}
@ -1931,36 +1930,70 @@ class JSScript : public js::gc::TenuredCell
size_t dataSize() const { return dataSize_; }
js::ConstArray* consts() {
private:
js::ConstArray* constsRaw() const {
MOZ_ASSERT(hasConsts());
return reinterpret_cast<js::ConstArray*>(data + constsOffset());
}
js::ObjectArray* objects() {
js::ObjectArray* objectsRaw() const {
MOZ_ASSERT(hasObjects());
return reinterpret_cast<js::ObjectArray*>(data + objectsOffset());
}
js::ScopeArray* scopes() const {
js::ScopeArray* scopesRaw() const {
return reinterpret_cast<js::ScopeArray*>(data + scopesOffset());
}
js::TryNoteArray* trynotes() const {
js::TryNoteArray* trynotesRaw() const {
MOZ_ASSERT(hasTrynotes());
return reinterpret_cast<js::TryNoteArray*>(data + trynotesOffset());
}
js::ScopeNoteArray* scopeNotes() {
js::ScopeNoteArray* scopeNotesRaw() const {
MOZ_ASSERT(hasScopeNotes());
return reinterpret_cast<js::ScopeNoteArray*>(data + scopeNotesOffset());
}
js::YieldAndAwaitOffsetArray& yieldAndAwaitOffsets() {
js::YieldAndAwaitOffsetArray& yieldAndAwaitOffsetsRaw() const {
MOZ_ASSERT(hasYieldAndAwaitOffsets());
return *reinterpret_cast<js::YieldAndAwaitOffsetArray*>(data +
yieldAndAwaitOffsetsOffset());
}
public:
mozilla::Span<js::GCPtrValue> consts() const {
js::ConstArray* array = constsRaw();
return mozilla::MakeSpan(array->vector, array->length);
}
mozilla::Span<js::GCPtrObject> objects() const {
js::ObjectArray* array = objectsRaw();
return mozilla::MakeSpan(array->vector, array->length);
}
mozilla::Span<js::GCPtrScope> scopes() const {
js::ScopeArray* array = scopesRaw();
return mozilla::MakeSpan(array->vector, array->length);
}
mozilla::Span<JSTryNote> trynotes() const {
js::TryNoteArray* array = trynotesRaw();
return mozilla::MakeSpan(array->vector, array->length);
}
mozilla::Span<js::ScopeNote> scopeNotes() const {
js::ScopeNoteArray* array = scopeNotesRaw();
return mozilla::MakeSpan(array->vector, array->length);
}
mozilla::Span<uint32_t> yieldAndAwaitOffsets() const {
js::YieldAndAwaitOffsetArray& array = yieldAndAwaitOffsetsRaw();
return mozilla::MakeSpan(&array[0], array.length());
}
bool hasLoops();
uint32_t numNotes() const {
@ -2001,10 +2034,8 @@ class JSScript : public js::gc::TenuredCell
}
JSObject* getObject(size_t index) {
js::ObjectArray* arr = objects();
MOZ_ASSERT(index < arr->length);
MOZ_ASSERT(arr->vector[index]->isTenured());
return arr->vector[index];
MOZ_ASSERT(objects()[index]->isTenured());
return objects()[index];
}
JSObject* getObject(jsbytecode* pc) {
@ -2013,9 +2044,7 @@ class JSScript : public js::gc::TenuredCell
}
js::Scope* getScope(size_t index) const {
js::ScopeArray* array = scopes();
MOZ_ASSERT(index < array->length);
return array->vector[index];
return scopes()[index];
}
js::Scope* getScope(jsbytecode* pc) const {
@ -2040,9 +2069,7 @@ class JSScript : public js::gc::TenuredCell
inline js::RegExpObject* getRegExp(jsbytecode* pc);
const js::Value& getConst(size_t index) {
js::ConstArray* arr = consts();
MOZ_ASSERT(index < arr->length);
return arr->vector[index];
return consts()[index];
}
// The following 3 functions find the static scope just before the

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

@ -240,15 +240,13 @@ ObjectGroup::useSingletonForAllocationSite(JSScript* script, jsbytecode* pc, JSP
unsigned offset = script->pcToOffset(pc);
JSTryNote* tn = script->trynotes()->vector;
JSTryNote* tnlimit = tn + script->trynotes()->length;
for (; tn < tnlimit; tn++) {
if (tn->kind != JSTRY_FOR_IN && tn->kind != JSTRY_FOR_OF && tn->kind != JSTRY_LOOP) {
for (const JSTryNote& tn : script->trynotes()) {
if (tn.kind != JSTRY_FOR_IN && tn.kind != JSTRY_FOR_OF && tn.kind != JSTRY_LOOP) {
continue;
}
unsigned startOffset = script->mainOffset() + tn->start;
unsigned endOffset = startOffset + tn->length;
unsigned startOffset = script->mainOffset() + tn.start;
unsigned endOffset = startOffset + tn.length;
if (offset >= startOffset && offset < endOffset) {
return GenericObject;

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

@ -710,9 +710,7 @@ AddInnerLazyFunctionsFromScript(JSScript* script, AutoObjectVector& lazyFunction
if (!script->hasObjects()) {
return true;
}
ObjectArray* objects = script->objects();
for (size_t i = 0; i < objects->length; i++) {
JSObject* obj = objects->vector[i];
for (JSObject* obj : script->objects()) {
if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpretedLazy()) {
if (!lazyFunctions.append(obj)) {
return false;