diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index ab95fff33214..5461adf04f35 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -15,6 +15,7 @@ #include "mozilla/FloatingPoint.h" #include "mozilla/Maybe.h" #include "mozilla/PodOperations.h" +#include "mozilla/ReverseIterator.h" #include @@ -9630,12 +9631,12 @@ BytecodeEmitter::copySrcNotes(jssrcnote* destination, uint32_t nsrcnotes) } void -CGNumberList::finish(ConstArray* array) +CGNumberList::finish(mozilla::Span 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 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 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 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 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 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]; diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 768c55184d1c..f2e701692aa4 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -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 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 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 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 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 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 array, uint32_t prologueLength); }; // Have a few inline elements, so as to avoid heap allocation for tiny diff --git a/js/src/jit/BaselineBailouts.cpp b/js/src/jit/BaselineBailouts.cpp index e71e251cf0e4..34a2e433551f 100644 --- a/js/src/jit/BaselineBailouts.cpp +++ b/js/src/jit/BaselineBailouts.cpp @@ -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; diff --git a/js/src/jit/BytecodeAnalysis.cpp b/js/src/jit/BytecodeAnalysis.cpp index 35b6fc34c800..eb436bd90956 100644 --- a/js/src/jit/BytecodeAnalysis.cpp +++ b/js/src/jit/BytecodeAnalysis.cpp @@ -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; } diff --git a/js/src/jit/IonControlFlow.cpp b/js/src/jit/IonControlFlow.cpp index a491fb149086..3b08ad072424 100644 --- a/js/src/jit/IonControlFlow.cpp +++ b/js/src/jit/IonControlFlow.cpp @@ -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; } } diff --git a/js/src/jit/JitFrames.cpp b/js/src/jit/JitFrames.cpp index 6af967a8a021..d7cc30186863 100644 --- a/js/src/jit/JitFrames.cpp +++ b/js/src/jit/JitFrames.cpp @@ -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) { diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 6467ba196aae..dfd02cdbc968 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -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(tn->kind)), - tn->stackDepth, startOff, startOff + tn->length)) + TryNoteName(static_cast(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()) { if (!sp->put("\n")) { return false; diff --git a/js/src/vm/BytecodeUtil.cpp b/js/src/vm/BytecodeUtil.cpp index 025637745f8e..b3e4d12c6dfc 100644 --- a/js/src/vm/BytecodeUtil.cpp +++ b/js/src/vm/BytecodeUtil.cpp @@ -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()) { continue; diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index e6832e9e4782..323b6ceab517 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -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()) { fun = &obj->as(); // 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; diff --git a/js/src/vm/EnvironmentObject.cpp b/js/src/vm/EnvironmentObject.cpp index e8da5c381fff..3f1ed16d5075 100644 --- a/js/src/vm/EnvironmentObject.cpp +++ b/js/src/vm/EnvironmentObject.cpp @@ -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() && obj->as().isInterpreted()) { fun = &obj->as(); 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() && obj->as().isInterpreted()) { fun = &obj->as(); 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() && obj->as().isInterpreted()) { fun = &obj->as(); innerScript = JSFunction::getOrCreateScript(cx, fun); diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 2a46f1aebf76..6c2fb6c05c27 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -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: diff --git a/js/src/vm/Interpreter.h b/js/src/vm/Interpreter.h index 675203f154f0..4cacf85b29a7 100644 --- a/js/src/vm/Interpreter.h +++ b/js/src/vm/Interpreter.h @@ -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 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 diff --git a/js/src/vm/JSScript.cpp b/js/src/vm/JSScript.cpp index 166c2661bbc2..f104933c09ea 100644 --- a/js/src/vm/JSScript.cpp +++ b/js/src/vm/JSScript.cpp @@ -304,11 +304,10 @@ XDRRelazificationInfo(XDRState* 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* 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* 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* 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* 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* 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()) { - classk = CK_RegexpObject; - } else if (obj->is()) { - classk = CK_JSFunction; - } else if (obj->is() || obj->is()) { - classk = CK_JSObject; - } else { - MOZ_CRASH("Cannot encode this class of object."); - } - } - - MOZ_TRY(xdr->codeEnum32(&classk)); - - switch (classk) { - case CK_RegexpObject: { - Rooted regexp(cx); if (mode == XDR_ENCODE) { - regexp = &(*objp)->as(); - } - 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()); - - if (function->isInterpretedLazy()) { - funEnclosingScope = function->lazyScript()->enclosingScope(); - } else if (function->isInterpreted()) { - funEnclosingScope = function->nonLazyScript()->enclosingScope(); + JSObject* obj = elem.get(); + if (obj->is()) { + classk = CK_RegexpObject; + } else if (obj->is()) { + classk = CK_JSFunction; + } else if (obj->is() || obj->is()) { + 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 regexp(cx); + if (mode == XDR_ENCODE) { + regexp = &elem->as(); + } + 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()); + + 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(); + } + 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(); - } - 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* 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(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(cursor); - size_t vectorSize = ntrynotes * sizeof(script->trynotes()->vector[0]); + script->trynotesRaw()->length = ntrynotes; + script->trynotesRaw()->vector = reinterpret_cast(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(cursor); - size_t vectorSize = nscopenotes * sizeof(script->scopeNotes()->vector[0]); + script->scopeNotesRaw()->length = nscopenotes; + script->scopeNotesRaw()->vector = reinterpret_cast(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(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 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()) { clone = CloneScriptRegExpObject(cx, obj->as()); @@ -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(dst, src, src->consts()->vector); - dst->consts()->vector = vector; + GCPtrValue* vector = Rebase(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(dst, src, src->objects()->vector); - dst->objects()->vector = vector; + GCPtrObject* vector = Rebase(dst, src, src->objectsRaw()->vector); + dst->objectsRaw()->vector = vector; for (unsigned i = 0; i < nobjects; ++i) { vector[i].init(&objects[i]->as()); } } { - GCPtrScope* vector = Rebase(dst, src, src->scopes()->vector); - dst->scopes()->vector = vector; + GCPtrScope* vector = Rebase(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(dst, src, src->trynotes()->vector); + dst->trynotesRaw()->vector = Rebase(dst, src, src->trynotesRaw()->vector); } if (nscopenotes != 0) { - dst->scopeNotes()->vector = Rebase(dst, src, src->scopeNotes()->vector); + dst->scopeNotesRaw()->vector = Rebase(dst, src, src->scopeNotesRaw()->vector); } if (nyieldoffsets != 0) { - dst->yieldAndAwaitOffsets().vector_ = - Rebase(dst, src, src->yieldAndAwaitOffsets().vector_); + dst->yieldAndAwaitOffsetsRaw().vector_ = + Rebase(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: diff --git a/js/src/vm/JSScript.h b/js/src/vm/JSScript.h index af5c501fa8e3..5104265d03ca 100644 --- a/js/src/vm/JSScript.h +++ b/js/src/vm/JSScript.h @@ -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(); } @@ -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(data + constsOffset()); } - js::ObjectArray* objects() { + js::ObjectArray* objectsRaw() const { MOZ_ASSERT(hasObjects()); return reinterpret_cast(data + objectsOffset()); } - js::ScopeArray* scopes() const { + js::ScopeArray* scopesRaw() const { return reinterpret_cast(data + scopesOffset()); } - js::TryNoteArray* trynotes() const { + js::TryNoteArray* trynotesRaw() const { MOZ_ASSERT(hasTrynotes()); return reinterpret_cast(data + trynotesOffset()); } - js::ScopeNoteArray* scopeNotes() { + js::ScopeNoteArray* scopeNotesRaw() const { MOZ_ASSERT(hasScopeNotes()); return reinterpret_cast(data + scopeNotesOffset()); } - js::YieldAndAwaitOffsetArray& yieldAndAwaitOffsets() { + js::YieldAndAwaitOffsetArray& yieldAndAwaitOffsetsRaw() const { MOZ_ASSERT(hasYieldAndAwaitOffsets()); return *reinterpret_cast(data + yieldAndAwaitOffsetsOffset()); } + public: + + mozilla::Span consts() const { + js::ConstArray* array = constsRaw(); + return mozilla::MakeSpan(array->vector, array->length); + } + + mozilla::Span objects() const { + js::ObjectArray* array = objectsRaw(); + return mozilla::MakeSpan(array->vector, array->length); + } + + mozilla::Span scopes() const { + js::ScopeArray* array = scopesRaw(); + return mozilla::MakeSpan(array->vector, array->length); + } + + mozilla::Span trynotes() const { + js::TryNoteArray* array = trynotesRaw(); + return mozilla::MakeSpan(array->vector, array->length); + } + + mozilla::Span scopeNotes() const { + js::ScopeNoteArray* array = scopeNotesRaw(); + return mozilla::MakeSpan(array->vector, array->length); + } + + mozilla::Span 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 diff --git a/js/src/vm/ObjectGroup.cpp b/js/src/vm/ObjectGroup.cpp index 8f9050d283a4..baaa7956a3c7 100644 --- a/js/src/vm/ObjectGroup.cpp +++ b/js/src/vm/ObjectGroup.cpp @@ -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; diff --git a/js/src/vm/Realm.cpp b/js/src/vm/Realm.cpp index 08cc509cbbb7..1eaa5b532b0d 100644 --- a/js/src/vm/Realm.cpp +++ b/js/src/vm/Realm.cpp @@ -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() && obj->as().isInterpretedLazy()) { if (!lazyFunctions.append(obj)) { return false;