Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/js/src/vm/Scope.h
Line
Count
Source (jump to first uncovered line)
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
#ifndef vm_Scope_h
8
#define vm_Scope_h
9
10
#include "mozilla/Maybe.h"
11
#include "mozilla/TypeTraits.h"
12
#include "mozilla/Variant.h"
13
14
#include <stddef.h>
15
16
#include "jsutil.h"
17
18
#include "gc/DeletePolicy.h"
19
#include "gc/Heap.h"
20
#include "gc/Policy.h"
21
#include "js/UbiNode.h"
22
#include "js/UniquePtr.h"
23
#include "vm/BytecodeUtil.h"
24
#include "vm/JSObject.h"
25
#include "vm/Xdr.h"
26
27
namespace js {
28
29
class BaseScopeData;
30
class ModuleObject;
31
class Scope;
32
33
enum class BindingKind : uint8_t
34
{
35
    Import,
36
    FormalParameter,
37
    Var,
38
    Let,
39
    Const,
40
41
    // So you think named lambda callee names are consts? Nope! They don't
42
    // throw when being assigned to in sloppy mode.
43
    NamedLambdaCallee
44
};
45
46
static inline bool
47
BindingKindIsLexical(BindingKind kind)
48
24.5k
{
49
24.5k
    return kind == BindingKind::Let || kind == BindingKind::Const;
50
24.5k
}
Unexecuted instantiation: CTypes.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: StoreBuffer.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: jsutil.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: StructuredClone.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src0.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src1.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src10.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src11.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src12.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src14.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src15.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src17.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src18.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src19.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src2.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src20.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src21.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src22.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src23.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src24.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src25.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src26.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src27.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src28.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src29.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src3.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src30.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src31.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src32.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src33.cpp:js::BindingKindIsLexical(js::BindingKind)
Unified_cpp_js_src34.cpp:js::BindingKindIsLexical(js::BindingKind)
Line
Count
Source
48
6
{
49
6
    return kind == BindingKind::Let || kind == BindingKind::Const;
50
6
}
Unexecuted instantiation: Unified_cpp_js_src35.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src36.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src37.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src38.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src39.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src4.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src40.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src41.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src42.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src43.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src44.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src45.cpp:js::BindingKindIsLexical(js::BindingKind)
Unified_cpp_js_src5.cpp:js::BindingKindIsLexical(js::BindingKind)
Line
Count
Source
48
22.1k
{
49
22.1k
    return kind == BindingKind::Let || kind == BindingKind::Const;
50
22.1k
}
Unified_cpp_js_src6.cpp:js::BindingKindIsLexical(js::BindingKind)
Line
Count
Source
48
171
{
49
171
    return kind == BindingKind::Let || kind == BindingKind::Const;
50
171
}
Unexecuted instantiation: Unified_cpp_js_src7.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src8.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src9.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: RegExp.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: BinSource-auto.cpp:js::BindingKindIsLexical(js::BindingKind)
BinSource.cpp:js::BindingKindIsLexical(js::BindingKind)
Line
Count
Source
48
2.24k
{
49
2.24k
    return kind == BindingKind::Let || kind == BindingKind::Const;
50
2.24k
}
Unexecuted instantiation: BinToken.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: BinTokenReaderBase.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: BinTokenReaderMultipart.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: BinTokenReaderTester.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Parser.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Disassembler-x86-shared.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: jsmath.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Interpreter.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: VTuneWrapper.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src13.cpp:js::BindingKindIsLexical(js::BindingKind)
Unexecuted instantiation: Unified_cpp_js_src16.cpp:js::BindingKindIsLexical(js::BindingKind)
51
52
enum class ScopeKind : uint8_t
53
{
54
    // FunctionScope
55
    Function,
56
57
    // VarScope
58
    FunctionBodyVar,
59
    ParameterExpressionVar,
60
61
    // LexicalScope
62
    Lexical,
63
    SimpleCatch,
64
    Catch,
65
    NamedLambda,
66
    StrictNamedLambda,
67
68
    // WithScope
69
    With,
70
71
    // EvalScope
72
    Eval,
73
    StrictEval,
74
75
    // GlobalScope
76
    Global,
77
    NonSyntactic,
78
79
    // ModuleScope
80
    Module,
81
82
    // WasmInstanceScope
83
    WasmInstance,
84
85
    // WasmFunctionScope
86
    WasmFunction
87
};
88
89
static inline bool
90
ScopeKindIsCatch(ScopeKind kind)
91
0
{
92
0
    return kind == ScopeKind::SimpleCatch || kind == ScopeKind::Catch;
93
0
}
Unexecuted instantiation: CTypes.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: StoreBuffer.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: jsutil.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: StructuredClone.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src0.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src1.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src10.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src11.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src12.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src14.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src15.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src17.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src18.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src19.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src2.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src20.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src21.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src22.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src23.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src24.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src25.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src26.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src27.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src28.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src29.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src3.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src30.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src31.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src32.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src33.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src34.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src35.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src36.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src37.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src38.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src39.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src4.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src40.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src41.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src42.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src43.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src44.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src45.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src5.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src6.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src7.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src8.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src9.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: RegExp.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: BinSource-auto.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: BinSource.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: BinToken.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: BinTokenReaderBase.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: BinTokenReaderMultipart.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: BinTokenReaderTester.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Parser.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Disassembler-x86-shared.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: jsmath.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Interpreter.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: VTuneWrapper.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src13.cpp:js::ScopeKindIsCatch(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src16.cpp:js::ScopeKindIsCatch(js::ScopeKind)
94
95
static inline bool
96
ScopeKindIsInBody(ScopeKind kind)
97
2.26k
{
98
2.26k
    return kind == ScopeKind::Lexical ||
99
2.26k
           kind == ScopeKind::SimpleCatch ||
100
2.26k
           kind == ScopeKind::Catch ||
101
2.26k
           kind == ScopeKind::With ||
102
2.26k
           kind == ScopeKind::FunctionBodyVar ||
103
2.26k
           kind == ScopeKind::ParameterExpressionVar;
104
2.26k
}
Unexecuted instantiation: CTypes.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: StoreBuffer.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: jsutil.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: StructuredClone.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src0.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src1.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src10.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src11.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src12.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src14.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src15.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unified_cpp_js_src17.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Line
Count
Source
97
28
{
98
28
    return kind == ScopeKind::Lexical ||
99
28
           kind == ScopeKind::SimpleCatch ||
100
28
           kind == ScopeKind::Catch ||
101
28
           kind == ScopeKind::With ||
102
28
           kind == ScopeKind::FunctionBodyVar ||
103
28
           kind == ScopeKind::ParameterExpressionVar;
104
28
}
Unexecuted instantiation: Unified_cpp_js_src18.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src19.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src2.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src20.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src21.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src22.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src23.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src24.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src25.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src26.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src27.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src28.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src29.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src3.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src30.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src31.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src32.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src33.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src34.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src35.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src36.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src37.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src38.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src39.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src4.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src40.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src41.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src42.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src43.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src44.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src45.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src5.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unified_cpp_js_src6.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Line
Count
Source
97
2.24k
{
98
2.24k
    return kind == ScopeKind::Lexical ||
99
2.24k
           kind == ScopeKind::SimpleCatch ||
100
2.24k
           kind == ScopeKind::Catch ||
101
2.24k
           kind == ScopeKind::With ||
102
2.24k
           kind == ScopeKind::FunctionBodyVar ||
103
2.24k
           kind == ScopeKind::ParameterExpressionVar;
104
2.24k
}
Unexecuted instantiation: Unified_cpp_js_src7.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src8.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src9.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: RegExp.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: BinSource-auto.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: BinSource.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: BinToken.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: BinTokenReaderBase.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: BinTokenReaderMultipart.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: BinTokenReaderTester.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Parser.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Disassembler-x86-shared.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: jsmath.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Interpreter.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: VTuneWrapper.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src13.cpp:js::ScopeKindIsInBody(js::ScopeKind)
Unexecuted instantiation: Unified_cpp_js_src16.cpp:js::ScopeKindIsInBody(js::ScopeKind)
105
106
const char* BindingKindString(BindingKind kind);
107
const char* ScopeKindString(ScopeKind kind);
108
109
class BindingName
110
{
111
    // A JSAtom* with its low bit used as a tag for the:
112
    //  * whether it is closed over (i.e., exists in the environment shape)
113
    //  * whether it is a top-level function binding in global or eval scope,
114
    //    instead of var binding (both are in the same range in Scope data)
115
    uintptr_t bits_;
116
117
    static const uintptr_t ClosedOverFlag = 0x1;
118
    // TODO: We should reuse this bit for let vs class distinction to
119
    //       show the better redeclaration error message (bug 1428672).
120
    static const uintptr_t TopLevelFunctionFlag = 0x2;
121
    static const uintptr_t FlagMask = 0x3;
122
123
  public:
124
    BindingName()
125
      : bits_(0)
126
2.32k
    { }
127
128
    BindingName(JSAtom* name, bool closedOver, bool isTopLevelFunction = false)
129
      : bits_(uintptr_t(name) |
130
              (closedOver ? ClosedOverFlag : 0x0) |
131
              (isTopLevelFunction? TopLevelFunctionFlag : 0x0))
132
17.9k
    { }
133
134
  private:
135
    // For fromXDR.
136
    BindingName(JSAtom* name, uint8_t flags)
137
      : bits_(uintptr_t(name) | flags)
138
0
    {
139
0
        static_assert(FlagMask < alignof(JSAtom),
140
0
                      "Flags should fit into unused bits of JSAtom pointer");
141
0
        MOZ_ASSERT((flags & FlagMask) == flags);
142
0
    }
143
144
  public:
145
0
    static BindingName fromXDR(JSAtom* name, uint8_t flags) {
146
0
        return BindingName(name, flags);
147
0
    }
148
149
245
    uint8_t flagsForXDR() const {
150
245
        return static_cast<uint8_t>(bits_ & FlagMask);
151
245
    }
152
153
43.0k
    JSAtom* name() const {
154
43.0k
        return reinterpret_cast<JSAtom*>(bits_ & ~FlagMask);
155
43.0k
    }
156
157
28.5k
    bool closedOver() const {
158
28.5k
        return bits_ & ClosedOverFlag;
159
28.5k
    }
160
161
  private:
162
    friend class BindingIter;
163
    // This method should be called only for binding names in `vars` range in
164
    // BindingIter.
165
15
    bool isTopLevelFunction() const {
166
15
        return bits_ & TopLevelFunctionFlag;
167
15
    }
168
169
  public:
170
    void trace(JSTracer* trc);
171
};
172
173
/**
174
 * The various {Global,Module,...}Scope::Data classes consist of always-present
175
 * bits, then a trailing array of BindingNames.  The various Data classes all
176
 * end in a TrailingNamesArray that contains sized/aligned space for *one*
177
 * BindingName.  Data instances that contain N BindingNames, are then allocated
178
 * in sizeof(Data) + (space for (N - 1) BindingNames).  Because this class's
179
 * |data_| field is properly sized/aligned, the N-BindingName array can start
180
 * at |data_|.
181
 *
182
 * This is concededly a very low-level representation, but we want to only
183
 * allocate once for data+bindings both, and this does so approximately as
184
 * elegantly as C++ allows.
185
 */
186
class TrailingNamesArray
187
{
188
  private:
189
    alignas(BindingName) unsigned char data_[sizeof(BindingName)];
190
191
  private:
192
    // Some versions of GCC treat it as a -Wstrict-aliasing violation (ergo a
193
    // -Werror compile error) to reinterpret_cast<> |data_| to |T*|, even
194
    // through |void*|.  Placing the latter cast in these separate functions
195
    // breaks the chain such that affected GCC versions no longer warn/error.
196
17.6k
    void* ptr() {
197
17.6k
        return data_;
198
17.6k
    }
199
200
  public:
201
    // Explicitly ensure no one accidentally allocates scope data without
202
    // poisoning its trailing names.
203
    TrailingNamesArray() = delete;
204
205
1.92k
    explicit TrailingNamesArray(size_t nameCount) {
206
1.92k
        if (nameCount) {
207
1.81k
            JS_POISON(&data_, 0xCC, sizeof(BindingName) * nameCount, MemCheckKind::MakeUndefined);
208
1.81k
        }
209
1.92k
    }
210
211
17.6k
    BindingName* start() { return reinterpret_cast<BindingName*>(ptr()); }
212
213
5.12k
    BindingName& get(size_t i) { return start()[i]; }
214
248
    BindingName& operator[](size_t i) { return get(i); }
215
};
216
217
class BindingLocation
218
{
219
  public:
220
    enum class Kind {
221
        Global,
222
        Argument,
223
        Frame,
224
        Environment,
225
        Import,
226
        NamedLambdaCallee
227
    };
228
229
  private:
230
    Kind kind_;
231
    uint32_t slot_;
232
233
    BindingLocation(Kind kind, uint32_t slot)
234
      : kind_(kind),
235
        slot_(slot)
236
8.06k
    { }
237
238
  public:
239
15
    static BindingLocation Global() {
240
15
        return BindingLocation(Kind::Global, UINT32_MAX);
241
15
    }
242
243
2.13k
    static BindingLocation Argument(uint16_t slot) {
244
2.13k
        return BindingLocation(Kind::Argument, slot);
245
2.13k
    }
246
247
5.29k
    static BindingLocation Frame(uint32_t slot) {
248
5.29k
        MOZ_ASSERT(slot < LOCALNO_LIMIT);
249
5.29k
        return BindingLocation(Kind::Frame, slot);
250
5.29k
    }
251
252
581
    static BindingLocation Environment(uint32_t slot) {
253
581
        MOZ_ASSERT(slot < ENVCOORD_SLOT_LIMIT);
254
581
        return BindingLocation(Kind::Environment, slot);
255
581
    }
256
257
0
    static BindingLocation Import() {
258
0
        return BindingLocation(Kind::Import, UINT32_MAX);
259
0
    }
260
261
39
    static BindingLocation NamedLambdaCallee() {
262
39
        return BindingLocation(Kind::NamedLambdaCallee, UINT32_MAX);
263
39
    }
264
265
0
    bool operator==(const BindingLocation& other) const {
266
0
        return kind_ == other.kind_ && slot_ == other.slot_;
267
0
    }
268
269
0
    bool operator!=(const BindingLocation& other) const {
270
0
        return !operator==(other);
271
0
    }
272
273
7.83k
    Kind kind() const {
274
7.83k
        return kind_;
275
7.83k
    }
276
277
5.73k
    uint32_t slot() const {
278
5.73k
        MOZ_ASSERT(kind_ == Kind::Frame || kind_ == Kind::Environment);
279
5.73k
        return slot_;
280
5.73k
    }
281
282
2.11k
    uint16_t argumentSlot() const {
283
2.11k
        MOZ_ASSERT(kind_ == Kind::Argument);
284
2.11k
        return mozilla::AssertedCast<uint16_t>(slot_);
285
2.11k
    }
286
};
287
288
//
289
// Allow using is<T> and as<T> on Rooted<Scope*> and Handle<Scope*>.
290
//
291
template <typename Wrapper>
292
class WrappedPtrOperations<Scope*, Wrapper>
293
{
294
  public:
295
    template <class U>
296
153
    JS::Handle<U*> as() const {
297
153
        const Wrapper& self = *static_cast<const Wrapper*>(this);
298
153
        MOZ_ASSERT_IF(self, self->template is<U>());
299
153
        return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
300
153
    }
Unexecuted instantiation: JS::Handle<js::LexicalScope*> js::WrappedPtrOperations<js::Scope*, JS::Rooted<js::Scope*> >::as<js::LexicalScope>() const
JS::Handle<js::FunctionScope*> js::WrappedPtrOperations<js::Scope*, JS::Rooted<js::Scope*> >::as<js::FunctionScope>() const
Line
Count
Source
296
6
    JS::Handle<U*> as() const {
297
6
        const Wrapper& self = *static_cast<const Wrapper*>(this);
298
6
        MOZ_ASSERT_IF(self, self->template is<U>());
299
6
        return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
300
6
    }
JS::Handle<js::LexicalScope*> js::WrappedPtrOperations<js::Scope*, JS::MutableHandle<js::Scope*> >::as<js::LexicalScope>() const
Line
Count
Source
296
63
    JS::Handle<U*> as() const {
297
63
        const Wrapper& self = *static_cast<const Wrapper*>(this);
298
63
        MOZ_ASSERT_IF(self, self->template is<U>());
299
63
        return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
300
63
    }
JS::Handle<js::FunctionScope*> js::WrappedPtrOperations<js::Scope*, JS::MutableHandle<js::Scope*> >::as<js::FunctionScope>() const
Line
Count
Source
296
65
    JS::Handle<U*> as() const {
297
65
        const Wrapper& self = *static_cast<const Wrapper*>(this);
298
65
        MOZ_ASSERT_IF(self, self->template is<U>());
299
65
        return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
300
65
    }
JS::Handle<js::VarScope*> js::WrappedPtrOperations<js::Scope*, JS::MutableHandle<js::Scope*> >::as<js::VarScope>() const
Line
Count
Source
296
2
    JS::Handle<U*> as() const {
297
2
        const Wrapper& self = *static_cast<const Wrapper*>(this);
298
2
        MOZ_ASSERT_IF(self, self->template is<U>());
299
2
        return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
300
2
    }
JS::Handle<js::GlobalScope*> js::WrappedPtrOperations<js::Scope*, JS::MutableHandle<js::Scope*> >::as<js::GlobalScope>() const
Line
Count
Source
296
5
    JS::Handle<U*> as() const {
297
5
        const Wrapper& self = *static_cast<const Wrapper*>(this);
298
5
        MOZ_ASSERT_IF(self, self->template is<U>());
299
5
        return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
300
5
    }
Unexecuted instantiation: JS::Handle<js::EvalScope*> js::WrappedPtrOperations<js::Scope*, JS::MutableHandle<js::Scope*> >::as<js::EvalScope>() const
Unexecuted instantiation: JS::Handle<js::WithScope*> js::WrappedPtrOperations<js::Scope*, ReservedRooted<js::Scope*> >::as<js::WithScope>() const
JS::Handle<js::LexicalScope*> js::WrappedPtrOperations<js::Scope*, ReservedRooted<js::Scope*> >::as<js::LexicalScope>() const
Line
Count
Source
296
12
    JS::Handle<U*> as() const {
297
12
        const Wrapper& self = *static_cast<const Wrapper*>(this);
298
12
        MOZ_ASSERT_IF(self, self->template is<U>());
299
12
        return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
300
12
    }
301
};
302
303
//
304
// The base class of all Scopes.
305
//
306
class Scope : public js::gc::TenuredCell
307
{
308
    friend class GCMarker;
309
310
    // The enclosing scope or nullptr.
311
    GCPtrScope enclosing_;
312
313
    // The kind determines data_.
314
    ScopeKind kind_;
315
316
    // If there are any aliased bindings, the shape for the
317
    // EnvironmentObject. Otherwise nullptr.
318
    GCPtrShape environmentShape_;
319
320
  protected:
321
    BaseScopeData* data_;
322
323
    Scope(ScopeKind kind, Scope* enclosing, Shape* environmentShape)
324
      : enclosing_(enclosing),
325
        kind_(kind),
326
        environmentShape_(environmentShape),
327
1.92k
        data_(nullptr) { }
328
329
    static Scope* create(JSContext* cx, ScopeKind kind, HandleScope enclosing,
330
                         HandleShape envShape);
331
332
    template <typename ConcreteScope>
333
    static ConcreteScope* create(JSContext* cx, ScopeKind kind, HandleScope enclosing,
334
                                 HandleShape envShape,
335
                                 MutableHandle<UniquePtr<typename ConcreteScope::Data>> data);
336
337
    template <typename ConcreteScope, XDRMode mode>
338
    static XDRResult XDRSizedBindingNames(XDRState<mode>* xdr, Handle<ConcreteScope*> scope,
339
                                          MutableHandle<typename ConcreteScope::Data*> data);
340
341
    Shape* maybeCloneEnvironmentShape(JSContext* cx);
342
343
    template <typename ConcreteScope>
344
    void initData(MutableHandle<UniquePtr<typename ConcreteScope::Data>> data);
345
346
  public:
347
    static const JS::TraceKind TraceKind = JS::TraceKind::Scope;
348
349
    template <typename T>
350
4.87M
    bool is() const {
351
4.87M
        return kind_ == T::classScopeKind_;
352
4.87M
    }
bool js::Scope::is<js::FunctionScope>() const
Line
Count
Source
350
4.87M
    bool is() const {
351
4.87M
        return kind_ == T::classScopeKind_;
352
4.87M
    }
bool js::Scope::is<js::ModuleScope>() const
Line
Count
Source
350
164
    bool is() const {
351
164
        return kind_ == T::classScopeKind_;
352
164
    }
Unexecuted instantiation: bool js::Scope::is<js::WasmInstanceScope>() const
Unexecuted instantiation: bool js::Scope::is<js::WasmFunctionScope>() const
Unexecuted instantiation: bool js::Scope::is<js::WithScope>() const
353
354
    template <typename T>
355
4.88M
    T& as() {
356
4.88M
        MOZ_ASSERT(this->is<T>());
357
4.88M
        return *static_cast<T*>(this);
358
4.88M
    }
js::FunctionScope& js::Scope::as<js::FunctionScope>()
Line
Count
Source
355
4.88M
    T& as() {
356
4.88M
        MOZ_ASSERT(this->is<T>());
357
4.88M
        return *static_cast<T*>(this);
358
4.88M
    }
Unexecuted instantiation: js::ModuleScope& js::Scope::as<js::ModuleScope>()
js::VarScope& js::Scope::as<js::VarScope>()
Line
Count
Source
355
81
    T& as() {
356
81
        MOZ_ASSERT(this->is<T>());
357
81
        return *static_cast<T*>(this);
358
81
    }
js::LexicalScope& js::Scope::as<js::LexicalScope>()
Line
Count
Source
355
1.69k
    T& as() {
356
1.69k
        MOZ_ASSERT(this->is<T>());
357
1.69k
        return *static_cast<T*>(this);
358
1.69k
    }
js::GlobalScope& js::Scope::as<js::GlobalScope>()
Line
Count
Source
355
166
    T& as() {
356
166
        MOZ_ASSERT(this->is<T>());
357
166
        return *static_cast<T*>(this);
358
166
    }
Unexecuted instantiation: js::WasmInstanceScope& js::Scope::as<js::WasmInstanceScope>()
Unexecuted instantiation: js::WasmFunctionScope& js::Scope::as<js::WasmFunctionScope>()
Unexecuted instantiation: js::EvalScope& js::Scope::as<js::EvalScope>()
Unexecuted instantiation: js::WithScope& js::Scope::as<js::WithScope>()
359
360
    template <typename T>
361
    const T& as() const {
362
        MOZ_ASSERT(this->is<T>());
363
        return *static_cast<const T*>(this);
364
    }
365
366
13.6k
    ScopeKind kind() const {
367
13.6k
        return kind_;
368
13.6k
    }
369
370
3.94k
    Scope* enclosing() const {
371
3.94k
        return enclosing_;
372
3.94k
    }
373
374
491
    Shape* environmentShape() const {
375
491
        return environmentShape_;
376
491
    }
377
378
2.76k
    bool hasEnvironment() const {
379
2.76k
        switch (kind()) {
380
2.76k
          case ScopeKind::With:
381
11
          case ScopeKind::Global:
382
11
          case ScopeKind::NonSyntactic:
383
11
            return true;
384
2.74k
          default:
385
2.74k
            // If there's a shape, an environment must be created for this scope.
386
2.74k
            return environmentShape_ != nullptr;
387
2.76k
        }
388
2.76k
    }
389
390
    uint32_t chainLength() const;
391
    uint32_t environmentChainLength() const;
392
393
    template <typename T>
394
    bool hasOnChain() const {
395
        for (const Scope* it = this; it; it = it->enclosing()) {
396
            if (it->is<T>()) {
397
                return true;
398
            }
399
        }
400
        return false;
401
    }
402
403
1.49k
    bool hasOnChain(ScopeKind kind) const {
404
4.59k
        for (const Scope* it = this; it; it = it->enclosing()) {
405
3.17k
            if (it->kind() == kind) {
406
70
                return true;
407
70
            }
408
3.17k
        }
409
1.49k
        return false;
410
1.49k
    }
411
412
    static Scope* clone(JSContext* cx, HandleScope scope, HandleScope enclosing);
413
414
    void traceChildren(JSTracer* trc);
415
    void finalize(FreeOp* fop);
416
417
    size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
418
419
    void dump();
420
};
421
422
/** Empty base class for scope Data classes to inherit from. */
423
class BaseScopeData
424
{};
425
426
/*
427
 * Scope for a top level script: either a global (classic) script or a module
428
 * script.
429
 */
430
class TopLevelScopeData : public BaseScopeData
431
{
432
  public:
433
    // Private data for use by the embedding.
434
    void* privateData = nullptr;
435
};
436
437
template<class Data>
438
inline size_t
439
SizeOfData(uint32_t numBindings)
440
3.73k
{
441
3.73k
    static_assert(mozilla::IsBaseOf<BaseScopeData, Data>::value,
442
3.73k
                  "Data must be the correct sort of data, i.e. it must "
443
3.73k
                  "inherit from BaseScopeData");
444
3.73k
    return sizeof(Data) + (numBindings ? numBindings - 1 : 0) * sizeof(BindingName);
445
3.73k
}
unsigned long js::SizeOfData<js::VarScope::Data>(unsigned int)
Line
Count
Source
440
82
{
441
82
    static_assert(mozilla::IsBaseOf<BaseScopeData, Data>::value,
442
82
                  "Data must be the correct sort of data, i.e. it must "
443
82
                  "inherit from BaseScopeData");
444
82
    return sizeof(Data) + (numBindings ? numBindings - 1 : 0) * sizeof(BindingName);
445
82
}
unsigned long js::SizeOfData<js::LexicalScope::Data>(unsigned int)
Line
Count
Source
440
750
{
441
750
    static_assert(mozilla::IsBaseOf<BaseScopeData, Data>::value,
442
750
                  "Data must be the correct sort of data, i.e. it must "
443
750
                  "inherit from BaseScopeData");
444
750
    return sizeof(Data) + (numBindings ? numBindings - 1 : 0) * sizeof(BindingName);
445
750
}
Unexecuted instantiation: unsigned long js::SizeOfData<js::EvalScope::Data>(unsigned int)
unsigned long js::SizeOfData<js::FunctionScope::Data>(unsigned int)
Line
Count
Source
440
2.88k
{
441
2.88k
    static_assert(mozilla::IsBaseOf<BaseScopeData, Data>::value,
442
2.88k
                  "Data must be the correct sort of data, i.e. it must "
443
2.88k
                  "inherit from BaseScopeData");
444
2.88k
    return sizeof(Data) + (numBindings ? numBindings - 1 : 0) * sizeof(BindingName);
445
2.88k
}
unsigned long js::SizeOfData<js::GlobalScope::Data>(unsigned int)
Line
Count
Source
440
21
{
441
21
    static_assert(mozilla::IsBaseOf<BaseScopeData, Data>::value,
442
21
                  "Data must be the correct sort of data, i.e. it must "
443
21
                  "inherit from BaseScopeData");
444
21
    return sizeof(Data) + (numBindings ? numBindings - 1 : 0) * sizeof(BindingName);
445
21
}
Unexecuted instantiation: unsigned long js::SizeOfData<js::ModuleScope::Data>(unsigned int)
Unexecuted instantiation: unsigned long js::SizeOfData<js::WasmInstanceScope::Data>(unsigned int)
Unexecuted instantiation: unsigned long js::SizeOfData<js::WasmFunctionScope::Data>(unsigned int)
446
447
//
448
// A lexical scope that holds let and const bindings. There are 4 kinds of
449
// LexicalScopes.
450
//
451
// Lexical
452
//   A plain lexical scope.
453
//
454
// SimpleCatch
455
//   Holds the single catch parameter of a catch block.
456
//
457
// Catch
458
//   Holds the catch parameters (and only the catch parameters) of a catch
459
//   block.
460
//
461
// NamedLambda
462
// StrictNamedLambda
463
//   Holds the single name of the callee for a named lambda expression.
464
//
465
// All kinds of LexicalScopes correspond to LexicalEnvironmentObjects on the
466
// environment chain.
467
//
468
class LexicalScope : public Scope
469
{
470
    friend class Scope;
471
    friend class BindingIter;
472
    friend class GCMarker;
473
474
  public:
475
    // Data is public because it is created by the frontend. See
476
    // Parser<FullParseHandler>::newLexicalScopeData.
477
    struct Data : public BaseScopeData
478
    {
479
        // Bindings are sorted by kind in both frames and environments.
480
        //
481
        //   lets - [0, constStart)
482
        // consts - [constStart, length)
483
        uint32_t constStart = 0;
484
        uint32_t length = 0;
485
486
        // Frame slots [0, nextFrameSlot) are live when this is the innermost
487
        // scope.
488
        uint32_t nextFrameSlot = 0;
489
490
        // The array of tagged JSAtom* names, allocated beyond the end of the
491
        // struct.
492
        TrailingNamesArray trailingNames;
493
494
375
        explicit Data(size_t nameCount) : trailingNames(nameCount) {}
495
        Data() = delete;
496
497
        void trace(JSTracer* trc);
498
    };
499
500
    static LexicalScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data,
501
                                uint32_t firstFrameSlot, HandleScope enclosing);
502
503
    template <XDRMode mode>
504
    static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
505
                    MutableHandleScope scope);
506
507
  private:
508
    static LexicalScope* createWithData(JSContext* cx, ScopeKind kind,
509
                                        MutableHandle<UniquePtr<Data>> data,
510
                                        uint32_t firstFrameSlot, HandleScope enclosing);
511
512
1.26k
    Data& data() {
513
1.26k
        return *static_cast<Data*>(data_);
514
1.26k
    }
515
516
14
    const Data& data() const {
517
14
        return *static_cast<Data*>(data_);
518
14
    }
519
520
    static uint32_t nextFrameSlot(Scope* start);
521
522
  public:
523
    uint32_t firstFrameSlot() const;
524
525
14
    uint32_t nextFrameSlot() const {
526
14
        return data().nextFrameSlot;
527
14
    }
528
529
    // Returns an empty shape for extensible global and non-syntactic lexical
530
    // scopes.
531
    static Shape* getEmptyExtensibleEnvironmentShape(JSContext* cx);
532
};
533
534
template <>
535
inline bool
536
Scope::is<LexicalScope>() const
537
0
{
538
0
    return kind_ == ScopeKind::Lexical ||
539
0
           kind_ == ScopeKind::SimpleCatch ||
540
0
           kind_ == ScopeKind::Catch ||
541
0
           kind_ == ScopeKind::NamedLambda ||
542
0
           kind_ == ScopeKind::StrictNamedLambda;
543
0
}
544
545
//
546
// Scope corresponding to a function. Holds formal parameter names, special
547
// internal names (see FunctionScope::isSpecialName), and, if the function
548
// parameters contain no expressions that might possibly be evaluated, the
549
// function's var bindings. For example, in these functions, the FunctionScope
550
// will store a/b/c bindings but not d/e/f bindings:
551
//
552
//   function f1(a, b) {
553
//     var c;
554
//     let e;
555
//     const f = 3;
556
//   }
557
//   function f2([a], b = 4, ...c) {
558
//     var d, e, f; // stored in VarScope
559
//   }
560
//
561
// Corresponds to CallObject on environment chain.
562
//
563
class FunctionScope : public Scope
564
{
565
    friend class GCMarker;
566
    friend class BindingIter;
567
    friend class PositionalFormalParameterIter;
568
    friend class Scope;
569
    static const ScopeKind classScopeKind_ = ScopeKind::Function;
570
571
  public:
572
    // Data is public because it is created by the
573
    // frontend. See Parser<FullParseHandler>::newFunctionScopeData.
574
    struct Data : public BaseScopeData
575
    {
576
        // The canonical function of the scope, as during a scope walk we
577
        // often query properties of the JSFunction (e.g., is the function an
578
        // arrow).
579
        GCPtrFunction canonicalFunction = {};
580
581
        // If parameter expressions are present, parameters act like lexical
582
        // bindings.
583
        bool hasParameterExprs = false;
584
585
        // Bindings are sorted by kind in both frames and environments.
586
        //
587
        // Positional formal parameter names are those that are not
588
        // destructured. They may be referred to by argument slots if
589
        // !script()->hasParameterExprs().
590
        //
591
        // An argument slot that needs to be skipped due to being destructured
592
        // or having defaults will have a nullptr name in the name array to
593
        // advance the argument slot.
594
        //
595
        // Rest parameter binding is also included in positional formals.
596
        // This also becomes nullptr if destructuring.
597
        //
598
        // The number of positional formals is equal to function.length if
599
        // there's no rest, function.length+1 otherwise.
600
        //
601
        // Destructuring parameters and destructuring rest are included in
602
        // "other formals" below.
603
        //
604
        // "vars" contains the following:
605
        //   * function's top level vars if !script()->hasParameterExprs()
606
        //   * special internal names (arguments, .this, .generator) if
607
        //     they're used.
608
        //
609
        // positional formals - [0, nonPositionalFormalStart)
610
        //      other formals - [nonPositionalParamStart, varStart)
611
        //               vars - [varStart, length)
612
        uint16_t nonPositionalFormalStart = 0;
613
        uint16_t varStart = 0;
614
        uint32_t length = 0;
615
616
        // Frame slots [0, nextFrameSlot) are live when this is the innermost
617
        // scope.
618
        uint32_t nextFrameSlot = 0;
619
620
        // The array of tagged JSAtom* names, allocated beyond the end of the
621
        // struct.
622
        TrailingNamesArray trailingNames;
623
624
1.49k
        explicit Data(size_t nameCount) : trailingNames(nameCount) {}
625
        Data() = delete;
626
627
        void trace(JSTracer* trc);
628
        Zone* zone() const;
629
    };
630
631
    static FunctionScope* create(JSContext* cx, Handle<Data*> data,
632
                                 bool hasParameterExprs, bool needsEnvironment,
633
                                 HandleFunction fun, HandleScope enclosing);
634
635
    static FunctionScope* clone(JSContext* cx, Handle<FunctionScope*> scope, HandleFunction fun,
636
                                HandleScope enclosing);
637
638
    template <XDRMode mode>
639
    static XDRResult XDR(XDRState<mode>* xdr, HandleFunction fun, HandleScope enclosing,
640
                    MutableHandleScope scope);
641
642
  private:
643
    static FunctionScope* createWithData(JSContext* cx, MutableHandle<UniquePtr<Data>> data,
644
                                         bool hasParameterExprs, bool needsEnvironment,
645
                                         HandleFunction fun, HandleScope enclosing);
646
647
4.67k
    Data& data() {
648
4.67k
        return *static_cast<Data*>(data_);
649
4.67k
    }
650
651
4.87M
    const Data& data() const {
652
4.87M
        return *static_cast<Data*>(data_);
653
4.87M
    }
654
655
  public:
656
27
    uint32_t nextFrameSlot() const {
657
27
        return data().nextFrameSlot;
658
27
    }
659
660
4.87M
    JSFunction* canonicalFunction() const {
661
4.87M
        return data().canonicalFunction;
662
4.87M
    }
663
664
    JSScript* script() const;
665
666
1.84k
    bool hasParameterExprs() const {
667
1.84k
        return data().hasParameterExprs;
668
1.84k
    }
669
670
0
    uint32_t numPositionalFormalParameters() const {
671
0
        return data().nonPositionalFormalStart;
672
0
    }
673
674
    static bool isSpecialName(JSContext* cx, JSAtom* name);
675
676
    static Shape* getEmptyEnvironmentShape(JSContext* cx, bool hasParameterExprs);
677
};
678
679
//
680
// Scope holding only vars. There are 2 kinds of VarScopes.
681
//
682
// FunctionBodyVar
683
//   Corresponds to the extra var scope present in functions with parameter
684
//   expressions. See examples in comment above FunctionScope.
685
//
686
// ParameterExpressionVar
687
//   Each parameter expression is evaluated in its own var environment. For
688
//   example, f() below will print 'fml', then 'global'. That's right.
689
//
690
//     var a = 'global';
691
//     function f(x = (eval(`var a = 'fml'`), a), y = a) {
692
//       print(x);
693
//       print(y);
694
//     };
695
//
696
// Corresponds to VarEnvironmentObject on environment chain.
697
//
698
class VarScope : public Scope
699
{
700
    friend class GCMarker;
701
    friend class BindingIter;
702
    friend class Scope;
703
704
  public:
705
    // Data is public because it is created by the
706
    // frontend. See Parser<FullParseHandler>::newVarScopeData.
707
    struct Data : public BaseScopeData
708
    {
709
        // All bindings are vars.
710
        uint32_t length = 0;
711
712
        // Frame slots [firstFrameSlot(), nextFrameSlot) are live when this is
713
        // the innermost scope.
714
        uint32_t nextFrameSlot = 0;
715
716
        // The array of tagged JSAtom* names, allocated beyond the end of the
717
        // struct.
718
        TrailingNamesArray trailingNames;
719
720
41
        explicit Data(size_t nameCount) : trailingNames(nameCount) {}
721
        Data() = delete;
722
723
        void trace(JSTracer* trc);
724
    };
725
726
    static VarScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data,
727
                            uint32_t firstFrameSlot, bool needsEnvironment,
728
                            HandleScope enclosing);
729
730
    template <XDRMode mode>
731
    static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
732
                    MutableHandleScope scope);
733
734
  private:
735
    static VarScope* createWithData(JSContext* cx, ScopeKind kind, MutableHandle<UniquePtr<Data>> data,
736
                                    uint32_t firstFrameSlot, bool needsEnvironment,
737
                                    HandleScope enclosing);
738
739
40
    Data& data() {
740
40
        return *static_cast<Data*>(data_);
741
40
    }
742
743
2
    const Data& data() const {
744
2
        return *static_cast<Data*>(data_);
745
2
    }
746
747
  public:
748
    uint32_t firstFrameSlot() const;
749
750
2
    uint32_t nextFrameSlot() const {
751
2
        return data().nextFrameSlot;
752
2
    }
753
754
    static Shape* getEmptyEnvironmentShape(JSContext* cx);
755
};
756
757
template <>
758
inline bool
759
Scope::is<VarScope>() const
760
0
{
761
0
    return kind_ == ScopeKind::FunctionBodyVar || kind_ == ScopeKind::ParameterExpressionVar;
762
0
}
763
764
//
765
// Scope corresponding to both the global object scope and the global lexical
766
// scope.
767
//
768
// Both are extensible and are singletons across <script> tags, so these
769
// scopes are a fragment of the names in global scope. In other words, two
770
// global scripts may have two different GlobalScopes despite having the same
771
// GlobalObject.
772
//
773
// There are 2 kinds of GlobalScopes.
774
//
775
// Global
776
//   Corresponds to a GlobalObject and its global LexicalEnvironmentObject on
777
//   the environment chain.
778
//
779
// NonSyntactic
780
//   Corresponds to a non-GlobalObject created by the embedding on the
781
//   environment chain. This distinction is important for optimizations.
782
//
783
class GlobalScope : public Scope
784
{
785
    friend class Scope;
786
    friend class BindingIter;
787
    friend class GCMarker;
788
789
  public:
790
    // Data is public because it is created by the frontend. See
791
    // Parser<FullParseHandler>::newGlobalScopeData.
792
    struct Data : public TopLevelScopeData
793
    {
794
        // Bindings are sorted by kind.
795
        // `vars` includes top-level functions which is distinguished by a bit
796
        // on the BindingName.
797
        //
798
        //            vars - [0, letStart)
799
        //            lets - [letStart, constStart)
800
        //          consts - [constStart, length)
801
        uint32_t letStart = 0;
802
        uint32_t constStart = 0;
803
        uint32_t length = 0;
804
805
        // The array of tagged JSAtom* names, allocated beyond the end of the
806
        // struct.
807
        TrailingNamesArray trailingNames;
808
809
17
        explicit Data(size_t nameCount) : trailingNames(nameCount) {}
810
        Data() = delete;
811
812
        void trace(JSTracer* trc);
813
    };
814
815
    static GlobalScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data);
816
817
9
    static GlobalScope* createEmpty(JSContext* cx, ScopeKind kind) {
818
9
        return create(cx, kind, nullptr);
819
9
    }
820
821
    static GlobalScope* clone(JSContext* cx, Handle<GlobalScope*> scope, ScopeKind kind);
822
823
    template <XDRMode mode>
824
    static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, MutableHandleScope scope);
825
826
  private:
827
    static GlobalScope* createWithData(JSContext* cx, ScopeKind kind,
828
                                       MutableHandle<UniquePtr<Data>> data);
829
830
144
    Data& data() {
831
144
        return *static_cast<Data*>(data_);
832
144
    }
833
834
0
    const Data& data() const {
835
0
        return *static_cast<Data*>(data_);
836
0
    }
837
838
  public:
839
0
    bool isSyntactic() const {
840
0
        return kind() != ScopeKind::NonSyntactic;
841
0
    }
842
843
0
    bool hasBindings() const {
844
0
        return data().length > 0;
845
0
    }
846
847
0
    void setTopLevelPrivate(void* value) {
848
0
        data().privateData = value;
849
0
    }
850
851
0
    void* topLevelPrivate() const {
852
0
        return data().privateData;
853
0
    }
854
};
855
856
template <>
857
inline bool
858
Scope::is<GlobalScope>() const
859
372
{
860
372
    return kind_ == ScopeKind::Global || kind_ == ScopeKind::NonSyntactic;
861
372
}
862
863
//
864
// Scope of a 'with' statement. Has no bindings.
865
//
866
// Corresponds to a WithEnvironmentObject on the environment chain.
867
class WithScope : public Scope
868
{
869
    friend class Scope;
870
    static const ScopeKind classScopeKind_ = ScopeKind::With;
871
872
  public:
873
    static WithScope* create(JSContext* cx, HandleScope enclosing);
874
};
875
876
//
877
// Scope of an eval. Holds var bindings. There are 2 kinds of EvalScopes.
878
//
879
// StrictEval
880
//   A strict eval. Corresponds to a VarEnvironmentObject, where its var
881
//   bindings lives.
882
//
883
// Eval
884
//   A sloppy eval. This is an empty scope, used only in the frontend, to
885
//   detect redeclaration errors. It has no Environment. Any `var`s declared
886
//   in the eval code are bound on the nearest enclosing var environment.
887
//
888
class EvalScope : public Scope
889
{
890
    friend class Scope;
891
    friend class BindingIter;
892
    friend class GCMarker;
893
894
  public:
895
    // Data is public because it is created by the frontend. See
896
    // Parser<FullParseHandler>::newEvalScopeData.
897
    struct Data : public BaseScopeData
898
    {
899
        // All bindings in an eval script are 'var' bindings. The implicit
900
        // lexical scope around the eval is present regardless of strictness
901
        // and is its own LexicalScope.
902
        // `vars` includes top-level functions which is distinguished by a bit
903
        // on the BindingName.
904
        //
905
        //            vars - [0, length)
906
        uint32_t varStart = 0;
907
        uint32_t length = 0;
908
909
        // Frame slots [0, nextFrameSlot) are live when this is the innermost
910
        // scope.
911
        uint32_t nextFrameSlot = 0;
912
913
        // The array of tagged JSAtom* names, allocated beyond the end of the
914
        // struct.
915
        TrailingNamesArray trailingNames;
916
917
0
        explicit Data(size_t nameCount) : trailingNames(nameCount) {}
918
        Data() = delete;
919
920
        void trace(JSTracer* trc);
921
    };
922
923
    static EvalScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data,
924
                             HandleScope enclosing);
925
926
    template <XDRMode mode>
927
    static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
928
                    MutableHandleScope scope);
929
930
  private:
931
    static EvalScope* createWithData(JSContext* cx, ScopeKind kind, MutableHandle<UniquePtr<Data>> data,
932
                                     HandleScope enclosing);
933
934
0
    Data& data() {
935
0
        return *static_cast<Data*>(data_);
936
0
    }
937
938
0
    const Data& data() const {
939
0
        return *static_cast<Data*>(data_);
940
0
    }
941
942
  public:
943
    // Starting a scope, the nearest var scope that a direct eval can
944
    // introduce vars on.
945
    static Scope* nearestVarScopeForDirectEval(Scope* scope);
946
947
0
    uint32_t nextFrameSlot() const {
948
0
        return data().nextFrameSlot;
949
0
    }
950
951
0
    bool strict() const {
952
0
        return kind() == ScopeKind::StrictEval;
953
0
    }
954
955
0
    bool hasBindings() const {
956
0
        return data().length > 0;
957
0
    }
958
959
0
    bool isNonGlobal() const {
960
0
        if (strict()) {
961
0
            return true;
962
0
        }
963
0
        return !nearestVarScopeForDirectEval(enclosing())->is<GlobalScope>();
964
0
    }
965
966
    static Shape* getEmptyEnvironmentShape(JSContext* cx);
967
};
968
969
template <>
970
inline bool
971
Scope::is<EvalScope>() const
972
26
{
973
26
    return kind_ == ScopeKind::Eval || kind_ == ScopeKind::StrictEval;
974
26
}
975
976
//
977
// Scope corresponding to the toplevel script in an ES module.
978
//
979
// Like GlobalScopes, these scopes contain both vars and lexical bindings, as
980
// the treating of imports and exports requires putting them in one scope.
981
//
982
// Corresponds to a ModuleEnvironmentObject on the environment chain.
983
//
984
class ModuleScope : public Scope
985
{
986
    friend class GCMarker;
987
    friend class BindingIter;
988
    friend class Scope;
989
    static const ScopeKind classScopeKind_ = ScopeKind::Module;
990
991
  public:
992
    // Data is public because it is created by the frontend. See
993
    // Parser<FullParseHandler>::newModuleScopeData.
994
    struct Data : public TopLevelScopeData
995
    {
996
        // The module of the scope.
997
        GCPtr<ModuleObject*> module = {};
998
999
        // Bindings are sorted by kind.
1000
        //
1001
        // imports - [0, varStart)
1002
        //    vars - [varStart, letStart)
1003
        //    lets - [letStart, constStart)
1004
        //  consts - [constStart, length)
1005
        uint32_t varStart = 0;
1006
        uint32_t letStart = 0;
1007
        uint32_t constStart = 0;
1008
        uint32_t length = 0;
1009
1010
        // Frame slots [0, nextFrameSlot) are live when this is the innermost
1011
        // scope.
1012
        uint32_t nextFrameSlot = 0;
1013
1014
        // The array of tagged JSAtom* names, allocated beyond the end of the
1015
        // struct.
1016
        TrailingNamesArray trailingNames;
1017
1018
0
        explicit Data(size_t nameCount) : trailingNames(nameCount) {}
1019
        Data() = delete;
1020
1021
        void trace(JSTracer* trc);
1022
        Zone* zone() const;
1023
    };
1024
1025
    static ModuleScope* create(JSContext* cx, Handle<Data*> data,
1026
                               Handle<ModuleObject*> module, HandleScope enclosing);
1027
1028
  private:
1029
    static ModuleScope* createWithData(JSContext* cx, MutableHandle<UniquePtr<Data>> data,
1030
                                       Handle<ModuleObject*> module, HandleScope enclosing);
1031
1032
0
    Data& data() {
1033
0
        return *static_cast<Data*>(data_);
1034
0
    }
1035
1036
0
    const Data& data() const {
1037
0
        return *static_cast<Data*>(data_);
1038
0
    }
1039
1040
  public:
1041
0
    uint32_t nextFrameSlot() const {
1042
0
        return data().nextFrameSlot;
1043
0
    }
1044
1045
0
    ModuleObject* module() const {
1046
0
        return data().module;
1047
0
    }
1048
1049
    JSScript* script() const;
1050
1051
0
    void setTopLevelPrivate(void* value) {
1052
0
        data().privateData = value;
1053
0
    }
1054
1055
0
    void* topLevelPrivate() const {
1056
0
        return data().privateData;
1057
0
    }
1058
1059
    static Shape* getEmptyEnvironmentShape(JSContext* cx);
1060
};
1061
1062
class WasmInstanceScope : public Scope
1063
{
1064
    friend class BindingIter;
1065
    friend class Scope;
1066
    friend class GCMarker;
1067
    static const ScopeKind classScopeKind_ = ScopeKind::WasmInstance;
1068
1069
  public:
1070
    struct Data : public BaseScopeData
1071
    {
1072
        uint32_t memoriesStart = 0;
1073
        uint32_t globalsStart = 0;
1074
        uint32_t length = 0;
1075
        uint32_t nextFrameSlot = 0;
1076
1077
        // The wasm instance of the scope.
1078
        GCPtr<WasmInstanceObject*> instance = {};
1079
1080
        TrailingNamesArray trailingNames;
1081
1082
0
        explicit Data(size_t nameCount) : trailingNames(nameCount) {}
1083
        Data() = delete;
1084
1085
        void trace(JSTracer* trc);
1086
    };
1087
1088
    static WasmInstanceScope* create(JSContext* cx, WasmInstanceObject* instance);
1089
1090
  private:
1091
0
    Data& data() {
1092
0
        return *static_cast<Data*>(data_);
1093
0
    }
1094
1095
0
    const Data& data() const {
1096
0
        return *static_cast<Data*>(data_);
1097
0
    }
1098
1099
  public:
1100
0
    WasmInstanceObject* instance() const {
1101
0
        return data().instance;
1102
0
    }
1103
1104
0
    uint32_t memoriesStart() const {
1105
0
        return data().memoriesStart;
1106
0
    }
1107
1108
0
    uint32_t globalsStart() const {
1109
0
        return data().globalsStart;
1110
0
    }
1111
1112
0
    uint32_t namesCount() const {
1113
0
        return data().length;
1114
0
    }
1115
1116
    static Shape* getEmptyEnvironmentShape(JSContext* cx);
1117
};
1118
1119
// Scope corresponding to the wasm function. A WasmFunctionScope is used by
1120
// Debugger only, and not for wasm execution.
1121
//
1122
class WasmFunctionScope : public Scope
1123
{
1124
    friend class BindingIter;
1125
    friend class Scope;
1126
    friend class GCMarker;
1127
    static const ScopeKind classScopeKind_ = ScopeKind::WasmFunction;
1128
1129
  public:
1130
    struct Data : public BaseScopeData
1131
    {
1132
        uint32_t length = 0;
1133
        uint32_t nextFrameSlot = 0;
1134
        uint32_t funcIndex = 0;
1135
1136
        TrailingNamesArray trailingNames;
1137
1138
0
        explicit Data(size_t nameCount) : trailingNames(nameCount) {}
1139
        Data() = delete;
1140
1141
        void trace(JSTracer* trc);
1142
    };
1143
1144
    static WasmFunctionScope* create(JSContext* cx, HandleScope enclosing, uint32_t funcIndex);
1145
1146
  private:
1147
0
    Data& data() {
1148
0
        return *static_cast<Data*>(data_);
1149
0
    }
1150
1151
0
    const Data& data() const {
1152
0
        return *static_cast<Data*>(data_);
1153
0
    }
1154
1155
  public:
1156
0
    uint32_t funcIndex() const {
1157
0
        return data().funcIndex;
1158
0
    }
1159
1160
    static Shape* getEmptyEnvironmentShape(JSContext* cx);
1161
};
1162
1163
//
1164
// An iterator for a Scope's bindings. This is the source of truth for frame
1165
// and environment object layout.
1166
//
1167
// It may be placed in GC containers; for example:
1168
//
1169
//   for (Rooted<BindingIter> bi(cx, BindingIter(scope)); bi; bi++) {
1170
//     use(bi);
1171
//     SomeMayGCOperation();
1172
//     use(bi);
1173
//   }
1174
//
1175
class BindingIter
1176
{
1177
  protected:
1178
    // Bindings are sorted by kind. Because different Scopes have differently
1179
    // laid out Data for packing, BindingIter must handle all binding kinds.
1180
    //
1181
    // Kind ranges:
1182
    //
1183
    //            imports - [0, positionalFormalStart)
1184
    // positional formals - [positionalFormalStart, nonPositionalFormalStart)
1185
    //      other formals - [nonPositionalParamStart, varStart)
1186
    //               vars - [varStart, letStart)
1187
    //               lets - [letStart, constStart)
1188
    //             consts - [constStart, length)
1189
    //
1190
    // Access method when not closed over:
1191
    //
1192
    //            imports - name
1193
    // positional formals - argument slot
1194
    //      other formals - frame slot
1195
    //               vars - frame slot
1196
    //               lets - frame slot
1197
    //             consts - frame slot
1198
    //
1199
    // Access method when closed over:
1200
    //
1201
    //            imports - name
1202
    // positional formals - environment slot or name
1203
    //      other formals - environment slot or name
1204
    //               vars - environment slot or name
1205
    //               lets - environment slot or name
1206
    //             consts - environment slot or name
1207
    MOZ_INIT_OUTSIDE_CTOR uint32_t positionalFormalStart_;
1208
    MOZ_INIT_OUTSIDE_CTOR uint32_t nonPositionalFormalStart_;
1209
    MOZ_INIT_OUTSIDE_CTOR uint32_t varStart_;
1210
    MOZ_INIT_OUTSIDE_CTOR uint32_t letStart_;
1211
    MOZ_INIT_OUTSIDE_CTOR uint32_t constStart_;
1212
    MOZ_INIT_OUTSIDE_CTOR uint32_t length_;
1213
1214
    MOZ_INIT_OUTSIDE_CTOR uint32_t index_;
1215
1216
    enum Flags : uint8_t {
1217
        CannotHaveSlots = 0,
1218
        CanHaveArgumentSlots = 1 << 0,
1219
        CanHaveFrameSlots = 1 << 1,
1220
        CanHaveEnvironmentSlots = 1 << 2,
1221
1222
        // See comment in settle below.
1223
        HasFormalParameterExprs = 1 << 3,
1224
        IgnoreDestructuredFormalParameters = 1 << 4,
1225
1226
        // Truly I hate named lambdas.
1227
        IsNamedLambda = 1 << 5
1228
    };
1229
1230
    static const uint8_t CanHaveSlotsMask = 0x7;
1231
1232
    MOZ_INIT_OUTSIDE_CTOR uint8_t flags_;
1233
    MOZ_INIT_OUTSIDE_CTOR uint16_t argumentSlot_;
1234
    MOZ_INIT_OUTSIDE_CTOR uint32_t frameSlot_;
1235
    MOZ_INIT_OUTSIDE_CTOR uint32_t environmentSlot_;
1236
1237
    MOZ_INIT_OUTSIDE_CTOR BindingName* names_;
1238
1239
    void init(uint32_t positionalFormalStart, uint32_t nonPositionalFormalStart,
1240
              uint32_t varStart, uint32_t letStart, uint32_t constStart,
1241
              uint8_t flags, uint32_t firstFrameSlot, uint32_t firstEnvironmentSlot,
1242
              BindingName* names, uint32_t length)
1243
7.04k
    {
1244
7.04k
        positionalFormalStart_ = positionalFormalStart;
1245
7.04k
        nonPositionalFormalStart_ = nonPositionalFormalStart;
1246
7.04k
        varStart_ = varStart;
1247
7.04k
        letStart_ = letStart;
1248
7.04k
        constStart_ = constStart;
1249
7.04k
        length_ = length;
1250
7.04k
        index_ = 0;
1251
7.04k
        flags_ = flags;
1252
7.04k
        argumentSlot_ = 0;
1253
7.04k
        frameSlot_ = firstFrameSlot;
1254
7.04k
        environmentSlot_ = firstEnvironmentSlot;
1255
7.04k
        names_ = names;
1256
7.04k
1257
7.04k
        settle();
1258
7.04k
    }
1259
1260
    void init(LexicalScope::Data& data, uint32_t firstFrameSlot, uint8_t flags);
1261
    void init(FunctionScope::Data& data, uint8_t flags);
1262
    void init(VarScope::Data& data, uint32_t firstFrameSlot);
1263
    void init(GlobalScope::Data& data);
1264
    void init(EvalScope::Data& data, bool strict);
1265
    void init(ModuleScope::Data& data);
1266
    void init(WasmInstanceScope::Data& data);
1267
    void init(WasmFunctionScope::Data& data);
1268
1269
9.72k
    bool hasFormalParameterExprs() const {
1270
9.72k
        return flags_ & HasFormalParameterExprs;
1271
9.72k
    }
1272
1273
24.9k
    bool ignoreDestructuredFormalParameters() const {
1274
24.9k
        return flags_ & IgnoreDestructuredFormalParameters;
1275
24.9k
    }
1276
1277
162
    bool isNamedLambda() const {
1278
162
        return flags_ & IsNamedLambda;
1279
162
    }
1280
1281
17.9k
    void increment() {
1282
17.9k
        MOZ_ASSERT(!done());
1283
17.9k
        if (flags_ & CanHaveSlotsMask) {
1284
17.9k
            if (canHaveArgumentSlots()) {
1285
15.4k
                if (index_ < nonPositionalFormalStart_) {
1286
7.08k
                    MOZ_ASSERT(index_ >= positionalFormalStart_);
1287
7.08k
                    argumentSlot_++;
1288
7.08k
                }
1289
15.4k
            }
1290
17.9k
            if (closedOver()) {
1291
761
                // Imports must not be given known slots. They are
1292
761
                // indirect bindings.
1293
761
                MOZ_ASSERT(kind() != BindingKind::Import);
1294
761
                MOZ_ASSERT(canHaveEnvironmentSlots());
1295
761
                environmentSlot_++;
1296
17.1k
            } else if (canHaveFrameSlots()) {
1297
17.0k
                // Usually positional formal parameters don't have frame
1298
17.0k
                // slots, except when there are parameter expressions, in
1299
17.0k
                // which case they act like lets.
1300
17.0k
                if (index_ >= nonPositionalFormalStart_ || (hasFormalParameterExprs() && name())) {
1301
10.4k
                    frameSlot_++;
1302
10.4k
                }
1303
17.0k
            }
1304
17.9k
        }
1305
17.9k
        index_++;
1306
17.9k
    }
1307
1308
24.9k
    void settle() {
1309
24.9k
        if (ignoreDestructuredFormalParameters()) {
1310
18.0k
            while (!done() && !name()) {
1311
0
                increment();
1312
0
            }
1313
18.0k
        }
1314
24.9k
    }
1315
1316
  public:
1317
    explicit BindingIter(Scope* scope);
1318
    explicit BindingIter(JSScript* script);
1319
1320
750
    BindingIter(LexicalScope::Data& data, uint32_t firstFrameSlot, bool isNamedLambda) {
1321
750
        init(data, firstFrameSlot, isNamedLambda ? IsNamedLambda : 0);
1322
750
    }
1323
1324
2.97k
    BindingIter(FunctionScope::Data& data, bool hasParameterExprs) {
1325
2.97k
        init(data,
1326
2.97k
             IgnoreDestructuredFormalParameters |
1327
2.97k
             (hasParameterExprs ? HasFormalParameterExprs : 0));
1328
2.97k
    }
1329
1330
82
    BindingIter(VarScope::Data& data, uint32_t firstFrameSlot) {
1331
82
        init(data, firstFrameSlot);
1332
82
    }
1333
1334
4
    explicit BindingIter(GlobalScope::Data& data) {
1335
4
        init(data);
1336
4
    }
1337
1338
0
    explicit BindingIter(ModuleScope::Data& data) {
1339
0
        init(data);
1340
0
    }
1341
1342
0
    explicit BindingIter(WasmFunctionScope::Data& data) {
1343
0
        init(data);
1344
0
    }
1345
1346
0
    BindingIter(EvalScope::Data& data, bool strict) {
1347
0
        init(data, strict);
1348
0
    }
1349
1350
    explicit BindingIter(const BindingIter& bi) = default;
1351
1352
42.9k
    bool done() const {
1353
42.9k
        return index_ == length_;
1354
42.9k
    }
1355
1356
24.8k
    explicit operator bool() const {
1357
24.8k
        return !done();
1358
24.8k
    }
1359
1360
17.9k
    void operator++(int) {
1361
17.9k
        increment();
1362
17.9k
        settle();
1363
17.9k
    }
1364
1365
0
    bool isLast() const {
1366
0
        MOZ_ASSERT(!done());
1367
0
        return index_ + 1 == length_;
1368
0
    }
1369
1370
20.2k
    bool canHaveArgumentSlots() const {
1371
20.2k
        return flags_ & CanHaveArgumentSlots;
1372
20.2k
    }
1373
1374
24.3k
    bool canHaveFrameSlots() const {
1375
24.3k
        return flags_ & CanHaveFrameSlots;
1376
24.3k
    }
1377
1378
0
    bool canHaveEnvironmentSlots() const {
1379
0
        return flags_ & CanHaveEnvironmentSlots;
1380
0
    }
1381
1382
30.4k
    JSAtom* name() const {
1383
30.4k
        MOZ_ASSERT(!done());
1384
30.4k
        return names_[index_].name();
1385
30.4k
    }
1386
1387
28.5k
    bool closedOver() const {
1388
28.5k
        MOZ_ASSERT(!done());
1389
28.5k
        return names_[index_].closedOver();
1390
28.5k
    }
1391
1392
8.06k
    BindingLocation location() const {
1393
8.06k
        MOZ_ASSERT(!done());
1394
8.06k
        if (!(flags_ & CanHaveSlotsMask)) {
1395
15
            return BindingLocation::Global();
1396
15
        }
1397
8.04k
        if (index_ < positionalFormalStart_) {
1398
0
            return BindingLocation::Import();
1399
0
        }
1400
8.04k
        if (closedOver()) {
1401
581
            MOZ_ASSERT(canHaveEnvironmentSlots());
1402
581
            return BindingLocation::Environment(environmentSlot_);
1403
581
        }
1404
7.46k
        if (index_ < nonPositionalFormalStart_ && canHaveArgumentSlots()) {
1405
2.13k
            return BindingLocation::Argument(argumentSlot_);
1406
2.13k
        }
1407
5.33k
        if (canHaveFrameSlots()) {
1408
5.29k
            return BindingLocation::Frame(frameSlot_);
1409
5.29k
        }
1410
39
        MOZ_ASSERT(isNamedLambda());
1411
39
        return BindingLocation::NamedLambdaCallee();
1412
39
    }
1413
1414
7.87k
    BindingKind kind() const {
1415
7.87k
        MOZ_ASSERT(!done());
1416
7.87k
        if (index_ < positionalFormalStart_) {
1417
0
            return BindingKind::Import;
1418
0
        }
1419
7.87k
        if (index_ < varStart_) {
1420
2.66k
            // When the parameter list has expressions, the parameters act
1421
2.66k
            // like lexical bindings and have TDZ.
1422
2.66k
            if (hasFormalParameterExprs()) {
1423
379
                return BindingKind::Let;
1424
379
            }
1425
2.28k
            return BindingKind::FormalParameter;
1426
2.28k
        }
1427
5.21k
        if (index_ < letStart_) {
1428
4.56k
            return BindingKind::Var;
1429
4.56k
        }
1430
652
        if (index_ < constStart_) {
1431
490
            return BindingKind::Let;
1432
490
        }
1433
162
        if (isNamedLambda()) {
1434
39
            return BindingKind::NamedLambdaCallee;
1435
39
        }
1436
123
        return BindingKind::Const;
1437
123
    }
1438
1439
15
    bool isTopLevelFunction() const {
1440
15
        MOZ_ASSERT(!done());
1441
15
        bool result = names_[index_].isTopLevelFunction();
1442
15
        MOZ_ASSERT_IF(result, kind() == BindingKind::Var);
1443
15
        return result;
1444
15
    }
1445
1446
0
    bool hasArgumentSlot() const {
1447
0
        MOZ_ASSERT(!done());
1448
0
        if (hasFormalParameterExprs()) {
1449
0
            return false;
1450
0
        }
1451
0
        return index_ >= positionalFormalStart_ && index_ < nonPositionalFormalStart_;
1452
0
    }
1453
1454
312
    uint16_t argumentSlot() const {
1455
312
        MOZ_ASSERT(canHaveArgumentSlots());
1456
312
        return mozilla::AssertedCast<uint16_t>(index_);
1457
312
    }
1458
1459
10.9k
    uint32_t nextFrameSlot() const {
1460
10.9k
        MOZ_ASSERT(canHaveFrameSlots());
1461
10.9k
        return frameSlot_;
1462
10.9k
    }
1463
1464
9.28k
    uint32_t nextEnvironmentSlot() const {
1465
9.28k
        MOZ_ASSERT(canHaveEnvironmentSlots());
1466
9.28k
        return environmentSlot_;
1467
9.28k
    }
1468
1469
    void trace(JSTracer* trc);
1470
};
1471
1472
void DumpBindings(JSContext* cx, Scope* scope);
1473
JSAtom* FrameSlotName(JSScript* script, jsbytecode* pc);
1474
1475
//
1476
// A refinement BindingIter that only iterates over positional formal
1477
// parameters of a function.
1478
//
1479
class PositionalFormalParameterIter : public BindingIter
1480
{
1481
4.19k
    void settle() {
1482
4.19k
        if (index_ >= nonPositionalFormalStart_) {
1483
1.52k
            index_ = length_;
1484
1.52k
        }
1485
4.19k
    }
1486
1487
  public:
1488
    explicit PositionalFormalParameterIter(JSScript* script);
1489
1490
2.58k
    void operator++(int) {
1491
2.58k
        BindingIter::operator++(1);
1492
2.58k
        settle();
1493
2.58k
    }
1494
1495
0
    bool isDestructured() const {
1496
0
        return !name();
1497
0
    }
1498
};
1499
1500
//
1501
// Iterator for walking the scope chain.
1502
//
1503
// It may be placed in GC containers; for example:
1504
//
1505
//   for (Rooted<ScopeIter> si(cx, ScopeIter(scope)); si; si++) {
1506
//     use(si);
1507
//     SomeMayGCOperation();
1508
//     use(si);
1509
//   }
1510
//
1511
class MOZ_STACK_CLASS ScopeIter
1512
{
1513
    Scope* scope_;
1514
1515
  public:
1516
    explicit ScopeIter(Scope* scope)
1517
      : scope_(scope)
1518
200
    { }
1519
1520
    explicit ScopeIter(JSScript* script);
1521
1522
    explicit ScopeIter(const ScopeIter& si)
1523
      : scope_(si.scope_)
1524
0
    { }
1525
1526
385
    bool done() const {
1527
385
        return !scope_;
1528
385
    }
1529
1530
42
    explicit operator bool() const {
1531
42
        return !done();
1532
42
    }
1533
1534
181
    void operator++(int) {
1535
181
        MOZ_ASSERT(!done());
1536
181
        scope_ = scope_->enclosing();
1537
181
    }
1538
1539
1.14k
    Scope* scope() const {
1540
1.14k
        MOZ_ASSERT(!done());
1541
1.14k
        return scope_;
1542
1.14k
    }
1543
1544
232
    ScopeKind kind() const {
1545
232
        MOZ_ASSERT(!done());
1546
232
        return scope_->kind();
1547
232
    }
1548
1549
    // Returns the shape of the environment if it is known. It is possible to
1550
    // hasSyntacticEnvironment and to have no known shape, e.g., eval.
1551
3
    Shape* environmentShape() const {
1552
3
        return scope()->environmentShape();
1553
3
    }
1554
1555
    // Returns whether this scope has a syntactic environment (i.e., an
1556
    // Environment that isn't a non-syntactic With or NonSyntacticVariables)
1557
    // on the environment chain.
1558
    bool hasSyntacticEnvironment() const;
1559
1560
0
    void trace(JSTracer* trc) {
1561
0
        if (scope_) {
1562
0
            TraceRoot(trc, &scope_, "scope iter scope");
1563
0
        }
1564
0
    }
1565
};
1566
1567
//
1568
// Specializations of Rooted containers for the iterators.
1569
//
1570
1571
template <typename Wrapper>
1572
class WrappedPtrOperations<BindingIter, Wrapper>
1573
{
1574
58
    const BindingIter& iter() const { return static_cast<const Wrapper*>(this)->get(); }
1575
1576
  public:
1577
31
    bool done() const { return iter().done(); }
1578
31
    explicit operator bool() const { return !done(); }
1579
    bool isLast() const { return iter().isLast(); }
1580
    bool canHaveArgumentSlots() const { return iter().canHaveArgumentSlots(); }
1581
    bool canHaveFrameSlots() const { return iter().canHaveFrameSlots(); }
1582
    bool canHaveEnvironmentSlots() const { return iter().canHaveEnvironmentSlots(); }
1583
15
    JSAtom* name() const { return iter().name(); }
1584
0
    bool closedOver() const { return iter().closedOver(); }
1585
0
    BindingLocation location() const { return iter().location(); }
1586
12
    BindingKind kind() const { return iter().kind(); }
1587
0
    bool isTopLevelFunction() const { return iter().isTopLevelFunction(); }
1588
    bool hasArgumentSlot() const { return iter().hasArgumentSlot(); }
1589
    uint16_t argumentSlot() const { return iter().argumentSlot(); }
1590
    uint32_t nextFrameSlot() const { return iter().nextFrameSlot(); }
1591
    uint32_t nextEnvironmentSlot() const { return iter().nextEnvironmentSlot(); }
1592
};
1593
1594
template <typename Wrapper>
1595
class MutableWrappedPtrOperations<BindingIter, Wrapper>
1596
  : public WrappedPtrOperations<BindingIter, Wrapper>
1597
{
1598
15
    BindingIter& iter() { return static_cast<Wrapper*>(this)->get(); }
1599
1600
  public:
1601
15
    void operator++(int) { iter().operator++(1); }
1602
};
1603
1604
template <typename Wrapper>
1605
class WrappedPtrOperations<ScopeIter, Wrapper>
1606
{
1607
1.59k
    const ScopeIter& iter() const { return static_cast<const Wrapper*>(this)->get(); }
1608
1609
  public:
1610
343
    bool done() const { return iter().done(); }
1611
343
    explicit operator bool() const { return !done(); }
1612
884
    Scope* scope() const { return iter().scope(); }
1613
189
    ScopeKind kind() const { return iter().kind(); }
1614
    Shape* environmentShape() const { return iter().environmentShape(); }
1615
174
    bool hasSyntacticEnvironment() const { return iter().hasSyntacticEnvironment(); }
1616
};
1617
1618
template <typename Wrapper>
1619
class MutableWrappedPtrOperations<ScopeIter, Wrapper>
1620
  : public WrappedPtrOperations<ScopeIter, Wrapper>
1621
{
1622
179
    ScopeIter& iter() { return static_cast<Wrapper*>(this)->get(); }
1623
1624
  public:
1625
179
    void operator++(int) { iter().operator++(1); }
1626
};
1627
1628
} // namespace js
1629
1630
namespace JS {
1631
1632
template <>
1633
struct GCPolicy<js::ScopeKind> : public IgnoreGCPolicy<js::ScopeKind>
1634
{ };
1635
1636
template <typename T>
1637
struct ScopeDataGCPolicy : public NonGCPointerPolicy<T> {};
1638
1639
#define DEFINE_SCOPE_DATA_GCPOLICY(Data)                        \
1640
    template <>                                                 \
1641
    struct MapTypeToRootKind<Data*> {                           \
1642
        static const RootKind kind = RootKind::Traceable;       \
1643
    };                                                          \
1644
    template <>                                                 \
1645
    struct GCPolicy<Data*> : public ScopeDataGCPolicy<Data*>    \
1646
    { }
1647
1648
DEFINE_SCOPE_DATA_GCPOLICY(js::LexicalScope::Data);
1649
DEFINE_SCOPE_DATA_GCPOLICY(js::FunctionScope::Data);
1650
DEFINE_SCOPE_DATA_GCPOLICY(js::VarScope::Data);
1651
DEFINE_SCOPE_DATA_GCPOLICY(js::GlobalScope::Data);
1652
DEFINE_SCOPE_DATA_GCPOLICY(js::EvalScope::Data);
1653
DEFINE_SCOPE_DATA_GCPOLICY(js::ModuleScope::Data);
1654
DEFINE_SCOPE_DATA_GCPOLICY(js::WasmFunctionScope::Data);
1655
1656
#undef DEFINE_SCOPE_DATA_GCPOLICY
1657
1658
// Scope data that contain GCPtrs must use the correct DeletePolicy.
1659
1660
template <>
1661
struct DeletePolicy<js::FunctionScope::Data>
1662
  : public js::GCManagedDeletePolicy<js::FunctionScope::Data>
1663
{};
1664
1665
template <>
1666
struct DeletePolicy<js::ModuleScope::Data>
1667
  : public js::GCManagedDeletePolicy<js::ModuleScope::Data>
1668
{};
1669
1670
template <>
1671
struct DeletePolicy<js::WasmInstanceScope::Data>
1672
  : public js::GCManagedDeletePolicy<js::WasmInstanceScope::Data>
1673
{ };
1674
1675
namespace ubi {
1676
1677
template <>
1678
class Concrete<js::Scope> : TracerConcrete<js::Scope>
1679
{
1680
  protected:
1681
0
    explicit Concrete(js::Scope* ptr) : TracerConcrete<js::Scope>(ptr) { }
1682
1683
  public:
1684
0
    static void construct(void* storage, js::Scope* ptr) {
1685
0
        new (storage) Concrete(ptr);
1686
0
    }
1687
1688
0
    CoarseType coarseType() const final { return CoarseType::Script; }
1689
1690
    Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
1691
1692
0
    const char16_t* typeName() const override { return concreteTypeName; }
1693
    static const char16_t concreteTypeName[];
1694
};
1695
1696
} // namespace ubi
1697
} // namespace JS
1698
1699
#endif // vm_Scope_h