зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
8b400ea6ce
Коммит
7d5a651b91
|
@ -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 = ¬es->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, ®exp));
|
||||
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, ®exp));
|
||||
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(¬e->index));
|
||||
MOZ_TRY(xdr->codeUint32(¬e->start));
|
||||
MOZ_TRY(xdr->codeUint32(¬e->length));
|
||||
MOZ_TRY(xdr->codeUint32(¬e->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 = ¬es->vector[mid];
|
||||
const ScopeNote* note = ¬es[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 = ¬es->vector[check];
|
||||
const ScopeNote* checkNote = ¬es[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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче