1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
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 frontend_SharedContext_h
8 #define frontend_SharedContext_h
9
10 #include "mozilla/Assertions.h"
11 #include "mozilla/Attributes.h"
12 #include "mozilla/Maybe.h"
13
14 #include "jstypes.h"
15
16 #include "frontend/AbstractScopePtr.h"
17 #include "frontend/FunctionSyntaxKind.h" // FunctionSyntaxKind
18 #include "frontend/ParseNode.h"
19 #include "frontend/Stencil.h"
20 #include "vm/FunctionFlags.h" // js::FunctionFlags
21 #include "vm/GeneratorAndAsyncKind.h" // js::GeneratorKind, js::FunctionAsyncKind
22 #include "vm/JSFunction.h"
23 #include "vm/JSScript.h"
24 #include "vm/Scope.h"
25 #include "vm/SharedStencil.h"
26
27 namespace js {
28 namespace frontend {
29
30 class ParseContext;
31 struct ScopeContext;
32
33 enum class StatementKind : uint8_t {
34 Label,
35 Block,
36 If,
37 Switch,
38 With,
39 Catch,
40 Try,
41 Finally,
42 ForLoopLexicalHead,
43 ForLoop,
44 ForInLoop,
45 ForOfLoop,
46 DoLoop,
47 WhileLoop,
48 Class,
49
50 // Used only by BytecodeEmitter.
51 Spread,
52 YieldStar,
53 };
54
StatementKindIsLoop(StatementKind kind)55 static inline bool StatementKindIsLoop(StatementKind kind) {
56 return kind == StatementKind::ForLoop || kind == StatementKind::ForInLoop ||
57 kind == StatementKind::ForOfLoop || kind == StatementKind::DoLoop ||
58 kind == StatementKind::WhileLoop || kind == StatementKind::Spread ||
59 kind == StatementKind::YieldStar;
60 }
61
StatementKindIsUnlabeledBreakTarget(StatementKind kind)62 static inline bool StatementKindIsUnlabeledBreakTarget(StatementKind kind) {
63 return StatementKindIsLoop(kind) || kind == StatementKind::Switch;
64 }
65
66 // List of directives that may be encountered in a Directive Prologue
67 // (ES5 15.1).
68 class Directives {
69 bool strict_;
70 bool asmJS_;
71
72 public:
Directives(bool strict)73 explicit Directives(bool strict) : strict_(strict), asmJS_(false) {}
74 explicit Directives(ParseContext* parent);
75
setStrict()76 void setStrict() { strict_ = true; }
strict()77 bool strict() const { return strict_; }
78
setAsmJS()79 void setAsmJS() { asmJS_ = true; }
asmJS()80 bool asmJS() const { return asmJS_; }
81
82 Directives& operator=(Directives rhs) {
83 strict_ = rhs.strict_;
84 asmJS_ = rhs.asmJS_;
85 return *this;
86 }
87 bool operator==(const Directives& rhs) const {
88 return strict_ == rhs.strict_ && asmJS_ == rhs.asmJS_;
89 }
90 bool operator!=(const Directives& rhs) const { return !(*this == rhs); }
91 };
92
93 // The kind of this-binding for the current scope. Note that arrow functions
94 // have a lexical this-binding so their ThisBinding is the same as the
95 // ThisBinding of their enclosing scope and can be any value. Derived
96 // constructors require TDZ checks when accessing the binding.
97 enum class ThisBinding : uint8_t {
98 Global,
99 Module,
100 Function,
101 DerivedConstructor
102 };
103
104 class GlobalSharedContext;
105 class EvalSharedContext;
106 class ModuleSharedContext;
107
108 #define FLAG_GETTER_SETTER(enumName, enumEntry, lowerName, name) \
109 public: \
110 bool lowerName() const { return hasFlag(enumName::enumEntry); } \
111 void set##name() { setFlag(enumName::enumEntry); } \
112 void set##name(bool b) { setFlag(enumName::enumEntry, b); }
113
114 #define IMMUTABLE_FLAG_GETTER_SETTER(lowerName, name) \
115 FLAG_GETTER_SETTER(ImmutableFlags, name, lowerName, name)
116
117 /*
118 * The struct SharedContext is part of the current parser context (see
119 * ParseContext). It stores information that is reused between the parser and
120 * the bytecode emitter.
121 */
122 class SharedContext {
123 public:
124 JSContext* const cx_;
125
126 protected:
127 CompilationInfo& compilationInfo_;
128
129 // See: BaseScript::immutableFlags_
130 ImmutableScriptFlags immutableFlags_ = {};
131
132 public:
133 // The location of this script in the source. Note that the value here differs
134 // from the final BaseScript for the case of standalone functions.
135 SourceExtent extent = {};
136
137 protected:
138 // See: ThisBinding
139 ThisBinding thisBinding_ = ThisBinding::Global;
140
141 // These flags do not have corresponding script flags and may be inherited
142 // from the scope chain in the case of eval and arrows.
143 bool allowNewTarget_ : 1;
144 bool allowSuperProperty_ : 1;
145 bool allowSuperCall_ : 1;
146 bool allowArguments_ : 1;
147 bool inWith_ : 1;
148
149 // See `strict()` below.
150 bool localStrict : 1;
151
152 // True if "use strict"; appears in the body instead of being inherited.
153 bool hasExplicitUseStrict_ : 1;
154
155 // End of fields.
156
157 enum class Kind : uint8_t { FunctionBox, Global, Eval, Module };
158
159 // Alias enum into SharedContext
160 using ImmutableFlags = ImmutableScriptFlagsEnum;
161
hasFlag(ImmutableFlags flag)162 MOZ_MUST_USE bool hasFlag(ImmutableFlags flag) const {
163 return immutableFlags_.hasFlag(flag);
164 }
165 void setFlag(ImmutableFlags flag, bool b = true) {
166 immutableFlags_.setFlag(flag, b);
167 }
168
169 public:
170 SharedContext(JSContext* cx, Kind kind, CompilationInfo& compilationInfo,
171 Directives directives, SourceExtent extent);
172
173 // If this is the outermost SharedContext, the Scope that encloses
174 // it. Otherwise nullptr.
175 virtual Scope* compilationEnclosingScope() const = 0;
176
IMMUTABLE_FLAG_GETTER_SETTER(isForEval,IsForEval)177 IMMUTABLE_FLAG_GETTER_SETTER(isForEval, IsForEval)
178 IMMUTABLE_FLAG_GETTER_SETTER(isModule, IsModule)
179 IMMUTABLE_FLAG_GETTER_SETTER(isFunction, IsFunction)
180 IMMUTABLE_FLAG_GETTER_SETTER(selfHosted, SelfHosted)
181 IMMUTABLE_FLAG_GETTER_SETTER(forceStrict, ForceStrict)
182 IMMUTABLE_FLAG_GETTER_SETTER(hasNonSyntacticScope, HasNonSyntacticScope)
183 IMMUTABLE_FLAG_GETTER_SETTER(noScriptRval, NoScriptRval)
184 IMMUTABLE_FLAG_GETTER_SETTER(treatAsRunOnce, TreatAsRunOnce)
185 // Strict: custom logic below
186 IMMUTABLE_FLAG_GETTER_SETTER(hasModuleGoal, HasModuleGoal)
187 IMMUTABLE_FLAG_GETTER_SETTER(hasInnerFunctions, HasInnerFunctions)
188 IMMUTABLE_FLAG_GETTER_SETTER(hasDirectEval, HasDirectEval)
189 IMMUTABLE_FLAG_GETTER_SETTER(bindingsAccessedDynamically,
190 BindingsAccessedDynamically)
191 IMMUTABLE_FLAG_GETTER_SETTER(hasCallSiteObj, HasCallSiteObj)
192
193 bool isFunctionBox() const { return isFunction(); }
194 inline FunctionBox* asFunctionBox();
isModuleContext()195 bool isModuleContext() const { return isModule(); }
196 inline ModuleSharedContext* asModuleContext();
isGlobalContext()197 bool isGlobalContext() const {
198 return !(isFunction() || isModule() || isForEval());
199 }
200 inline GlobalSharedContext* asGlobalContext();
isEvalContext()201 bool isEvalContext() const { return isForEval(); }
202 inline EvalSharedContext* asEvalContext();
203
isTopLevelContext()204 bool isTopLevelContext() const { return !isFunction(); }
205
compilationInfo()206 CompilationInfo& compilationInfo() const { return compilationInfo_; }
207
thisBinding()208 ThisBinding thisBinding() const { return thisBinding_; }
hasFunctionThisBinding()209 bool hasFunctionThisBinding() const {
210 return thisBinding() == ThisBinding::Function ||
211 thisBinding() == ThisBinding::DerivedConstructor;
212 }
needsThisTDZChecks()213 bool needsThisTDZChecks() const {
214 return thisBinding() == ThisBinding::DerivedConstructor;
215 }
216
isSelfHosted()217 bool isSelfHosted() const { return selfHosted(); }
allowNewTarget()218 bool allowNewTarget() const { return allowNewTarget_; }
allowSuperProperty()219 bool allowSuperProperty() const { return allowSuperProperty_; }
allowSuperCall()220 bool allowSuperCall() const { return allowSuperCall_; }
allowArguments()221 bool allowArguments() const { return allowArguments_; }
inWith()222 bool inWith() const { return inWith_; }
223
hasExplicitUseStrict()224 bool hasExplicitUseStrict() const { return hasExplicitUseStrict_; }
setExplicitUseStrict()225 void setExplicitUseStrict() { hasExplicitUseStrict_ = true; }
226
immutableFlags()227 ImmutableScriptFlags immutableFlags() { return immutableFlags_; }
228
229 inline bool allBindingsClosedOver();
230
231 // The ImmutableFlag tracks if the entire script is strict, while the
232 // localStrict flag indicates the current region (such as class body) should
233 // be treated as strict. The localStrict flag will always be reset to false
234 // before the end of the script.
strict()235 bool strict() const { return hasFlag(ImmutableFlags::Strict) || localStrict; }
setStrictScript()236 void setStrictScript() { setFlag(ImmutableFlags::Strict); }
setLocalStrictMode(bool strict)237 bool setLocalStrictMode(bool strict) {
238 bool retVal = localStrict;
239 localStrict = strict;
240 return retVal;
241 }
242 };
243
244 class MOZ_STACK_CLASS GlobalSharedContext : public SharedContext {
245 ScopeKind scopeKind_;
246
247 public:
248 Rooted<GlobalScope::Data*> bindings;
249
GlobalSharedContext(JSContext * cx,ScopeKind scopeKind,CompilationInfo & compilationInfo,Directives directives,SourceExtent extent)250 GlobalSharedContext(JSContext* cx, ScopeKind scopeKind,
251 CompilationInfo& compilationInfo, Directives directives,
252 SourceExtent extent)
253 : SharedContext(cx, Kind::Global, compilationInfo, directives, extent),
254 scopeKind_(scopeKind),
255 bindings(cx) {
256 MOZ_ASSERT(scopeKind == ScopeKind::Global ||
257 scopeKind == ScopeKind::NonSyntactic);
258 MOZ_ASSERT(thisBinding_ == ThisBinding::Global);
259 }
260
compilationEnclosingScope()261 Scope* compilationEnclosingScope() const override { return nullptr; }
262
scopeKind()263 ScopeKind scopeKind() const { return scopeKind_; }
264 };
265
asGlobalContext()266 inline GlobalSharedContext* SharedContext::asGlobalContext() {
267 MOZ_ASSERT(isGlobalContext());
268 return static_cast<GlobalSharedContext*>(this);
269 }
270
271 class MOZ_STACK_CLASS EvalSharedContext : public SharedContext {
272 RootedScope enclosingScope_;
273
274 public:
275 Rooted<EvalScope::Data*> bindings;
276
277 EvalSharedContext(JSContext* cx, CompilationInfo& compilationInfo,
278 Scope* enclosingScope, Directives directives,
279 SourceExtent extent);
280
compilationEnclosingScope()281 Scope* compilationEnclosingScope() const override { return enclosingScope_; }
282 };
283
asEvalContext()284 inline EvalSharedContext* SharedContext::asEvalContext() {
285 MOZ_ASSERT(isEvalContext());
286 return static_cast<EvalSharedContext*>(this);
287 }
288
289 enum class HasHeritage { No, Yes };
290 enum class TopLevelFunction { No, Yes };
291
292 class FunctionBox : public SharedContext {
293 friend struct GCThingList;
294
295 // The parser handles tracing the fields below via the FunctionBox linked
296 // list represented by |traceLink_|.
297 FunctionBox* traceLink_ = nullptr;
298
299 // This field is used for two purposes:
300 // * If this FunctionBox refers to the function being compiled, this field
301 // holds its enclosing scope, used for compilation.
302 // * If this FunctionBox refers to a lazy child of the function being
303 // compiled, this field holds the child's immediately enclosing scope.
304 // Once compilation succeeds, we will store it in the child's
305 // BaseScript. (Debugger may become confused if lazy scripts refer to
306 // partially initialized enclosing scopes, so we must avoid storing the
307 // scope in the BaseScript until compilation has completed
308 // successfully.)
309 AbstractScopePtr enclosingScope_ = {};
310
311 // Names from the named lambda scope, if a named lambda.
312 LexicalScope::Data* namedLambdaBindings_ = nullptr;
313
314 // Names from the function scope.
315 FunctionScope::Data* functionScopeBindings_ = nullptr;
316
317 // Names from the extra 'var' scope of the function, if the parameter list
318 // has expressions.
319 VarScope::Data* extraVarScopeBindings_ = nullptr;
320
321 // The explicit or implicit name of the function. The FunctionFlags indicate
322 // the kind of name.
323 JSAtom* atom_ = nullptr;
324
325 // Index into CompilationInfo::funcData, which contains the function
326 // information, either a JSFunction* (for a FunctionBox representing a real
327 // function) or a ScriptStencilBase.
328 size_t funcDataIndex_ = (size_t)(-1);
329
330 public:
331 // Back pointer used by asm.js for error messages.
332 FunctionNode* functionNode = nullptr;
333
334 // See: PrivateScriptData::fieldInitializers_
335 mozilla::Maybe<FieldInitializers> fieldInitializers = {};
336
337 FunctionFlags flags_ = {}; // See: FunctionFlags
338 uint16_t length = 0; // See: ImmutableScriptData::funLength
339 uint16_t nargs_ = 0; // JSFunction::nargs_
340
341 // True if bytecode will be emitted for this function in the current
342 // compilation.
343 bool emitBytecode : 1;
344
345 // This is set by the BytecodeEmitter of the enclosing script when a reference
346 // to this function is generated. This is also used to determine a hoisted
347 // function already is referenced by the bytecode.
348 bool wasEmitted : 1;
349
350 // This function should be marked as a singleton. It is expected to be defined
351 // at most once. This is a heuristic only and does not affect correctness.
352 bool isSingleton : 1;
353
354 // Need to emit a synthesized Annex B assignment
355 bool isAnnexB : 1;
356
357 // Track if we saw "use asm" and if we successfully validated.
358 bool useAsm : 1;
359 bool isAsmJSModule_ : 1;
360
361 // Analysis of parameter list
362 bool hasParameterExprs : 1;
363 bool hasDestructuringArgs : 1;
364 bool hasDuplicateParameters : 1;
365
366 // Arrow function with expression body like: `() => 1`.
367 bool hasExprBody_ : 1;
368
369 // Analysis for use in heuristics.
370 bool usesApply : 1; // Contains an f.apply() call
371 bool usesThis : 1; // Contains 'this'
372 bool usesReturn : 1; // Contains a 'return' statement
373
374 // End of fields.
375
376 FunctionBox(JSContext* cx, FunctionBox* traceListHead, SourceExtent extent,
377 CompilationInfo& compilationInfo, Directives directives,
378 GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
379 JSAtom* explicitName, FunctionFlags flags, size_t index);
380
381 JSFunction* createFunction(JSContext* cx);
382
383 MutableHandle<ScriptStencil> functionStencil() const;
384
385 bool hasFunctionStencil() const;
386 bool hasFunction() const;
387
388 #ifdef DEBUG
389 bool atomsAreKept();
390 #endif
391
namedLambdaBindings()392 MutableHandle<LexicalScope::Data*> namedLambdaBindings() {
393 MOZ_ASSERT(atomsAreKept());
394 return MutableHandle<LexicalScope::Data*>::fromMarkedLocation(
395 &namedLambdaBindings_);
396 }
397
functionScopeBindings()398 MutableHandle<FunctionScope::Data*> functionScopeBindings() {
399 MOZ_ASSERT(atomsAreKept());
400 return MutableHandle<FunctionScope::Data*>::fromMarkedLocation(
401 &functionScopeBindings_);
402 }
403
extraVarScopeBindings()404 MutableHandle<VarScope::Data*> extraVarScopeBindings() {
405 MOZ_ASSERT(atomsAreKept());
406 return MutableHandle<VarScope::Data*>::fromMarkedLocation(
407 &extraVarScopeBindings_);
408 }
409
410 void initFromLazyFunction(JSFunction* fun);
411
412 void initWithEnclosingScope(ScopeContext& scopeContext, Scope* enclosingScope,
413 FunctionFlags flags, FunctionSyntaxKind kind);
414
415 void initWithEnclosingParseContext(ParseContext* enclosing,
416 FunctionFlags flags,
417 FunctionSyntaxKind kind);
418
419 void setEnclosingScopeForInnerLazyFunction(
420 const AbstractScopePtr& enclosingScope);
421 void finish();
422
423 JSFunction* function() const;
424
425 // Initialize FunctionBox with a deferred allocation Function
initializeFunction(JSFunction * fun)426 void initializeFunction(JSFunction* fun) { clobberFunction(fun); }
427
428 void setAsmJSModule(JSFunction* function);
isAsmJSModule()429 bool isAsmJSModule() { return isAsmJSModule_; }
430
431 void clobberFunction(JSFunction* function);
432
compilationEnclosingScope()433 Scope* compilationEnclosingScope() const override {
434 // This is used when emitting code for the current FunctionBox and therefore
435 // the enclosingScope_ must have be set correctly during initalization.
436
437 MOZ_ASSERT(enclosingScope_);
438 return enclosingScope_.scope();
439 }
440
IMMUTABLE_FLAG_GETTER_SETTER(isAsync,IsAsync)441 IMMUTABLE_FLAG_GETTER_SETTER(isAsync, IsAsync)
442 IMMUTABLE_FLAG_GETTER_SETTER(isGenerator, IsGenerator)
443 IMMUTABLE_FLAG_GETTER_SETTER(funHasExtensibleScope, FunHasExtensibleScope)
444 IMMUTABLE_FLAG_GETTER_SETTER(functionHasThisBinding, FunctionHasThisBinding)
445 // NeedsHomeObject: custom logic below.
446 // IsDerivedClassConstructor: custom logic below.
447 // IsFieldInitializer: custom logic below.
448 IMMUTABLE_FLAG_GETTER_SETTER(hasRest, HasRest)
449 IMMUTABLE_FLAG_GETTER_SETTER(needsFunctionEnvironmentObjects,
450 NeedsFunctionEnvironmentObjects)
451 IMMUTABLE_FLAG_GETTER_SETTER(functionHasExtraBodyVarScope,
452 FunctionHasExtraBodyVarScope)
453 IMMUTABLE_FLAG_GETTER_SETTER(shouldDeclareArguments, ShouldDeclareArguments)
454 IMMUTABLE_FLAG_GETTER_SETTER(argumentsHasVarBinding, ArgumentsHasVarBinding)
455 // AlwaysNeedsArgsObj: custom logic below.
456 // HasMappedArgsObj: custom logic below.
457 // IsLikelyConstructorWrapper: custom logic below.
458
459 bool needsCallObjectRegardlessOfBindings() const {
460 // Always create a CallObject if:
461 // - The scope is extensible at runtime due to sloppy eval.
462 // - The function is a generator or async function. (The debugger reads the
463 // generator object directly from the frame.)
464
465 return funHasExtensibleScope() || isGenerator() || isAsync();
466 }
467
needsExtraBodyVarEnvironmentRegardlessOfBindings()468 bool needsExtraBodyVarEnvironmentRegardlessOfBindings() const {
469 MOZ_ASSERT(hasParameterExprs);
470 return funHasExtensibleScope();
471 }
472
isLikelyConstructorWrapper()473 bool isLikelyConstructorWrapper() const {
474 return argumentsHasVarBinding() && usesApply && usesThis && !usesReturn;
475 }
476
generatorKind()477 GeneratorKind generatorKind() const {
478 return isGenerator() ? GeneratorKind::Generator
479 : GeneratorKind::NotGenerator;
480 }
481
asyncKind()482 FunctionAsyncKind asyncKind() const {
483 return isAsync() ? FunctionAsyncKind::AsyncFunction
484 : FunctionAsyncKind::SyncFunction;
485 }
486
needsFinalYield()487 bool needsFinalYield() const { return isGenerator() || isAsync(); }
needsDotGeneratorName()488 bool needsDotGeneratorName() const { return isGenerator() || isAsync(); }
needsIteratorResult()489 bool needsIteratorResult() const { return isGenerator() && !isAsync(); }
needsPromiseResult()490 bool needsPromiseResult() const { return isAsync() && !isGenerator(); }
491
isArrow()492 bool isArrow() const { return flags_.isArrow(); }
isLambda()493 bool isLambda() const { return flags_.isLambda(); }
494
hasExprBody()495 bool hasExprBody() const { return hasExprBody_; }
setHasExprBody()496 void setHasExprBody() {
497 MOZ_ASSERT(isArrow());
498 hasExprBody_ = true;
499 }
500
isNamedLambda()501 bool isNamedLambda() const {
502 return flags_.isNamedLambda(explicitName() != nullptr);
503 }
isGetter()504 bool isGetter() const { return flags_.isGetter(); }
isSetter()505 bool isSetter() const { return flags_.isSetter(); }
isMethod()506 bool isMethod() const { return flags_.isMethod(); }
isClassConstructor()507 bool isClassConstructor() const { return flags_.isClassConstructor(); }
508
isInterpreted()509 bool isInterpreted() const { return flags_.hasBaseScript(); }
setIsInterpreted(bool interpreted)510 void setIsInterpreted(bool interpreted) {
511 flags_.setFlags(FunctionFlags::BASESCRIPT, interpreted);
512 }
513
kind()514 FunctionFlags::FunctionKind kind() { return flags_.kind(); }
515
hasInferredName()516 bool hasInferredName() const { return flags_.hasInferredName(); }
hasGuessedAtom()517 bool hasGuessedAtom() const { return flags_.hasGuessedAtom(); }
518
displayAtom()519 JSAtom* displayAtom() const { return atom_; }
explicitName()520 JSAtom* explicitName() const {
521 return (hasInferredName() || hasGuessedAtom()) ? nullptr : atom_;
522 }
523
524 // NOTE: We propagate to any existing functions for now. This handles both the
525 // delazification case where functions already exist, and also handles
526 // code-coverage which is not yet deferred.
setInferredName(JSAtom * atom)527 void setInferredName(JSAtom* atom) {
528 atom_ = atom;
529 flags_.setInferredName();
530 }
setGuessedAtom(JSAtom * atom)531 void setGuessedAtom(JSAtom* atom) {
532 atom_ = atom;
533 flags_.setGuessedAtom();
534 }
535
setAlwaysNeedsArgsObj()536 void setAlwaysNeedsArgsObj() {
537 MOZ_ASSERT(argumentsHasVarBinding());
538 setFlag(ImmutableFlags::AlwaysNeedsArgsObj);
539 }
540
needsHomeObject()541 bool needsHomeObject() const {
542 return hasFlag(ImmutableFlags::NeedsHomeObject);
543 }
setNeedsHomeObject()544 void setNeedsHomeObject() {
545 MOZ_ASSERT(flags_.allowSuperProperty());
546 setFlag(ImmutableFlags::NeedsHomeObject);
547 }
548
isDerivedClassConstructor()549 bool isDerivedClassConstructor() const {
550 return hasFlag(ImmutableFlags::IsDerivedClassConstructor);
551 }
setDerivedClassConstructor()552 void setDerivedClassConstructor() {
553 MOZ_ASSERT(flags_.isClassConstructor());
554 setFlag(ImmutableFlags::IsDerivedClassConstructor);
555 }
556
isFieldInitializer()557 bool isFieldInitializer() const {
558 return hasFlag(ImmutableFlags::IsFieldInitializer);
559 }
setFieldInitializer()560 void setFieldInitializer() {
561 MOZ_ASSERT(flags_.isMethod());
562 setFlag(ImmutableFlags::IsFieldInitializer);
563 }
564
hasSimpleParameterList()565 bool hasSimpleParameterList() const {
566 return !hasRest() && !hasParameterExprs && !hasDestructuringArgs;
567 }
568
hasMappedArgsObj()569 bool hasMappedArgsObj() const {
570 return !strict() && hasSimpleParameterList();
571 }
572
shouldSuppressRunOnce()573 bool shouldSuppressRunOnce() const {
574 // These heuristics suppress the run-once optimization if we expect that
575 // script-cloning will have more impact than TI type-precision would gain.
576 //
577 // See also: Bug 864218
578 return explicitName() || argumentsHasVarBinding() || isGenerator() ||
579 isAsync();
580 }
581
582 // Return whether this or an enclosing function is being parsed and
583 // validated as asm.js. Note: if asm.js validation fails, this will be false
584 // while the function is being reparsed. This flag can be used to disable
585 // certain parsing features that are necessary in general, but unnecessary
586 // for validated asm.js.
useAsmOrInsideUseAsm()587 bool useAsmOrInsideUseAsm() const { return useAsm; }
588
setStart(uint32_t offset,uint32_t line,uint32_t column)589 void setStart(uint32_t offset, uint32_t line, uint32_t column) {
590 extent.sourceStart = offset;
591 extent.lineno = line;
592 extent.column = column;
593 }
594
setEnd(uint32_t end)595 void setEnd(uint32_t end) {
596 // For all functions except class constructors, the buffer and
597 // toString ending positions are the same. Class constructors override
598 // the toString ending position with the end of the class definition.
599 extent.sourceEnd = end;
600 extent.toStringEnd = end;
601 }
602
setArgCount(uint16_t args)603 void setArgCount(uint16_t args) { nargs_ = args; }
604
nargs()605 size_t nargs() { return nargs_; }
606
607 // Flush the acquired argCount to the associated function.
synchronizeArgCount()608 void synchronizeArgCount() { function()->setArgCount(nargs_); }
609
setTypeForScriptedFunction(JSContext * cx)610 bool setTypeForScriptedFunction(JSContext* cx) {
611 RootedFunction fun(cx, function());
612 return JSFunction::setTypeForScriptedFunction(cx, fun, isSingleton);
613 }
614
index()615 size_t index() { return funcDataIndex_; }
616
617 void trace(JSTracer* trc);
618
619 static void TraceList(JSTracer* trc, FunctionBox* listHead);
620
traceLink()621 FunctionBox* traceLink() { return traceLink_; }
622 };
623
624 #undef FLAG_GETTER_SETTER
625 #undef IMMUTABLE_FLAG_GETTER_SETTER
626
asFunctionBox()627 inline FunctionBox* SharedContext::asFunctionBox() {
628 MOZ_ASSERT(isFunctionBox());
629 return static_cast<FunctionBox*>(this);
630 }
631
632 // In generators, we treat all bindings as closed so that they get stored on
633 // the heap. This way there is less information to copy off the stack when
634 // suspending, and back on when resuming. It also avoids the need to create
635 // and invalidate DebugScope proxies for unaliased locals in a generator
636 // frame, as the generator frame will be copied out to the heap and released
637 // only by GC.
allBindingsClosedOver()638 inline bool SharedContext::allBindingsClosedOver() {
639 return bindingsAccessedDynamically() ||
640 (isFunctionBox() &&
641 (asFunctionBox()->isGenerator() || asFunctionBox()->isAsync()));
642 }
643
644 } // namespace frontend
645 } // namespace js
646
647 #endif /* frontend_SharedContext_h */
648