LCOV - code coverage report
Current view: top level - js/src/vm - Scope.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 55 669 8.2 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "vm/Scope.h"
       8             : 
       9             : #include <memory>
      10             : #include <new>
      11             : 
      12             : #include "builtin/ModuleObject.h"
      13             : #include "gc/Allocator.h"
      14             : #include "gc/FreeOp.h"
      15             : #include "util/StringBuffer.h"
      16             : #include "vm/EnvironmentObject.h"
      17             : #include "vm/JSScript.h"
      18             : #include "wasm/WasmInstance.h"
      19             : 
      20             : #include "gc/ObjectKind-inl.h"
      21             : #include "vm/Shape-inl.h"
      22             : 
      23             : using namespace js;
      24             : 
      25           0 : using mozilla::Maybe;
      26             : 
      27           0 : const char*
      28             : js::BindingKindString(BindingKind kind)
      29             : {
      30             :     switch (kind) {
      31           0 :       case BindingKind::Import:
      32             :         return "import";
      33           0 :       case BindingKind::FormalParameter:
      34             :         return "formal parameter";
      35           0 :       case BindingKind::Var:
      36             :         return "var";
      37           0 :       case BindingKind::Let:
      38             :         return "let";
      39           0 :       case BindingKind::Const:
      40             :         return "const";
      41           0 :       case BindingKind::NamedLambdaCallee:
      42             :         return "named lambda callee";
      43             :     }
      44             :     MOZ_CRASH("Bad BindingKind");
      45           0 : }
      46             : 
      47           0 : const char*
      48             : js::ScopeKindString(ScopeKind kind)
      49             : {
      50             :     switch (kind) {
      51           0 :       case ScopeKind::Function:
      52             :         return "function";
      53           0 :       case ScopeKind::FunctionBodyVar:
      54             :         return "function body var";
      55           0 :       case ScopeKind::ParameterExpressionVar:
      56             :         return "parameter expression var";
      57             :       case ScopeKind::Lexical:
      58           0 :         return "lexical";
      59             :       case ScopeKind::SimpleCatch:
      60           0 :       case ScopeKind::Catch:
      61             :         return "catch";
      62           0 :       case ScopeKind::NamedLambda:
      63             :         return "named lambda";
      64           0 :       case ScopeKind::StrictNamedLambda:
      65             :         return "strict named lambda";
      66           0 :       case ScopeKind::With:
      67             :         return "with";
      68           0 :       case ScopeKind::Eval:
      69             :         return "eval";
      70           0 :       case ScopeKind::StrictEval:
      71             :         return "strict eval";
      72           0 :       case ScopeKind::Global:
      73             :         return "global";
      74           0 :       case ScopeKind::NonSyntactic:
      75             :         return "non-syntactic";
      76           0 :       case ScopeKind::Module:
      77             :         return "module";
      78           0 :       case ScopeKind::WasmInstance:
      79             :         return "wasm instance";
      80           0 :       case ScopeKind::WasmFunction:
      81             :         return "wasm function";
      82             :     }
      83             :     MOZ_CRASH("Bad ScopeKind");
      84           0 : }
      85             : 
      86             : static Shape*
      87             : EmptyEnvironmentShape(JSContext* cx, const Class* cls, uint32_t numSlots,
      88           0 :                       uint32_t baseShapeFlags)
      89           0 : {
      90           0 :     // Put as many slots into the object header as possible.
      91             :     uint32_t numFixed = gc::GetGCKindSlots(gc::GetGCObjectKind(numSlots));
      92             :     return EmptyShape::getInitialShape(cx, cls, TaggedProto(nullptr), numFixed,
      93             :                                        baseShapeFlags);
      94           0 : }
      95             : 
      96             : static Shape*
      97           0 : NextEnvironmentShape(JSContext* cx, HandleAtom name, BindingKind bindKind, uint32_t slot,
      98           0 :                      StackBaseShape& stackBase, HandleShape shape)
      99             : {
     100             :     UnownedBaseShape* base = BaseShape::getUnowned(cx, stackBase);
     101           0 :     if (!base)
     102           0 :         return nullptr;
     103             : 
     104             :     unsigned attrs = JSPROP_PERMANENT | JSPROP_ENUMERATE;
     105           0 :     switch (bindKind) {
     106           0 :       case BindingKind::Const:
     107             :       case BindingKind::NamedLambdaCallee:
     108             :         attrs |= JSPROP_READONLY;
     109             :         break;
     110             :       default:
     111           0 :         break;
     112           0 :     }
     113           0 : 
     114             :     jsid id = NameToId(name->asPropertyName());
     115             :     Rooted<StackShape> child(cx, StackShape(base, id, slot, attrs));
     116             :     return cx->zone()->propertyTree().getChild(cx, shape, child);
     117           0 : }
     118             : 
     119             : static Shape*
     120           0 : CreateEnvironmentShape(JSContext* cx, BindingIter& bi, const Class* cls,
     121           0 :                        uint32_t numSlots, uint32_t baseShapeFlags)
     122             : {
     123             :     RootedShape shape(cx, EmptyEnvironmentShape(cx, cls, numSlots, baseShapeFlags));
     124           0 :     if (!shape)
     125             :         return nullptr;
     126           0 : 
     127           0 :     RootedAtom name(cx);
     128           0 :     StackBaseShape stackBase(cls, baseShapeFlags);
     129           0 :     for (; bi; bi++) {
     130           0 :         BindingLocation loc = bi.location();
     131           0 :         if (loc.kind() == BindingLocation::Kind::Environment) {
     132           0 :             name = bi.name();
     133           0 :             cx->markAtom(name);
     134             :             shape = NextEnvironmentShape(cx, name, bi.kind(), loc.slot(), stackBase, shape);
     135             :             if (!shape)
     136             :                 return nullptr;
     137           0 :         }
     138             :     }
     139             : 
     140             :     return shape;
     141             : }
     142           0 : 
     143             : template <typename ConcreteScope>
     144             : static UniquePtr<typename ConcreteScope::Data>
     145             : CopyScopeData(JSContext* cx, Handle<typename ConcreteScope::Data*> data)
     146           0 : {
     147           0 :     // Make sure the binding names are marked in the context's zone, if we are
     148           0 :     // copying data from another zone.
     149           0 :     BindingName* names = data->trailingNames.start();
     150           0 :     uint32_t length = data->length;
     151           0 :     for (size_t i = 0; i < length; i++) {
     152             :         if (JSAtom* name = names[i].name())
     153             :             cx->markAtom(name);
     154           0 :     }
     155           0 : 
     156           0 :     size_t size = SizeOfData<typename ConcreteScope::Data>(data->length);
     157           0 :     void* bytes = cx->zone()->pod_malloc<char>(size);
     158             :     if (!bytes) {
     159           0 :         ReportOutOfMemory(cx);
     160           0 :         return nullptr;
     161           0 :     }
     162             : 
     163             :     auto* dataCopy = new (bytes) typename ConcreteScope::Data(*data);
     164             : 
     165           0 :     std::uninitialized_copy_n(names, length, dataCopy->trailingNames.start());
     166           0 : 
     167             :     return UniquePtr<typename ConcreteScope::Data>(dataCopy);
     168           0 : }
     169           0 : 
     170             : template <typename ConcreteScope>
     171           0 : static bool
     172             : PrepareScopeData(JSContext* cx, BindingIter& bi, Handle<UniquePtr<typename ConcreteScope::Data>> data,
     173             :                  const Class* cls, uint32_t baseShapeFlags, MutableHandleShape envShape)
     174             : {
     175             :     // Copy a fresh BindingIter for use below.
     176             :     BindingIter freshBi(bi);
     177           0 : 
     178             :     // Iterate through all bindings. This counts the number of environment
     179             :     // slots needed and computes the maximum frame slot.
     180             :     while (bi)
     181           0 :         bi++;
     182             :     data->nextFrameSlot = bi.canHaveFrameSlots() ? bi.nextFrameSlot() : LOCALNO_LIMIT;
     183             : 
     184             :     // Make a new environment shape if any environment slots were used.
     185           0 :     if (bi.nextEnvironmentSlot() == JSSLOT_FREE(cls)) {
     186           0 :         envShape.set(nullptr);
     187           0 :     } else {
     188             :         envShape.set(CreateEnvironmentShape(cx, freshBi, cls, bi.nextEnvironmentSlot(),
     189             :                                             baseShapeFlags));
     190           0 :         if (!envShape)
     191           0 :             return false;
     192             :     }
     193           0 : 
     194             :     return true;
     195           0 : }
     196             : 
     197             : template <typename ConcreteScope>
     198             : static UniquePtr<typename ConcreteScope::Data>
     199             : NewEmptyScopeData(JSContext* cx, uint32_t length = 0)
     200             : {
     201             :     size_t dataSize = SizeOfData<typename ConcreteScope::Data>(length);
     202             :     uint8_t* bytes = cx->zone()->pod_malloc<uint8_t>(dataSize);
     203             :     if (!bytes)
     204           0 :         ReportOutOfMemory(cx);
     205             :     auto data = reinterpret_cast<typename ConcreteScope::Data*>(bytes);
     206           0 :     if (data)
     207           0 :         new (data) typename ConcreteScope::Data(length);
     208           0 :     return UniquePtr<typename ConcreteScope::Data>(data);
     209           0 : }
     210           0 : 
     211           0 : static constexpr size_t HasAtomMask = 1;
     212           0 : static constexpr size_t HasAtomShift = 1;
     213             : 
     214             : static XDRResult
     215             : XDRBindingName(XDRState<XDR_ENCODE>* xdr, BindingName* bindingName)
     216           0 : {
     217             :     JSContext* cx = xdr->cx();
     218           0 : 
     219             :     RootedAtom atom(cx, bindingName->name());
     220           0 :     bool hasAtom = !!atom;
     221           0 : 
     222             :     uint8_t flags = bindingName->flagsForXDR();
     223           0 :     MOZ_ASSERT(((flags << HasAtomShift) >> HasAtomShift) == flags);
     224           0 :     uint8_t u8 = (flags << HasAtomShift) | uint8_t(hasAtom);
     225             :     MOZ_TRY(xdr->codeUint8(&u8));
     226           0 : 
     227           0 :     if (hasAtom)
     228             :         MOZ_TRY(XDRAtom(xdr, &atom));
     229           0 : 
     230             :     return Ok();
     231             : }
     232             : 
     233           0 : static XDRResult
     234             : XDRBindingName(XDRState<XDR_DECODE>* xdr, BindingName* bindingName)
     235           0 : {
     236             :     JSContext* cx = xdr->cx();
     237             : 
     238           0 :     uint8_t u8;
     239             :     MOZ_TRY(xdr->codeUint8(&u8));
     240           0 : 
     241           0 :     bool hasAtom = u8 & HasAtomMask;
     242             :     RootedAtom atom(cx);
     243           0 :     if (hasAtom)
     244           0 :         MOZ_TRY(XDRAtom(xdr, &atom));
     245           0 : 
     246             :     uint8_t flags = u8 >> HasAtomShift;
     247           0 :     *bindingName = BindingName::fromXDR(atom, flags);
     248             : 
     249           0 :     return Ok();
     250             : }
     251             : 
     252             : template <typename ConcreteScopeData>
     253             : static void
     254             : DeleteScopeData(ConcreteScopeData* data)
     255             : {
     256             :     // Some scope Data classes have GCManagedDeletePolicy because then contain
     257             :     // GCPtrs. Dispose of them in the appropriate way.
     258           0 :     JS::DeletePolicy<ConcreteScopeData>()(data);
     259             : }
     260             : 
     261             : template <typename ConcreteScope, XDRMode mode>
     262             : /* static */ XDRResult
     263           0 : Scope::XDRSizedBindingNames(XDRState<mode>* xdr, Handle<ConcreteScope*> scope,
     264             :                             MutableHandle<typename ConcreteScope::Data*> data)
     265             : {
     266           0 :     MOZ_ASSERT(!data);
     267             : 
     268           0 :     JSContext* cx = xdr->cx();
     269             : 
     270             :     uint32_t length;
     271             :     if (mode == XDR_ENCODE)
     272           0 :         length = scope->data().length;
     273           0 :     MOZ_TRY(xdr->codeUint32(&length));
     274             : 
     275             :     if (mode == XDR_ENCODE) {
     276           0 :         data.set(&scope->data());
     277             :     } else {
     278           0 :         data.set(NewEmptyScopeData<ConcreteScope>(cx, length).release());
     279           0 :         if (!data)
     280           0 :             return xdr->fail(JS::TranscodeResult_Throw);
     281           0 :         data->length = length;
     282             :     }
     283             : 
     284             :     auto dataGuard = mozilla::MakeScopeExit([&] () {
     285             :         if (mode == XDR_DECODE) {
     286           0 :             DeleteScopeData(data.get());
     287           0 :             data.set(nullptr);
     288             :         }
     289           0 :     });
     290             : 
     291           0 :     for (uint32_t i = 0; i < length; i++)
     292           0 :         MOZ_TRY(XDRBindingName(xdr, &data->trailingNames[i]));
     293             : 
     294           0 :     dataGuard.release();
     295           0 :     return Ok();
     296             : }
     297             : 
     298             : /* static */ Scope*
     299           0 : Scope::create(JSContext* cx, ScopeKind kind, HandleScope enclosing, HandleShape envShape)
     300             : {
     301           0 :     Scope* scope = Allocate<Scope>(cx);
     302           0 :     if (scope)
     303           0 :         new (scope) Scope(kind, enclosing, envShape);
     304           0 :     return scope;
     305             : }
     306             : 
     307             : template <typename T, typename D>
     308             : /* static */ Scope*
     309           0 : Scope::create(JSContext* cx, ScopeKind kind, HandleScope enclosing,
     310             :               HandleShape envShape, mozilla::UniquePtr<T, D> data)
     311             : {
     312           0 :     Scope* scope = create(cx, kind, enclosing, envShape);
     313           0 :     if (!scope)
     314             :         return nullptr;
     315             : 
     316             :     // It is an invariant that all Scopes that have data (currently, all
     317             :     // ScopeKinds except With) must have non-null data.
     318           0 :     MOZ_ASSERT(data);
     319           0 :     scope->initData(std::move(data));
     320             : 
     321           0 :     return scope;
     322             : }
     323             : 
     324             : uint32_t
     325           0 : Scope::chainLength() const
     326             : {
     327           0 :     uint32_t length = 0;
     328           0 :     for (ScopeIter si(const_cast<Scope*>(this)); si; si++)
     329           0 :         length++;
     330           0 :     return length;
     331             : }
     332             : 
     333             : uint32_t
     334           0 : Scope::environmentChainLength() const
     335             : {
     336           0 :     uint32_t length = 0;
     337           0 :     for (ScopeIter si(const_cast<Scope*>(this)); si; si++) {
     338           0 :         if (si.hasSyntacticEnvironment())
     339           0 :             length++;
     340             :     }
     341           0 :     return length;
     342             : }
     343             : 
     344             : Shape*
     345           0 : Scope::maybeCloneEnvironmentShape(JSContext* cx)
     346             : {
     347             :     // Clone the environment shape if cloning into a different zone.
     348           0 :     if (environmentShape_ && environmentShape_->zoneFromAnyThread() != cx->zone()) {
     349           0 :         BindingIter bi(this);
     350           0 :         return CreateEnvironmentShape(cx, bi,
     351           0 :                                       environmentShape_->getObjectClass(),
     352           0 :                                       environmentShape_->slotSpan(),
     353           0 :                                       environmentShape_->getObjectFlags());
     354             :     }
     355           0 :     return environmentShape_;
     356             : }
     357             : 
     358             : /* static */ Scope*
     359           0 : Scope::clone(JSContext* cx, HandleScope scope, HandleScope enclosing)
     360             : {
     361           0 :     RootedShape envShape(cx);
     362           0 :     if (scope->environmentShape()) {
     363           0 :         envShape = scope->maybeCloneEnvironmentShape(cx);
     364           0 :         if (!envShape)
     365             :             return nullptr;
     366             :     }
     367             : 
     368           0 :     switch (scope->kind_) {
     369             :       case ScopeKind::Function: {
     370           0 :         RootedScript script(cx, scope->as<FunctionScope>().script());
     371           0 :         const char* filename = script->filename();
     372             :         // If the script has an internal URL, include it in the crash reason. If
     373             :         // not, it may be a web URL, and therefore privacy-sensitive.
     374           0 :         if (!strncmp(filename, "chrome:", 7) || !strncmp(filename, "resource:", 9))
     375           0 :             MOZ_CRASH_UNSAFE_PRINTF("Use FunctionScope::clone (script URL: %s)", filename);
     376             : 
     377           0 :         MOZ_CRASH("Use FunctionScope::clone.");
     378             :         break;
     379             :       }
     380             : 
     381             :       case ScopeKind::FunctionBodyVar:
     382             :       case ScopeKind::ParameterExpressionVar: {
     383           0 :         Rooted<VarScope::Data*> original(cx, &scope->as<VarScope>().data());
     384           0 :         UniquePtr<VarScope::Data> dataClone = CopyScopeData<VarScope>(cx, original);
     385           0 :         if (!dataClone)
     386             :             return nullptr;
     387           0 :         return create(cx, scope->kind_, enclosing, envShape, std::move(dataClone));
     388             :       }
     389             : 
     390             :       case ScopeKind::Lexical:
     391             :       case ScopeKind::SimpleCatch:
     392             :       case ScopeKind::Catch:
     393             :       case ScopeKind::NamedLambda:
     394             :       case ScopeKind::StrictNamedLambda: {
     395           0 :         Rooted<LexicalScope::Data*> original(cx, &scope->as<LexicalScope>().data());
     396           0 :         UniquePtr<LexicalScope::Data> dataClone = CopyScopeData<LexicalScope>(cx, original);
     397           0 :         if (!dataClone)
     398             :             return nullptr;
     399           0 :         return create(cx, scope->kind_, enclosing, envShape, std::move(dataClone));
     400             :       }
     401             : 
     402             :       case ScopeKind::With:
     403           0 :         return create(cx, scope->kind_, enclosing, envShape);
     404             : 
     405             :       case ScopeKind::Eval:
     406             :       case ScopeKind::StrictEval: {
     407           0 :         Rooted<EvalScope::Data*> original(cx, &scope->as<EvalScope>().data());
     408           0 :         UniquePtr<EvalScope::Data> dataClone = CopyScopeData<EvalScope>(cx, original);
     409           0 :         if (!dataClone)
     410             :             return nullptr;
     411           0 :         return create(cx, scope->kind_, enclosing, envShape, std::move(dataClone));
     412             :       }
     413             : 
     414             :       case ScopeKind::Global:
     415             :       case ScopeKind::NonSyntactic:
     416           0 :         MOZ_CRASH("Use GlobalScope::clone.");
     417             :         break;
     418             : 
     419             :       case ScopeKind::WasmFunction:
     420           0 :         MOZ_CRASH("wasm functions are not nested in JSScript");
     421             :         break;
     422             : 
     423             :       case ScopeKind::Module:
     424             :       case ScopeKind::WasmInstance:
     425           0 :         MOZ_CRASH("NYI");
     426             :         break;
     427             : 
     428             :     }
     429             : 
     430             :     return nullptr;
     431             : }
     432             : 
     433             : void
     434           0 : Scope::finalize(FreeOp* fop)
     435             : {
     436           0 :     MOZ_ASSERT(CurrentThreadIsGCSweeping());
     437           0 :     if (data_) {
     438             :         // We don't need to call the destructors for any GCPtrs in Data because
     439             :         // this only happens during a GC.
     440           0 :         fop->free_(reinterpret_cast<void*>(data_));
     441           0 :         data_ = 0;
     442             :     }
     443           0 : }
     444             : 
     445             : size_t
     446           0 : Scope::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
     447             : {
     448           0 :     if (data_)
     449           0 :         return mallocSizeOf(reinterpret_cast<void*>(data_));
     450             :     return 0;
     451             : }
     452             : 
     453             : void
     454           0 : Scope::dump()
     455             : {
     456           0 :     for (ScopeIter si(this); si; si++) {
     457           0 :         fprintf(stderr, "%s [%p]", ScopeKindString(si.kind()), si.scope());
     458           0 :         if (si.scope()->enclosing())
     459           0 :             fprintf(stderr, " -> ");
     460             :     }
     461           0 :     fprintf(stderr, "\n");
     462           0 : }
     463             : 
     464             : uint32_t
     465           0 : LexicalScope::firstFrameSlot() const
     466             : {
     467           0 :     switch (kind()) {
     468             :       case ScopeKind::Lexical:
     469             :       case ScopeKind::SimpleCatch:
     470             :       case ScopeKind::Catch:
     471             :         // For intra-frame scopes, find the enclosing scope's next frame slot.
     472           0 :         return nextFrameSlot(enclosing());
     473             :       case ScopeKind::NamedLambda:
     474             :       case ScopeKind::StrictNamedLambda:
     475             :         // Named lambda scopes cannot have frame slots.
     476             :         return LOCALNO_LIMIT;
     477             :       default:
     478             :         // Otherwise start at 0.
     479             :         break;
     480             :     }
     481           0 :     return 0;
     482             : }
     483             : 
     484             : /* static */ uint32_t
     485           0 : LexicalScope::nextFrameSlot(Scope* scope)
     486             : {
     487           0 :     for (ScopeIter si(scope); si; si++) {
     488           0 :         switch (si.kind()) {
     489             :           case ScopeKind::Function:
     490           0 :             return si.scope()->as<FunctionScope>().nextFrameSlot();
     491             :           case ScopeKind::FunctionBodyVar:
     492             :           case ScopeKind::ParameterExpressionVar:
     493           0 :             return si.scope()->as<VarScope>().nextFrameSlot();
     494             :           case ScopeKind::Lexical:
     495             :           case ScopeKind::SimpleCatch:
     496             :           case ScopeKind::Catch:
     497           0 :             return si.scope()->as<LexicalScope>().nextFrameSlot();
     498             :           case ScopeKind::NamedLambda:
     499             :           case ScopeKind::StrictNamedLambda:
     500             :             // Named lambda scopes cannot have frame slots.
     501             :             return 0;
     502             :           case ScopeKind::With:
     503             :             continue;
     504             :           case ScopeKind::Eval:
     505             :           case ScopeKind::StrictEval:
     506           0 :             return si.scope()->as<EvalScope>().nextFrameSlot();
     507             :           case ScopeKind::Global:
     508             :           case ScopeKind::NonSyntactic:
     509             :             return 0;
     510             :           case ScopeKind::Module:
     511           0 :             return si.scope()->as<ModuleScope>().nextFrameSlot();
     512             :           case ScopeKind::WasmInstance:
     513             :             // TODO return si.scope()->as<WasmInstanceScope>().nextFrameSlot();
     514             :             return 0;
     515             :           case ScopeKind::WasmFunction:
     516             :             // TODO return si.scope()->as<WasmFunctionScope>().nextFrameSlot();
     517             :             return 0;
     518             :         }
     519             :     }
     520           0 :     MOZ_CRASH("Not an enclosing intra-frame Scope");
     521             : }
     522             : 
     523             : /* static */ LexicalScope*
     524           0 : LexicalScope::create(JSContext* cx, ScopeKind kind, Handle<Data*> data,
     525             :                      uint32_t firstFrameSlot, HandleScope enclosing)
     526             : {
     527           0 :     MOZ_ASSERT(data, "LexicalScopes should not be created if there are no bindings.");
     528             : 
     529             :     // The data that's passed in is from the frontend and is LifoAlloc'd.
     530             :     // Copy it now that we're creating a permanent VM scope.
     531           0 :     Rooted<UniquePtr<Data>> copy(cx, CopyScopeData<LexicalScope>(cx, data));
     532           0 :     if (!copy)
     533             :         return nullptr;
     534             : 
     535           0 :     return createWithData(cx, kind, &copy, firstFrameSlot, enclosing);
     536             : }
     537             : 
     538             : /* static */ LexicalScope*
     539           0 : LexicalScope::createWithData(JSContext* cx, ScopeKind kind, MutableHandle<UniquePtr<Data>> data,
     540             :                              uint32_t firstFrameSlot, HandleScope enclosing)
     541             : {
     542           0 :     bool isNamedLambda = kind == ScopeKind::NamedLambda || kind == ScopeKind::StrictNamedLambda;
     543             : 
     544           0 :     MOZ_ASSERT_IF(!isNamedLambda && firstFrameSlot != 0,
     545             :                   firstFrameSlot == nextFrameSlot(enclosing));
     546           0 :     MOZ_ASSERT_IF(isNamedLambda, firstFrameSlot == LOCALNO_LIMIT);
     547             : 
     548           0 :     RootedShape envShape(cx);
     549           0 :     BindingIter bi(*data, firstFrameSlot, isNamedLambda);
     550           0 :     if (!PrepareScopeData<LexicalScope>(cx, bi, data, &LexicalEnvironmentObject::class_,
     551             :                                         BaseShape::NOT_EXTENSIBLE | BaseShape::DELEGATE, &envShape))
     552             :     {
     553             :         return nullptr;
     554             :     }
     555             : 
     556           0 :     Scope* scope = Scope::create(cx, kind, enclosing, envShape, std::move(data.get()));
     557           0 :     if (!scope)
     558             :         return nullptr;
     559           0 :     MOZ_ASSERT(scope->as<LexicalScope>().firstFrameSlot() == firstFrameSlot);
     560           0 :     return &scope->as<LexicalScope>();
     561             : }
     562             : 
     563             : /* static */ Shape*
     564           0 : LexicalScope::getEmptyExtensibleEnvironmentShape(JSContext* cx)
     565             : {
     566           0 :     const Class* cls = &LexicalEnvironmentObject::class_;
     567           0 :     return EmptyEnvironmentShape(cx, cls, JSSLOT_FREE(cls), BaseShape::DELEGATE);
     568             : }
     569             : 
     570             : template <XDRMode mode>
     571             : /* static */ XDRResult
     572           0 : LexicalScope::XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
     573             :                   MutableHandleScope scope)
     574             : {
     575           0 :     JSContext* cx = xdr->cx();
     576             : 
     577           0 :     Rooted<Data*> data(cx);
     578           0 :     MOZ_TRY(XDRSizedBindingNames<LexicalScope>(xdr, scope.as<LexicalScope>(), &data));
     579             : 
     580             :     {
     581           0 :         Maybe<Rooted<UniquePtr<Data>>> uniqueData;
     582             :         if (mode == XDR_DECODE)
     583           0 :             uniqueData.emplace(cx, data);
     584             : 
     585             :         uint32_t firstFrameSlot;
     586             :         uint32_t nextFrameSlot;
     587             :         if (mode == XDR_ENCODE) {
     588           0 :             firstFrameSlot = scope->as<LexicalScope>().firstFrameSlot();
     589           0 :             nextFrameSlot = data->nextFrameSlot;
     590             :         }
     591             : 
     592           0 :         MOZ_TRY(xdr->codeUint32(&data->constStart));
     593           0 :         MOZ_TRY(xdr->codeUint32(&firstFrameSlot));
     594           0 :         MOZ_TRY(xdr->codeUint32(&nextFrameSlot));
     595             : 
     596             :         if (mode == XDR_DECODE) {
     597           0 :             scope.set(createWithData(cx, kind, &uniqueData.ref(), firstFrameSlot, enclosing));
     598           0 :             if (!scope)
     599           0 :                 return xdr->fail(JS::TranscodeResult_Throw);
     600             : 
     601             :             // nextFrameSlot is used only for this correctness check.
     602           0 :             MOZ_ASSERT(nextFrameSlot == scope->as<LexicalScope>().data().nextFrameSlot);
     603             :         }
     604             :     }
     605             : 
     606           0 :     return Ok();
     607             : }
     608             : 
     609             : template
     610             : /* static */ XDRResult
     611             : LexicalScope::XDR(XDRState<XDR_ENCODE>* xdr, ScopeKind kind, HandleScope enclosing,
     612             :                   MutableHandleScope scope);
     613             : 
     614             : template
     615             : /* static */ XDRResult
     616             : LexicalScope::XDR(XDRState<XDR_DECODE>* xdr, ScopeKind kind, HandleScope enclosing,
     617             :                   MutableHandleScope scope);
     618             : 
     619             : static inline uint32_t
     620             : FunctionScopeEnvShapeFlags(bool hasParameterExprs)
     621             : {
     622           0 :     if (hasParameterExprs)
     623             :         return BaseShape::DELEGATE;
     624             :     return BaseShape::QUALIFIED_VAROBJ | BaseShape::DELEGATE;
     625             : }
     626             : 
     627             : Zone*
     628           0 : FunctionScope::Data::zone() const
     629             : {
     630           0 :     return canonicalFunction ? canonicalFunction->zone() : nullptr;
     631             : }
     632             : 
     633             : /* static */ FunctionScope*
     634           0 : FunctionScope::create(JSContext* cx, Handle<Data*> dataArg,
     635             :                       bool hasParameterExprs, bool needsEnvironment,
     636             :                       HandleFunction fun, HandleScope enclosing)
     637             : {
     638             :     // The data that's passed in is from the frontend and is LifoAlloc'd.
     639             :     // Copy it now that we're creating a permanent VM scope.
     640           0 :     Rooted<UniquePtr<Data>> data(cx, dataArg ? CopyScopeData<FunctionScope>(cx, dataArg)
     641           0 :                                              : NewEmptyScopeData<FunctionScope>(cx));
     642           0 :     if (!data)
     643             :         return nullptr;
     644             : 
     645           0 :     return createWithData(cx, &data, hasParameterExprs, needsEnvironment, fun, enclosing);
     646             : }
     647             : 
     648             : /* static */ FunctionScope*
     649           0 : FunctionScope::createWithData(JSContext* cx, MutableHandle<UniquePtr<Data>> data,
     650             :                               bool hasParameterExprs, bool needsEnvironment,
     651             :                               HandleFunction fun, HandleScope enclosing)
     652             : {
     653           0 :     MOZ_ASSERT(data);
     654           0 :     MOZ_ASSERT(fun->isTenured());
     655             : 
     656             :     // FunctionScope::Data has GCManagedDeletePolicy because it contains a
     657             :     // GCPtr. Destruction of |data| below may trigger calls into the GC.
     658           0 :     Rooted<FunctionScope*> funScope(cx);
     659             : 
     660             :     {
     661           0 :         RootedShape envShape(cx);
     662             : 
     663           0 :         BindingIter bi(*data, hasParameterExprs);
     664           0 :         uint32_t shapeFlags = FunctionScopeEnvShapeFlags(hasParameterExprs);
     665           0 :         if (!PrepareScopeData<FunctionScope>(cx, bi, data, &CallObject::class_, shapeFlags,
     666             :                                              &envShape))
     667             :         {
     668           0 :             return nullptr;
     669             :         }
     670             : 
     671           0 :         data->hasParameterExprs = hasParameterExprs;
     672           0 :         data->canonicalFunction.init(fun);
     673             : 
     674             :         // An environment may be needed regardless of existence of any closed over
     675             :         // bindings:
     676             :         //   - Extensible scopes (i.e., due to direct eval)
     677             :         //   - Needing a home object
     678             :         //   - Being a derived class constructor
     679             :         //   - Being a generator
     680           0 :         if (!envShape && needsEnvironment) {
     681           0 :             envShape = getEmptyEnvironmentShape(cx, hasParameterExprs);
     682           0 :             if (!envShape)
     683             :                 return nullptr;
     684             :         }
     685             : 
     686           0 :         Scope* scope = Scope::create(cx, ScopeKind::Function, enclosing, envShape);
     687           0 :         if (!scope)
     688             :             return nullptr;
     689             : 
     690           0 :         funScope = &scope->as<FunctionScope>();
     691           0 :         funScope->initData(std::move(data.get()));
     692             :     }
     693             : 
     694           0 :     return funScope;
     695             : }
     696             : 
     697             : JSScript*
     698           0 : FunctionScope::script() const
     699             : {
     700           0 :     return canonicalFunction()->nonLazyScript();
     701             : }
     702             : 
     703             : /* static */ bool
     704           0 : FunctionScope::isSpecialName(JSContext* cx, JSAtom* name)
     705             : {
     706           0 :     return name == cx->names().arguments ||
     707           0 :            name == cx->names().dotThis ||
     708           0 :            name == cx->names().dotGenerator;
     709             : }
     710             : 
     711             : /* static */ Shape*
     712           0 : FunctionScope::getEmptyEnvironmentShape(JSContext* cx, bool hasParameterExprs)
     713             : {
     714           0 :     const Class* cls = &CallObject::class_;
     715           0 :     uint32_t shapeFlags = FunctionScopeEnvShapeFlags(hasParameterExprs);
     716           0 :     return EmptyEnvironmentShape(cx, cls, JSSLOT_FREE(cls), shapeFlags);
     717             : }
     718             : 
     719             : /* static */ FunctionScope*
     720           0 : FunctionScope::clone(JSContext* cx, Handle<FunctionScope*> scope, HandleFunction fun,
     721             :                      HandleScope enclosing)
     722             : {
     723           0 :     MOZ_ASSERT(fun != scope->canonicalFunction());
     724             : 
     725             :     // FunctionScope::Data has GCManagedDeletePolicy because it contains a
     726             :     // GCPtr. Destruction of |dataClone| below may trigger calls into the GC.
     727           0 :     Rooted<FunctionScope*> funScopeClone(cx);
     728             : 
     729             :     {
     730           0 :         RootedShape envShape(cx);
     731           0 :         if (scope->environmentShape()) {
     732           0 :             envShape = scope->maybeCloneEnvironmentShape(cx);
     733           0 :             if (!envShape)
     734           0 :                 return nullptr;
     735             :         }
     736             : 
     737           0 :         Rooted<Data*> dataOriginal(cx, &scope->as<FunctionScope>().data());
     738           0 :         Rooted<UniquePtr<Data>> dataClone(cx, CopyScopeData<FunctionScope>(cx, dataOriginal));
     739           0 :         if (!dataClone)
     740           0 :             return nullptr;
     741             : 
     742           0 :         dataClone->canonicalFunction.init(fun);
     743             : 
     744           0 :         Scope* scopeClone = Scope::create(cx, scope->kind(), enclosing, envShape);
     745           0 :         if (!scopeClone)
     746             :             return nullptr;
     747             : 
     748           0 :         funScopeClone = &scopeClone->as<FunctionScope>();
     749           0 :         funScopeClone->initData(std::move(dataClone.get()));
     750             :     }
     751             : 
     752           0 :     return funScopeClone;
     753             : }
     754             : 
     755             : template <XDRMode mode>
     756             : /* static */ XDRResult
     757           0 : FunctionScope::XDR(XDRState<mode>* xdr, HandleFunction fun, HandleScope enclosing,
     758             :                    MutableHandleScope scope)
     759             : {
     760           0 :     JSContext* cx = xdr->cx();
     761           0 :     Rooted<Data*> data(cx);
     762           0 :     MOZ_TRY(XDRSizedBindingNames<FunctionScope>(xdr, scope.as<FunctionScope>(), &data));
     763             : 
     764             :     {
     765           0 :         Maybe<Rooted<UniquePtr<Data>>> uniqueData;
     766             :         if (mode == XDR_DECODE)
     767           0 :             uniqueData.emplace(cx, data);
     768             : 
     769             :         uint8_t needsEnvironment;
     770             :         uint8_t hasParameterExprs;
     771             :         uint32_t nextFrameSlot;
     772             :         if (mode == XDR_ENCODE) {
     773           0 :             needsEnvironment = scope->hasEnvironment();
     774           0 :             hasParameterExprs = data->hasParameterExprs;
     775           0 :             nextFrameSlot = data->nextFrameSlot;
     776             :         }
     777           0 :         MOZ_TRY(xdr->codeUint8(&needsEnvironment));
     778           0 :         MOZ_TRY(xdr->codeUint8(&hasParameterExprs));
     779           0 :         MOZ_TRY(xdr->codeUint16(&data->nonPositionalFormalStart));
     780           0 :         MOZ_TRY(xdr->codeUint16(&data->varStart));
     781           0 :         MOZ_TRY(xdr->codeUint32(&nextFrameSlot));
     782             : 
     783             :         if (mode == XDR_DECODE) {
     784           0 :             if (!data->length) {
     785           0 :                 MOZ_ASSERT(!data->nonPositionalFormalStart);
     786           0 :                 MOZ_ASSERT(!data->varStart);
     787           0 :                 MOZ_ASSERT(!data->nextFrameSlot);
     788             :             }
     789             : 
     790           0 :             scope.set(createWithData(cx, &uniqueData.ref(), hasParameterExprs, needsEnvironment, fun,
     791             :                                      enclosing));
     792           0 :             if (!scope)
     793           0 :                 return xdr->fail(JS::TranscodeResult_Throw);
     794             : 
     795             :             // nextFrameSlot is used only for this correctness check.
     796           0 :             MOZ_ASSERT(nextFrameSlot == scope->as<FunctionScope>().data().nextFrameSlot);
     797             :         }
     798             :     }
     799             : 
     800           0 :     return Ok();
     801             : }
     802             : 
     803             : template
     804             : /* static */ XDRResult
     805             : FunctionScope::XDR(XDRState<XDR_ENCODE>* xdr, HandleFunction fun, HandleScope enclosing,
     806             :                    MutableHandleScope scope);
     807             : 
     808             : template
     809             : /* static */ XDRResult
     810             : FunctionScope::XDR(XDRState<XDR_DECODE>* xdr, HandleFunction fun, HandleScope enclosing,
     811             :                    MutableHandleScope scope);
     812             : 
     813             : static const uint32_t VarScopeEnvShapeFlags =
     814             :     BaseShape::QUALIFIED_VAROBJ | BaseShape::DELEGATE;
     815             : 
     816             : static UniquePtr<VarScope::Data>
     817           0 : NewEmptyVarScopeData(JSContext* cx, uint32_t firstFrameSlot)
     818             : {
     819           0 :     UniquePtr<VarScope::Data> data(NewEmptyScopeData<VarScope>(cx));
     820           0 :     if (data)
     821           0 :         data->nextFrameSlot = firstFrameSlot;
     822             : 
     823           0 :     return data;
     824             : }
     825             : 
     826             : /* static */ VarScope*
     827           0 : VarScope::create(JSContext* cx, ScopeKind kind, Handle<Data*> dataArg,
     828             :                  uint32_t firstFrameSlot, bool needsEnvironment, HandleScope enclosing)
     829             : {
     830             :     // The data that's passed in is from the frontend and is LifoAlloc'd.
     831             :     // Copy it now that we're creating a permanent VM scope.
     832           0 :     Rooted<UniquePtr<Data>> data(cx, dataArg ? CopyScopeData<VarScope>(cx, dataArg)
     833           0 :                                              : NewEmptyVarScopeData(cx, firstFrameSlot));
     834           0 :     if (!data)
     835             :         return nullptr;
     836             : 
     837           0 :     return createWithData(cx, kind, &data, firstFrameSlot, needsEnvironment, enclosing);
     838             : }
     839             : 
     840             : /* static */ VarScope*
     841           0 : VarScope::createWithData(JSContext* cx, ScopeKind kind, MutableHandle<UniquePtr<Data>> data,
     842             :                          uint32_t firstFrameSlot, bool needsEnvironment, HandleScope enclosing)
     843             : {
     844           0 :     MOZ_ASSERT(data);
     845             : 
     846           0 :     RootedShape envShape(cx);
     847           0 :     BindingIter bi(*data, firstFrameSlot);
     848           0 :     if (!PrepareScopeData<VarScope>(cx, bi, data, &VarEnvironmentObject::class_, VarScopeEnvShapeFlags,
     849             :                                     &envShape))
     850             :     {
     851             :         return nullptr;
     852             :     }
     853             : 
     854             :     // An environment may be needed regardless of existence of any closed over
     855             :     // bindings:
     856             :     //   - Extensible scopes (i.e., due to direct eval)
     857             :     //   - Being a generator
     858           0 :     if (!envShape && needsEnvironment) {
     859           0 :         envShape = getEmptyEnvironmentShape(cx);
     860           0 :         if (!envShape)
     861             :             return nullptr;
     862             :     }
     863             : 
     864           0 :     Scope* scope = Scope::create(cx, kind, enclosing, envShape, std::move(data.get()));
     865           0 :     if (!scope)
     866             :         return nullptr;
     867           0 :     return &scope->as<VarScope>();
     868             : }
     869             : 
     870             : /* static */ Shape*
     871           0 : VarScope::getEmptyEnvironmentShape(JSContext* cx)
     872             : {
     873           0 :     const Class* cls = &VarEnvironmentObject::class_;
     874           0 :     return EmptyEnvironmentShape(cx, cls, JSSLOT_FREE(cls), VarScopeEnvShapeFlags);
     875             : }
     876             : 
     877             : uint32_t
     878           0 : VarScope::firstFrameSlot() const
     879             : {
     880           0 :     if (enclosing()->is<FunctionScope>())
     881           0 :         return enclosing()->as<FunctionScope>().nextFrameSlot();
     882             :     return 0;
     883             : }
     884             : 
     885             : template <XDRMode mode>
     886             : /* static */ XDRResult
     887           0 : VarScope::XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
     888             :               MutableHandleScope scope)
     889             : {
     890           0 :     JSContext* cx = xdr->cx();
     891           0 :     Rooted<Data*> data(cx);
     892           0 :     MOZ_TRY(XDRSizedBindingNames<VarScope>(xdr, scope.as<VarScope>(), &data));
     893             : 
     894             :     {
     895           0 :         Maybe<Rooted<UniquePtr<Data>>> uniqueData;
     896             :         if (mode == XDR_DECODE)
     897           0 :             uniqueData.emplace(cx, data);
     898             : 
     899             :         uint8_t needsEnvironment;
     900             :         uint32_t firstFrameSlot;
     901             :         uint32_t nextFrameSlot;
     902             :         if (mode == XDR_ENCODE) {
     903           0 :             needsEnvironment = scope->hasEnvironment();
     904           0 :             firstFrameSlot = scope->as<VarScope>().firstFrameSlot();
     905           0 :             nextFrameSlot = data->nextFrameSlot;
     906             :         }
     907           0 :         MOZ_TRY(xdr->codeUint8(&needsEnvironment));
     908           0 :         MOZ_TRY(xdr->codeUint32(&firstFrameSlot));
     909           0 :         MOZ_TRY(xdr->codeUint32(&nextFrameSlot));
     910             : 
     911             :         if (mode == XDR_DECODE) {
     912           0 :             if (!data->length) {
     913           0 :                 MOZ_ASSERT(!data->nextFrameSlot);
     914             :             }
     915             : 
     916           0 :             scope.set(createWithData(cx, kind, &uniqueData.ref(), firstFrameSlot, needsEnvironment,
     917             :                                      enclosing));
     918           0 :             if (!scope)
     919           0 :                 return xdr->fail(JS::TranscodeResult_Throw);
     920             : 
     921             :             // nextFrameSlot is used only for this correctness check.
     922           0 :             MOZ_ASSERT(nextFrameSlot == scope->as<VarScope>().data().nextFrameSlot);
     923             :         }
     924             :     }
     925             : 
     926           0 :     return Ok();
     927             : }
     928             : 
     929             : template
     930             : /* static */ XDRResult
     931             : VarScope::XDR(XDRState<XDR_ENCODE>* xdr, ScopeKind kind, HandleScope enclosing,
     932             :               MutableHandleScope scope);
     933             : 
     934             : template
     935             : /* static */ XDRResult
     936             : VarScope::XDR(XDRState<XDR_DECODE>* xdr, ScopeKind kind, HandleScope enclosing,
     937             :               MutableHandleScope scope);
     938             : 
     939             : /* static */ GlobalScope*
     940           0 : GlobalScope::create(JSContext* cx, ScopeKind kind, Handle<Data*> dataArg)
     941             : {
     942             :     // The data that's passed in is from the frontend and is LifoAlloc'd.
     943             :     // Copy it now that we're creating a permanent VM scope.
     944           0 :     Rooted<UniquePtr<Data>> data(cx, dataArg ? CopyScopeData<GlobalScope>(cx, dataArg)
     945           0 :                                              : NewEmptyScopeData<GlobalScope>(cx));
     946           0 :     if (!data)
     947             :         return nullptr;
     948             : 
     949           0 :     return createWithData(cx, kind, &data);
     950             : }
     951             : 
     952             : /* static */ GlobalScope*
     953           0 : GlobalScope::createWithData(JSContext* cx, ScopeKind kind, MutableHandle<UniquePtr<Data>> data)
     954             : {
     955           0 :     MOZ_ASSERT(data);
     956             : 
     957             :     // The global scope has no environment shape. Its environment is the
     958             :     // global lexical scope and the global object or non-syntactic objects
     959             :     // created by embedding, all of which are not only extensible but may
     960             :     // have names on them deleted.
     961           0 :     Scope* scope = Scope::create(cx, kind, nullptr, nullptr, std::move(data.get()));
     962           0 :     if (!scope)
     963             :         return nullptr;
     964           0 :     return &scope->as<GlobalScope>();
     965             : }
     966             : 
     967             : /* static */ GlobalScope*
     968           0 : GlobalScope::clone(JSContext* cx, Handle<GlobalScope*> scope, ScopeKind kind)
     969             : {
     970           0 :     Rooted<Data*> dataOriginal(cx, &scope->as<GlobalScope>().data());
     971           0 :     Rooted<UniquePtr<Data>> dataClone(cx, CopyScopeData<GlobalScope>(cx, dataOriginal));
     972           0 :     if (!dataClone)
     973             :         return nullptr;
     974             : 
     975           0 :     Scope* scopeClone = Scope::create(cx, kind, nullptr, nullptr, std::move(dataClone.get()));
     976           0 :     if (!scopeClone)
     977             :         return nullptr;
     978           0 :     return &scopeClone->as<GlobalScope>();
     979             : }
     980             : 
     981             : template <XDRMode mode>
     982             : /* static */ XDRResult
     983           0 : GlobalScope::XDR(XDRState<mode>* xdr, ScopeKind kind, MutableHandleScope scope)
     984             : {
     985           0 :     MOZ_ASSERT((mode == XDR_DECODE) == !scope);
     986             : 
     987           0 :     JSContext* cx = xdr->cx();
     988           0 :     Rooted<Data*> data(cx);
     989           0 :     MOZ_TRY(XDRSizedBindingNames<GlobalScope>(xdr, scope.as<GlobalScope>(), &data));
     990             : 
     991             :     {
     992           0 :         Maybe<Rooted<UniquePtr<Data>>> uniqueData;
     993             :         if (mode == XDR_DECODE)
     994           0 :             uniqueData.emplace(cx, data);
     995             : 
     996           0 :         MOZ_TRY(xdr->codeUint32(&data->letStart));
     997           0 :         MOZ_TRY(xdr->codeUint32(&data->constStart));
     998             : 
     999             :         if (mode == XDR_DECODE) {
    1000           0 :             if (!data->length) {
    1001           0 :                 MOZ_ASSERT(!data->letStart);
    1002           0 :                 MOZ_ASSERT(!data->constStart);
    1003             :             }
    1004             : 
    1005           0 :             scope.set(createWithData(cx, kind, &uniqueData.ref()));
    1006           0 :             if (!scope)
    1007           0 :                 return xdr->fail(JS::TranscodeResult_Throw);
    1008             :         }
    1009             :     }
    1010             : 
    1011         481 :     return Ok();
    1012             : }
    1013             : 
    1014             : template
    1015             : /* static */ XDRResult
    1016             : GlobalScope::XDR(XDRState<XDR_ENCODE>* xdr, ScopeKind kind, MutableHandleScope scope);
    1017             : 
    1018             : template
    1019             : /* static */ XDRResult
    1020             : GlobalScope::XDR(XDRState<XDR_DECODE>* xdr, ScopeKind kind, MutableHandleScope scope);
    1021             : 
    1022             : /* static */ WithScope*
    1023           0 : WithScope::create(JSContext* cx, HandleScope enclosing)
    1024             : {
    1025           0 :     Scope* scope = Scope::create(cx, ScopeKind::With, enclosing, nullptr);
    1026           0 :     return static_cast<WithScope*>(scope);
    1027             : }
    1028             : 
    1029             : static const uint32_t EvalScopeEnvShapeFlags =
    1030             :     BaseShape::QUALIFIED_VAROBJ | BaseShape::DELEGATE;
    1031             : 
    1032             : /* static */ EvalScope*
    1033          20 : EvalScope::create(JSContext* cx, ScopeKind scopeKind, Handle<Data*> dataArg,
    1034             :                   HandleScope enclosing)
    1035             : {
    1036             :     // The data that's passed in is from the frontend and is LifoAlloc'd.
    1037             :     // Copy it now that we're creating a permanent VM scope.
    1038          40 :     Rooted<UniquePtr<Data>> data(cx, dataArg ? CopyScopeData<EvalScope>(cx, dataArg)
    1039          80 :                                              : NewEmptyScopeData<EvalScope>(cx));
    1040           0 :     if (!data)
    1041             :         return nullptr;
    1042             : 
    1043          20 :     return createWithData(cx, scopeKind, &data, enclosing);
    1044             : }
    1045             : 
    1046             : /* static */ EvalScope*
    1047          20 : EvalScope::createWithData(JSContext* cx, ScopeKind scopeKind, MutableHandle<UniquePtr<Data>> data,
    1048             :                           HandleScope enclosing)
    1049             : {
    1050          20 :     MOZ_ASSERT(data);
    1051             : 
    1052           0 :     RootedShape envShape(cx);
    1053          20 :     if (scopeKind == ScopeKind::StrictEval) {
    1054           0 :         BindingIter bi(*data, true);
    1055           0 :         if (!PrepareScopeData<EvalScope>(cx, bi, data, &VarEnvironmentObject::class_,
    1056             :                                          EvalScopeEnvShapeFlags, &envShape))
    1057             :         {
    1058           0 :             return nullptr;
    1059             :         }
    1060             :     }
    1061             : 
    1062             :     // Strict eval and direct eval in parameter expressions always get their own
    1063             :     // var environment even if there are no bindings.
    1064          20 :     if (!envShape && scopeKind == ScopeKind::StrictEval) {
    1065           6 :         envShape = getEmptyEnvironmentShape(cx);
    1066           0 :         if (!envShape)
    1067             :             return nullptr;
    1068             :     }
    1069             : 
    1070          80 :     Scope* scope = Scope::create(cx, scopeKind, enclosing, envShape, std::move(data.get()));
    1071          20 :     if (!scope)
    1072             :         return nullptr;
    1073           0 :     return &scope->as<EvalScope>();
    1074             : }
    1075             : 
    1076             : /* static */ Scope*
    1077           0 : EvalScope::nearestVarScopeForDirectEval(Scope* scope)
    1078             : {
    1079           0 :     for (ScopeIter si(scope); si; si++) {
    1080           0 :         switch (si.kind()) {
    1081             :           case ScopeKind::Function:
    1082             :           case ScopeKind::FunctionBodyVar:
    1083             :           case ScopeKind::ParameterExpressionVar:
    1084             :           case ScopeKind::Global:
    1085             :           case ScopeKind::NonSyntactic:
    1086           0 :             return scope;
    1087             :           default:
    1088             :             break;
    1089             :         }
    1090             :     }
    1091           0 :     return nullptr;
    1092             : }
    1093             : 
    1094             : /* static */ Shape*
    1095           3 : EvalScope::getEmptyEnvironmentShape(JSContext* cx)
    1096             : {
    1097           0 :     const Class* cls = &VarEnvironmentObject::class_;
    1098           3 :     return EmptyEnvironmentShape(cx, cls, JSSLOT_FREE(cls), EvalScopeEnvShapeFlags);
    1099             : }
    1100             : 
    1101             : template <XDRMode mode>
    1102             : /* static */ XDRResult
    1103           0 : EvalScope::XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
    1104             :                MutableHandleScope scope)
    1105             : {
    1106           0 :     JSContext* cx = xdr->cx();
    1107           0 :     Rooted<Data*> data(cx);
    1108             : 
    1109             :     {
    1110           0 :         Maybe<Rooted<UniquePtr<Data>>> uniqueData;
    1111             :         if (mode == XDR_DECODE)
    1112           0 :             uniqueData.emplace(cx, data);
    1113             : 
    1114           0 :         MOZ_TRY(XDRSizedBindingNames<EvalScope>(xdr, scope.as<EvalScope>(), &data));
    1115             : 
    1116             :         if (mode == XDR_DECODE) {
    1117           0 :             if (!data->length)
    1118           0 :                 MOZ_ASSERT(!data->nextFrameSlot);
    1119             : 
    1120           0 :             scope.set(createWithData(cx, kind, &uniqueData.ref(), enclosing));
    1121           0 :             if (!scope)
    1122           0 :                 return xdr->fail(JS::TranscodeResult_Throw);
    1123             :         }
    1124             :     }
    1125             : 
    1126           0 :     return Ok();
    1127             : }
    1128             : 
    1129             : template
    1130             : /* static */ XDRResult
    1131             : EvalScope::XDR(XDRState<XDR_ENCODE>* xdr, ScopeKind kind, HandleScope enclosing,
    1132             :                MutableHandleScope scope);
    1133             : 
    1134             : template
    1135             : /* static */ XDRResult
    1136             : EvalScope::XDR(XDRState<XDR_DECODE>* xdr, ScopeKind kind, HandleScope enclosing,
    1137             :                MutableHandleScope scope);
    1138             : 
    1139             : static const uint32_t ModuleScopeEnvShapeFlags =
    1140             :     BaseShape::NOT_EXTENSIBLE | BaseShape::QUALIFIED_VAROBJ | BaseShape::DELEGATE;
    1141             : 
    1142             : Zone*
    1143           0 : ModuleScope::Data::zone() const
    1144             : {
    1145           0 :     return module ? module->zone() : nullptr;
    1146             : }
    1147             : 
    1148             : /* static */ ModuleScope*
    1149           0 : ModuleScope::create(JSContext* cx, Handle<Data*> dataArg,
    1150             :                     HandleModuleObject module, HandleScope enclosing)
    1151             : {
    1152           0 :     Rooted<UniquePtr<Data>> data(cx, dataArg ? CopyScopeData<ModuleScope>(cx, dataArg)
    1153           0 :                                              : NewEmptyScopeData<ModuleScope>(cx));
    1154           0 :     if (!data)
    1155             :         return nullptr;
    1156             : 
    1157           0 :     return createWithData(cx, &data, module, enclosing);
    1158             : }
    1159             : 
    1160             : /* static */ ModuleScope*
    1161           0 : ModuleScope::createWithData(JSContext* cx, MutableHandle<UniquePtr<Data>> data,
    1162             :                             HandleModuleObject module, HandleScope enclosing)
    1163             : {
    1164           0 :     MOZ_ASSERT(data);
    1165           0 :     MOZ_ASSERT(enclosing->is<GlobalScope>());
    1166             : 
    1167             :     // ModuleScope::Data has GCManagedDeletePolicy because it contains a
    1168             :     // GCPtr. Destruction of |copy| below may trigger calls into the GC.
    1169           0 :     Rooted<ModuleScope*> moduleScope(cx);
    1170             : 
    1171             :     {
    1172             :         // The data that's passed in is from the frontend and is LifoAlloc'd.
    1173             :         // Copy it now that we're creating a permanent VM scope.
    1174           0 :         RootedShape envShape(cx);
    1175           0 :         BindingIter bi(*data);
    1176           0 :         if (!PrepareScopeData<ModuleScope>(cx, bi, data, &ModuleEnvironmentObject::class_,
    1177             :                                            ModuleScopeEnvShapeFlags, &envShape))
    1178             :         {
    1179           0 :             return nullptr;
    1180             :         }
    1181             : 
    1182             :         // Modules always need an environment object for now.
    1183           0 :         if (!envShape) {
    1184           0 :             envShape = getEmptyEnvironmentShape(cx);
    1185           0 :             if (!envShape)
    1186             :                 return nullptr;
    1187             :         }
    1188             : 
    1189           0 :         Scope* scope = Scope::create(cx, ScopeKind::Module, enclosing, envShape);
    1190           0 :         if (!scope)
    1191             :             return nullptr;
    1192             : 
    1193           0 :         data->module.init(module);
    1194             : 
    1195           0 :         moduleScope = &scope->as<ModuleScope>();
    1196           0 :         moduleScope->initData(std::move(data.get()));
    1197             :     }
    1198             : 
    1199           0 :     return moduleScope;
    1200             : }
    1201             : 
    1202             : /* static */ Shape*
    1203           0 : ModuleScope::getEmptyEnvironmentShape(JSContext* cx)
    1204             : {
    1205           0 :     const Class* cls = &ModuleEnvironmentObject::class_;
    1206           0 :     return EmptyEnvironmentShape(cx, cls, JSSLOT_FREE(cls), ModuleScopeEnvShapeFlags);
    1207             : }
    1208             : 
    1209             : JSScript*
    1210           0 : ModuleScope::script() const
    1211             : {
    1212           0 :     return module()->script();
    1213             : }
    1214             : 
    1215             : static const uint32_t WasmInstanceEnvShapeFlags =
    1216             :     BaseShape::NOT_EXTENSIBLE | BaseShape::DELEGATE;
    1217             : 
    1218             : 
    1219             : template <size_t ArrayLength>
    1220             : static JSAtom*
    1221           0 : GenerateWasmName(JSContext* cx, const char (&prefix)[ArrayLength], uint32_t index)
    1222             : {
    1223           0 :     StringBuffer sb(cx);
    1224           0 :     if (!sb.append(prefix))
    1225             :         return nullptr;
    1226           0 :     if (!NumberValueToStringBuffer(cx, Int32Value(index), sb))
    1227             :         return nullptr;
    1228             : 
    1229           0 :     return sb.finishAtom();
    1230             : }
    1231             : 
    1232             : /* static */ WasmInstanceScope*
    1233           0 : WasmInstanceScope::create(JSContext* cx, WasmInstanceObject* instance)
    1234             : {
    1235             :     // WasmInstanceScope::Data has GCManagedDeletePolicy because it contains a
    1236             :     // GCPtr. Destruction of |data| below may trigger calls into the GC.
    1237           0 :     Rooted<WasmInstanceScope*> wasmInstanceScope(cx);
    1238             : 
    1239             :     {
    1240           0 :         size_t namesCount = 0;
    1241           0 :         if (instance->instance().memory()) {
    1242           0 :             namesCount++;
    1243             :         }
    1244           0 :         size_t globalsStart = namesCount;
    1245           0 :         size_t globalsCount = instance->instance().metadata().globals.length();
    1246           0 :         namesCount += globalsCount;
    1247             : 
    1248           0 :         Rooted<UniquePtr<Data>> data(cx, NewEmptyScopeData<WasmInstanceScope>(cx, namesCount));
    1249           0 :         if (!data)
    1250           0 :             return nullptr;
    1251             : 
    1252           0 :         size_t nameIndex = 0;
    1253           0 :         RootedAtom name(cx);
    1254           0 :         if (instance->instance().memory()) {
    1255           0 :             name = GenerateWasmName(cx, "memory", /* index = */ 0);
    1256           0 :             if (!name)
    1257           0 :                 return nullptr;
    1258           0 :             new (&data->trailingNames[nameIndex]) BindingName(name, false);
    1259             :             nameIndex++;
    1260             :         }
    1261           0 :         for (size_t i = 0; i < globalsCount; i++) {
    1262           0 :             name = GenerateWasmName(cx, "global", i);
    1263           0 :             if (!name)
    1264             :                 return nullptr;
    1265           0 :             new (&data->trailingNames[nameIndex]) BindingName(name, false);
    1266           0 :             nameIndex++;
    1267             :         }
    1268           0 :         MOZ_ASSERT(nameIndex == namesCount);
    1269             : 
    1270           0 :         data->instance.init(instance);
    1271           0 :         data->memoriesStart = 0;
    1272           0 :         data->globalsStart = globalsStart;
    1273           0 :         data->length = namesCount;
    1274             : 
    1275           0 :         Rooted<Scope*> enclosingScope(cx, &cx->global()->emptyGlobalScope());
    1276             : 
    1277           0 :         Scope* scope = Scope::create(cx, ScopeKind::WasmInstance, enclosingScope, /* envShape = */ nullptr);
    1278           0 :         if (!scope)
    1279           0 :             return nullptr;
    1280             : 
    1281           0 :         wasmInstanceScope = &scope->as<WasmInstanceScope>();
    1282           0 :         wasmInstanceScope->initData(std::move(data.get()));
    1283             :     }
    1284             : 
    1285           0 :     return wasmInstanceScope;
    1286             : }
    1287             : 
    1288             : /* static */ Shape*
    1289           0 : WasmInstanceScope::getEmptyEnvironmentShape(JSContext* cx)
    1290             : {
    1291           0 :     const Class* cls = &WasmInstanceEnvironmentObject::class_;
    1292           0 :     return EmptyEnvironmentShape(cx, cls, JSSLOT_FREE(cls), WasmInstanceEnvShapeFlags);
    1293             : }
    1294             : 
    1295             : // TODO Check what Debugger behavior should be when it evaluates a
    1296             : // var declaration.
    1297             : static const uint32_t WasmFunctionEnvShapeFlags =
    1298             :     BaseShape::NOT_EXTENSIBLE | BaseShape::DELEGATE;
    1299             : 
    1300             : /* static */ WasmFunctionScope*
    1301           0 : WasmFunctionScope::create(JSContext* cx, HandleScope enclosing, uint32_t funcIndex)
    1302             : {
    1303           0 :     MOZ_ASSERT(enclosing->is<WasmInstanceScope>());
    1304             : 
    1305           0 :     Rooted<WasmFunctionScope*> wasmFunctionScope(cx);
    1306             : 
    1307           0 :     Rooted<WasmInstanceObject*> instance(cx, enclosing->as<WasmInstanceScope>().instance());
    1308             : 
    1309             :     // TODO pull the local variable names from the wasm function definition.
    1310           0 :     wasm::ValTypeVector locals;
    1311             :     size_t argsLength;
    1312           0 :     if (!instance->instance().debug().debugGetLocalTypes(funcIndex, &locals, &argsLength))
    1313             :         return nullptr;
    1314           0 :     uint32_t namesCount = locals.length();
    1315             : 
    1316           0 :     Rooted<UniquePtr<Data>> data(cx, NewEmptyScopeData<WasmFunctionScope>(cx, namesCount));
    1317           0 :     if (!data)
    1318             :         return nullptr;
    1319             : 
    1320           0 :     data->funcIndex = funcIndex;
    1321           0 :     data->length = namesCount;
    1322           0 :     RootedAtom name(cx);
    1323           0 :     for (size_t i = 0; i < namesCount; i++) {
    1324           0 :         name = GenerateWasmName(cx, "var", i);
    1325           0 :         if (!name)
    1326             :             return nullptr;
    1327           0 :         new (&data->trailingNames[i]) BindingName(name, false);
    1328             :     }
    1329             : 
    1330           0 :     Scope* scope = Scope::create(cx, ScopeKind::WasmFunction, enclosing, /* envShape = */ nullptr);
    1331           0 :     if (!scope)
    1332             :         return nullptr;
    1333             : 
    1334           0 :     wasmFunctionScope = &scope->as<WasmFunctionScope>();
    1335           0 :     wasmFunctionScope->initData(std::move(data.get()));
    1336             : 
    1337           0 :     return wasmFunctionScope;
    1338             : }
    1339             : 
    1340             : /* static */ Shape*
    1341           0 : WasmFunctionScope::getEmptyEnvironmentShape(JSContext* cx)
    1342             : {
    1343           0 :     const Class* cls = &WasmFunctionCallObject::class_;
    1344           0 :     return EmptyEnvironmentShape(cx, cls, JSSLOT_FREE(cls), WasmFunctionEnvShapeFlags);
    1345             : }
    1346             : 
    1347           0 : ScopeIter::ScopeIter(JSScript* script)
    1348           0 :   : scope_(script->bodyScope())
    1349           0 : { }
    1350             : 
    1351             : bool
    1352       80930 : ScopeIter::hasSyntacticEnvironment() const
    1353             : {
    1354           0 :     return scope()->hasEnvironment() && scope()->kind() != ScopeKind::NonSyntactic;
    1355             : }
    1356             : 
    1357       49003 : BindingIter::BindingIter(Scope* scope)
    1358             : {
    1359           0 :     switch (scope->kind()) {
    1360             :       case ScopeKind::Lexical:
    1361             :       case ScopeKind::SimpleCatch:
    1362             :       case ScopeKind::Catch:
    1363          20 :         init(scope->as<LexicalScope>().data(),
    1364          40 :              scope->as<LexicalScope>().firstFrameSlot(), 0);
    1365           0 :         break;
    1366             :       case ScopeKind::NamedLambda:
    1367             :       case ScopeKind::StrictNamedLambda:
    1368         144 :         init(scope->as<LexicalScope>().data(), LOCALNO_LIMIT, IsNamedLambda);
    1369          72 :         break;
    1370             :       case ScopeKind::With:
    1371             :         // With scopes do not have bindings.
    1372           0 :         index_ = length_ = 0;
    1373           0 :         MOZ_ASSERT(done());
    1374             :         break;
    1375             :       case ScopeKind::Function: {
    1376       47935 :         uint8_t flags = IgnoreDestructuredFormalParameters;
    1377       95870 :         if (scope->as<FunctionScope>().hasParameterExprs())
    1378           0 :             flags |= HasFormalParameterExprs;
    1379           0 :         init(scope->as<FunctionScope>().data(), flags);
    1380           0 :         break;
    1381             :       }
    1382             :       case ScopeKind::FunctionBodyVar:
    1383             :       case ScopeKind::ParameterExpressionVar:
    1384           0 :         init(scope->as<VarScope>().data(),
    1385           0 :              scope->as<VarScope>().firstFrameSlot());
    1386           0 :         break;
    1387             :       case ScopeKind::Eval:
    1388             :       case ScopeKind::StrictEval:
    1389           0 :         init(scope->as<EvalScope>().data(), scope->kind() == ScopeKind::StrictEval);
    1390           0 :         break;
    1391             :       case ScopeKind::Global:
    1392             :       case ScopeKind::NonSyntactic:
    1393        1956 :         init(scope->as<GlobalScope>().data());
    1394             :         break;
    1395             :       case ScopeKind::Module:
    1396           0 :         init(scope->as<ModuleScope>().data());
    1397           0 :         break;
    1398             :       case ScopeKind::WasmInstance:
    1399           0 :         init(scope->as<WasmInstanceScope>().data());
    1400             :         break;
    1401             :       case ScopeKind::WasmFunction:
    1402           0 :         init(scope->as<WasmFunctionScope>().data());
    1403             :         break;
    1404             :     }
    1405       49003 : }
    1406             : 
    1407           0 : BindingIter::BindingIter(JSScript* script)
    1408       46881 :   : BindingIter(script->bodyScope())
    1409           0 : { }
    1410             : 
    1411             : void
    1412       19350 : BindingIter::init(LexicalScope::Data& data, uint32_t firstFrameSlot, uint8_t flags)
    1413             : {
    1414             :     // Named lambda scopes can only have environment slots. If the callee
    1415             :     // isn't closed over, it is accessed via JSOP_CALLEE.
    1416       19350 :     if (flags & IsNamedLambda) {
    1417             :         // Named lambda binding is weird. Normal BindingKind ordering rules
    1418             :         // don't apply.
    1419       10152 :         init(0, 0, 0, 0, 0,
    1420        2538 :              CanHaveEnvironmentSlots | flags,
    1421           0 :              firstFrameSlot, JSSLOT_FREE(&LexicalEnvironmentObject::class_),
    1422             :              data.trailingNames.start(), data.length);
    1423             :     } else {
    1424             :         //            imports - [0, 0)
    1425             :         // positional formals - [0, 0)
    1426             :         //      other formals - [0, 0)
    1427             :         //               vars - [0, 0)
    1428             :         //               lets - [0, data.constStart)
    1429             :         //             consts - [data.constStart, data.length)
    1430       67248 :         init(0, 0, 0, 0, data.constStart,
    1431       16812 :              CanHaveFrameSlots | CanHaveEnvironmentSlots | flags,
    1432       16812 :              firstFrameSlot, JSSLOT_FREE(&LexicalEnvironmentObject::class_),
    1433             :              data.trailingNames.start(), data.length);
    1434             :     }
    1435           0 : }
    1436             : 
    1437             : void
    1438           0 : BindingIter::init(FunctionScope::Data& data, uint8_t flags)
    1439             : {
    1440      119184 :     flags = CanHaveFrameSlots | CanHaveEnvironmentSlots | flags;
    1441           0 :     if (!(flags & HasFormalParameterExprs))
    1442      115974 :         flags |= CanHaveArgumentSlots;
    1443             : 
    1444             :     //            imports - [0, 0)
    1445             :     // positional formals - [0, data.nonPositionalFormalStart)
    1446             :     //      other formals - [data.nonPositionalParamStart, data.varStart)
    1447             :     //               vars - [data.varStart, data.length)
    1448             :     //               lets - [data.length, data.length)
    1449             :     //             consts - [data.length, data.length)
    1450      357554 :     init(0, data.nonPositionalFormalStart, data.varStart, data.length, data.length,
    1451             :          flags,
    1452      119184 :          0, JSSLOT_FREE(&CallObject::class_),
    1453      119187 :          data.trailingNames.start(), data.length);
    1454           0 : }
    1455             : 
    1456             : void
    1457           0 : BindingIter::init(VarScope::Data& data, uint32_t firstFrameSlot)
    1458             : {
    1459             :     //            imports - [0, 0)
    1460             :     // positional formals - [0, 0)
    1461             :     //      other formals - [0, 0)
    1462             :     //               vars - [0, data.length)
    1463             :     //               lets - [data.length, data.length)
    1464             :     //             consts - [data.length, data.length)
    1465         255 :     init(0, 0, 0, data.length, data.length,
    1466             :          CanHaveFrameSlots | CanHaveEnvironmentSlots,
    1467          85 :          firstFrameSlot, JSSLOT_FREE(&VarEnvironmentObject::class_),
    1468          85 :          data.trailingNames.start(), data.length);
    1469          85 : }
    1470             : 
    1471             : void
    1472           0 : BindingIter::init(GlobalScope::Data& data)
    1473             : {
    1474             :     //            imports - [0, 0)
    1475             :     // positional formals - [0, 0)
    1476             :     //      other formals - [0, 0)
    1477             :     //               vars - [0, data.letStart)
    1478             :     //               lets - [data.letStart, data.constStart)
    1479             :     //             consts - [data.constStart, data.length)
    1480        2510 :     init(0, 0, 0, data.letStart, data.constStart,
    1481             :          CannotHaveSlots,
    1482             :          UINT32_MAX, UINT32_MAX,
    1483        1255 :          data.trailingNames.start(), data.length);
    1484         277 : }
    1485             : 
    1486             : void
    1487          20 : BindingIter::init(EvalScope::Data& data, bool strict)
    1488             : {
    1489             :     uint32_t flags;
    1490             :     uint32_t firstFrameSlot;
    1491             :     uint32_t firstEnvironmentSlot;
    1492          20 :     if (strict) {
    1493           0 :         flags = CanHaveFrameSlots | CanHaveEnvironmentSlots;
    1494          20 :         firstFrameSlot = 0;
    1495          20 :         firstEnvironmentSlot = JSSLOT_FREE(&VarEnvironmentObject::class_);
    1496             :     } else {
    1497             :         flags = CannotHaveSlots;
    1498             :         firstFrameSlot = UINT32_MAX;
    1499             :         firstEnvironmentSlot = UINT32_MAX;
    1500             :     }
    1501             : 
    1502             :     //            imports - [0, 0)
    1503             :     // positional formals - [0, 0)
    1504             :     //      other formals - [0, 0)
    1505             :     //               vars - [0, data.length)
    1506             :     //               lets - [data.length, data.length)
    1507             :     //             consts - [data.length, data.length)
    1508          40 :     init(0, 0, 0, data.length, data.length,
    1509             :          flags, firstFrameSlot, firstEnvironmentSlot,
    1510          20 :          data.trailingNames.start(), data.length);
    1511          20 : }
    1512             : 
    1513             : void
    1514           0 : BindingIter::init(ModuleScope::Data& data)
    1515             : {
    1516             :     //            imports - [0, data.varStart)
    1517             :     // positional formals - [data.varStart, data.varStart)
    1518             :     //      other formals - [data.varStart, data.varStart)
    1519             :     //               vars - [data.varStart, data.letStart)
    1520             :     //               lets - [data.letStart, data.constStart)
    1521             :     //             consts - [data.constStart, data.length)
    1522           0 :     init(data.varStart, data.varStart, data.varStart, data.letStart, data.constStart,
    1523             :          CanHaveFrameSlots | CanHaveEnvironmentSlots,
    1524           0 :          0, JSSLOT_FREE(&ModuleEnvironmentObject::class_),
    1525           0 :          data.trailingNames.start(), data.length);
    1526           0 : }
    1527             : 
    1528             : void
    1529           0 : BindingIter::init(WasmInstanceScope::Data& data)
    1530             : {
    1531             :     //            imports - [0, 0)
    1532             :     // positional formals - [0, 0)
    1533             :     //      other formals - [0, 0)
    1534             :     //               vars - [0, data.length)
    1535             :     //               lets - [data.length, data.length)
    1536             :     //             consts - [data.length, data.length)
    1537           0 :     init(0, 0, 0, data.length, data.length,
    1538             :          CanHaveFrameSlots | CanHaveEnvironmentSlots,
    1539             :          UINT32_MAX, UINT32_MAX,
    1540           0 :          data.trailingNames.start(), data.length);
    1541           0 : }
    1542             : 
    1543             : void
    1544           0 : BindingIter::init(WasmFunctionScope::Data& data)
    1545             : {
    1546             :     //            imports - [0, 0)
    1547             :     // positional formals - [0, 0)
    1548             :     //      other formals - [0, 0)
    1549             :     //               vars - [0, data.length)
    1550             :     //               lets - [data.length, data.length)
    1551             :     //             consts - [data.length, data.length)
    1552           0 :     init(0, 0, 0, data.length, data.length,
    1553             :          CanHaveFrameSlots | CanHaveEnvironmentSlots,
    1554             :          UINT32_MAX, UINT32_MAX,
    1555           0 :          data.trailingNames.start(), data.length);
    1556           0 : }
    1557             : 
    1558       46466 : PositionalFormalParameterIter::PositionalFormalParameterIter(JSScript* script)
    1559       46466 :   : BindingIter(script)
    1560             : {
    1561             :     // Reinit with flags = 0, i.e., iterate over all positional parameters.
    1562           0 :     if (script->bodyScope()->is<FunctionScope>())
    1563       92934 :         init(script->bodyScope()->as<FunctionScope>().data(), /* flags = */ 0);
    1564       46467 :     settle();
    1565           0 : }
    1566             : 
    1567             : void
    1568           0 : js::DumpBindings(JSContext* cx, Scope* scopeArg)
    1569             : {
    1570           0 :     RootedScope scope(cx, scopeArg);
    1571           0 :     for (Rooted<BindingIter> bi(cx, BindingIter(scope)); bi; bi++) {
    1572           0 :         JSAutoByteString bytes;
    1573           0 :         if (!AtomToPrintableString(cx, bi.name(), &bytes))
    1574           0 :             return;
    1575           0 :         fprintf(stderr, "%s %s ", BindingKindString(bi.kind()), bytes.ptr());
    1576           0 :         switch (bi.location().kind()) {
    1577             :           case BindingLocation::Kind::Global:
    1578           0 :             if (bi.isTopLevelFunction())
    1579           0 :                 fprintf(stderr, "global function\n");
    1580             :             else
    1581           0 :                 fprintf(stderr, "global\n");
    1582             :             break;
    1583             :           case BindingLocation::Kind::Argument:
    1584           0 :             fprintf(stderr, "arg slot %u\n", bi.location().argumentSlot());
    1585           0 :             break;
    1586             :           case BindingLocation::Kind::Frame:
    1587           0 :             fprintf(stderr, "frame slot %u\n", bi.location().slot());
    1588           0 :             break;
    1589             :           case BindingLocation::Kind::Environment:
    1590           0 :             fprintf(stderr, "env slot %u\n", bi.location().slot());
    1591           0 :             break;
    1592             :           case BindingLocation::Kind::NamedLambdaCallee:
    1593           0 :             fprintf(stderr, "named lambda callee\n");
    1594             :             break;
    1595             :           case BindingLocation::Kind::Import:
    1596           0 :             fprintf(stderr, "import\n");
    1597             :             break;
    1598             :         }
    1599             :     }
    1600             : }
    1601             : 
    1602             : static JSAtom*
    1603           0 : GetFrameSlotNameInScope(Scope* scope, uint32_t slot)
    1604             : {
    1605           0 :     for (BindingIter bi(scope); bi; bi++) {
    1606           0 :         BindingLocation loc = bi.location();
    1607           0 :         if (loc.kind() == BindingLocation::Kind::Frame && loc.slot() == slot)
    1608           0 :             return bi.name();
    1609             :     }
    1610           0 :     return nullptr;
    1611             : }
    1612             : 
    1613             : JSAtom*
    1614           0 : js::FrameSlotName(JSScript* script, jsbytecode* pc)
    1615             : {
    1616           0 :     MOZ_ASSERT(IsLocalOp(JSOp(*pc)));
    1617           0 :     uint32_t slot = GET_LOCALNO(pc);
    1618           0 :     MOZ_ASSERT(slot < script->nfixed());
    1619             : 
    1620             :     // Look for it in the body scope first.
    1621           0 :     if (JSAtom* name = GetFrameSlotNameInScope(script->bodyScope(), slot))
    1622             :         return name;
    1623             : 
    1624             :     // If this is a function script and there is an extra var scope, look for
    1625             :     // it there.
    1626           0 :     if (script->functionHasExtraBodyVarScope()) {
    1627           0 :         if (JSAtom* name = GetFrameSlotNameInScope(script->functionExtraBodyVarScope(), slot))
    1628             :             return name;
    1629             :     }
    1630             : 
    1631             :     // If not found, look for it in a lexical scope.
    1632           0 :     for (ScopeIter si(script->innermostScope(pc)); si; si++) {
    1633           0 :         if (!si.scope()->is<LexicalScope>())
    1634             :             continue;
    1635           0 :         LexicalScope& lexicalScope = si.scope()->as<LexicalScope>();
    1636             : 
    1637             :         // Is the slot within bounds of the current lexical scope?
    1638           0 :         if (slot < lexicalScope.firstFrameSlot())
    1639             :             continue;
    1640           0 :         if (slot >= lexicalScope.nextFrameSlot())
    1641             :             break;
    1642             : 
    1643             :         // If so, get the name.
    1644           0 :         if (JSAtom* name = GetFrameSlotNameInScope(&lexicalScope, slot))
    1645           0 :             return name;
    1646             :     }
    1647             : 
    1648           0 :     MOZ_CRASH("Frame slot not found");
    1649             : }
    1650             : 
    1651             : JS::ubi::Node::Size
    1652           0 : JS::ubi::Concrete<Scope>::size(mozilla::MallocSizeOf mallocSizeOf) const
    1653             : {
    1654           0 :     return js::gc::Arena::thingSize(get().asTenured().getAllocKind()) +
    1655           0 :            get().sizeOfExcludingThis(mallocSizeOf);
    1656             : }

Generated by: LCOV version 1.13-14-ga5dd952