SharedContext.h (26404B)
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 <stddef.h> 15 #include <stdint.h> 16 17 #include "jstypes.h" 18 19 #include "frontend/FunctionSyntaxKind.h" // FunctionSyntaxKind 20 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex 21 #include "frontend/ScopeIndex.h" // ScopeIndex 22 #include "frontend/ScriptIndex.h" // ScriptIndex 23 #include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin 24 #include "vm/FunctionFlags.h" // js::FunctionFlags 25 #include "vm/GeneratorAndAsyncKind.h" // js::GeneratorKind, js::FunctionAsyncKind 26 #include "vm/Scope.h" 27 #include "vm/ScopeKind.h" 28 #include "vm/SharedStencil.h" 29 #include "vm/StencilEnums.h" 30 31 namespace JS { 32 class JS_PUBLIC_API ReadOnlyCompileOptions; 33 struct WasmModule; 34 } // namespace JS 35 36 namespace js { 37 38 class FrontendContext; 39 40 namespace frontend { 41 42 struct CompilationState; 43 class FunctionBox; 44 class FunctionNode; 45 class ParseContext; 46 class ScriptStencil; 47 class ScriptStencilExtra; 48 struct ScopeContext; 49 50 enum class StatementKind : uint8_t { 51 Label, 52 Block, 53 If, 54 Switch, 55 With, 56 Catch, 57 Try, 58 Finally, 59 ForLoopLexicalHead, 60 ForLoop, 61 ForInLoop, 62 ForOfLoop, 63 DoLoop, 64 WhileLoop, 65 Class, 66 67 // Used only by BytecodeEmitter. 68 Spread, 69 YieldStar, 70 }; 71 72 static inline bool StatementKindIsLoop(StatementKind kind) { 73 return kind == StatementKind::ForLoop || kind == StatementKind::ForInLoop || 74 kind == StatementKind::ForOfLoop || kind == StatementKind::DoLoop || 75 kind == StatementKind::WhileLoop || kind == StatementKind::Spread || 76 kind == StatementKind::YieldStar; 77 } 78 79 static inline bool StatementKindIsUnlabeledBreakTarget(StatementKind kind) { 80 return StatementKindIsLoop(kind) || kind == StatementKind::Switch; 81 } 82 83 // List of directives that may be encountered in a Directive Prologue 84 // (ES5 15.1). 85 class Directives { 86 bool strict_; 87 bool asmJS_; 88 89 public: 90 explicit Directives(bool strict) : strict_(strict), asmJS_(false) {} 91 explicit Directives(ParseContext* parent); 92 93 void setStrict() { strict_ = true; } 94 bool strict() const { return strict_; } 95 96 void setAsmJS() { asmJS_ = true; } 97 bool asmJS() const { return asmJS_; } 98 99 Directives& operator=(Directives rhs) { 100 strict_ = rhs.strict_; 101 asmJS_ = rhs.asmJS_; 102 return *this; 103 } 104 bool operator==(const Directives& rhs) const { 105 return strict_ == rhs.strict_ && asmJS_ == rhs.asmJS_; 106 } 107 bool operator!=(const Directives& rhs) const { return !(*this == rhs); } 108 }; 109 110 // The kind of this-binding for the current scope. Note that arrow functions 111 // have a lexical this-binding so their ThisBinding is the same as the 112 // ThisBinding of their enclosing scope and can be any value. Derived 113 // constructors require TDZ checks when accessing the binding. 114 enum class ThisBinding : uint8_t { 115 Global, 116 Module, 117 Function, 118 DerivedConstructor 119 }; 120 121 // If Yes, the script inherits it's "this" environment and binding from the 122 // enclosing script. This is true for arrow-functions and eval scripts. 123 enum class InheritThis { No, Yes }; 124 125 class GlobalSharedContext; 126 class EvalSharedContext; 127 class ModuleSharedContext; 128 class SuspendableContext; 129 130 #define IMMUTABLE_FLAG_GETTER_SETTER(lowerName, name) \ 131 GENERIC_FLAG_GETTER_SETTER(ImmutableFlags, lowerName, name) 132 133 #define IMMUTABLE_FLAG_GETTER(lowerName, name) \ 134 GENERIC_FLAG_GETTER(ImmutableFlags, lowerName, name) 135 136 /* 137 * The struct SharedContext is part of the current parser context (see 138 * ParseContext). It stores information that is reused between the parser and 139 * the bytecode emitter. 140 */ 141 class SharedContext { 142 public: 143 FrontendContext* const fc_; 144 145 protected: 146 // See: BaseScript::immutableFlags_ 147 ImmutableScriptFlags immutableFlags_ = {}; 148 149 // The location of this script in the source. Note that the value here differs 150 // from the final BaseScript for the case of standalone functions. 151 // This field is copied to ScriptStencil, and shouldn't be modified after the 152 // copy. 153 SourceExtent extent_ = {}; 154 155 protected: 156 // See: ThisBinding 157 ThisBinding thisBinding_ = ThisBinding::Global; 158 159 // These flags do not have corresponding script flags and may be inherited 160 // from the scope chain in the case of eval and arrows. 161 bool allowNewTarget_ : 1; 162 bool allowSuperProperty_ : 1; 163 bool allowSuperCall_ : 1; 164 bool allowArguments_ : 1; 165 bool inWith_ : 1; 166 bool inClass_ : 1; 167 168 // See `strict()` below. 169 bool localStrict : 1; 170 171 // True if "use strict"; appears in the body instead of being inherited. 172 bool hasExplicitUseStrict_ : 1; 173 174 // Tracks if script-related fields are already copied to ScriptStencilExtra. 175 // 176 // If this field is true, those fileds shouldn't be modified. 177 // 178 // For FunctionBox, some fields are allowed to be modified, but the 179 // modification should be synced with ScriptStencilExtra by 180 // FunctionBox::copyUpdated* methods. 181 bool isScriptExtraFieldCopiedToStencil : 1; 182 183 // Indicates this shared context is eligible to use JSOp::ArgumentsLength 184 // when emitting the ArgumentsLength parse node. 185 bool eligibleForArgumentsLength : 1; 186 187 // End of fields. 188 189 enum class Kind : uint8_t { FunctionBox, Global, Eval, Module }; 190 191 // Alias enum into SharedContext 192 using ImmutableFlags = ImmutableScriptFlagsEnum; 193 194 [[nodiscard]] bool hasFlag(ImmutableFlags flag) const { 195 return immutableFlags_.hasFlag(flag); 196 } 197 void setFlag(ImmutableFlags flag, bool b = true) { 198 MOZ_ASSERT(!isScriptExtraFieldCopiedToStencil); 199 immutableFlags_.setFlag(flag, b); 200 } 201 void clearFlag(ImmutableFlags flag) { 202 MOZ_ASSERT(!isScriptExtraFieldCopiedToStencil); 203 immutableFlags_.clearFlag(flag); 204 } 205 206 public: 207 SharedContext(FrontendContext* fc, Kind kind, 208 const JS::ReadOnlyCompileOptions& options, 209 Directives directives, SourceExtent extent); 210 211 IMMUTABLE_FLAG_GETTER_SETTER(isForEval, IsForEval) 212 IMMUTABLE_FLAG_GETTER_SETTER(isModule, IsModule) 213 IMMUTABLE_FLAG_GETTER_SETTER(isFunction, IsFunction) 214 IMMUTABLE_FLAG_GETTER_SETTER(selfHosted, SelfHosted) 215 IMMUTABLE_FLAG_GETTER_SETTER(forceStrict, ForceStrict) 216 IMMUTABLE_FLAG_GETTER_SETTER(hasNonSyntacticScope, HasNonSyntacticScope) 217 IMMUTABLE_FLAG_GETTER_SETTER(noScriptRval, NoScriptRval) 218 IMMUTABLE_FLAG_GETTER(treatAsRunOnce, TreatAsRunOnce) 219 // Strict: custom logic below 220 IMMUTABLE_FLAG_GETTER_SETTER(hasModuleGoal, HasModuleGoal) 221 IMMUTABLE_FLAG_GETTER_SETTER(hasInnerFunctions, HasInnerFunctions) 222 IMMUTABLE_FLAG_GETTER_SETTER(hasDirectEval, HasDirectEval) 223 IMMUTABLE_FLAG_GETTER_SETTER(bindingsAccessedDynamically, 224 BindingsAccessedDynamically) 225 IMMUTABLE_FLAG_GETTER_SETTER(hasCallSiteObj, HasCallSiteObj) 226 227 const SourceExtent& extent() const { return extent_; } 228 229 bool isFunctionBox() const { return isFunction(); } 230 inline FunctionBox* asFunctionBox(); 231 bool isModuleContext() const { return isModule(); } 232 inline ModuleSharedContext* asModuleContext(); 233 bool isSuspendableContext() const { return isFunction() || isModule(); } 234 inline SuspendableContext* asSuspendableContext(); 235 bool isGlobalContext() const { 236 return !(isFunction() || isModule() || isForEval()); 237 } 238 inline GlobalSharedContext* asGlobalContext(); 239 bool isEvalContext() const { return isForEval(); } 240 inline EvalSharedContext* asEvalContext(); 241 242 bool isTopLevelContext() const { return !isFunction(); } 243 244 ThisBinding thisBinding() const { return thisBinding_; } 245 bool hasFunctionThisBinding() const { 246 return thisBinding() == ThisBinding::Function || 247 thisBinding() == ThisBinding::DerivedConstructor; 248 } 249 bool needsThisTDZChecks() const { 250 return thisBinding() == ThisBinding::DerivedConstructor; 251 } 252 253 bool isSelfHosted() const { return selfHosted(); } 254 bool allowNewTarget() const { return allowNewTarget_; } 255 bool allowSuperProperty() const { return allowSuperProperty_; } 256 bool allowSuperCall() const { return allowSuperCall_; } 257 bool allowArguments() const { return allowArguments_; } 258 bool inWith() const { return inWith_; } 259 bool inClass() const { return inClass_; } 260 261 bool hasExplicitUseStrict() const { return hasExplicitUseStrict_; } 262 void setExplicitUseStrict() { hasExplicitUseStrict_ = true; } 263 264 ImmutableScriptFlags immutableFlags() const { return immutableFlags_; } 265 266 bool allBindingsClosedOver() const { return bindingsAccessedDynamically(); } 267 268 // The ImmutableFlag tracks if the entire script is strict, while the 269 // localStrict flag indicates the current region (such as class body) should 270 // be treated as strict. The localStrict flag will always be reset to false 271 // before the end of the script. 272 bool strict() const { return hasFlag(ImmutableFlags::Strict) || localStrict; } 273 void setStrictScript() { setFlag(ImmutableFlags::Strict); } 274 bool setLocalStrictMode(bool strict) { 275 bool retVal = localStrict; 276 localStrict = strict; 277 return retVal; 278 } 279 280 bool isEligibleForArgumentsLength() const { 281 return eligibleForArgumentsLength && !bindingsAccessedDynamically(); 282 } 283 void setIneligibleForArgumentsLength() { eligibleForArgumentsLength = false; } 284 285 void copyScriptExtraFields(ScriptStencilExtra& scriptExtra); 286 }; 287 288 class MOZ_STACK_CLASS GlobalSharedContext : public SharedContext { 289 ScopeKind scopeKind_; 290 291 public: 292 GlobalScope::ParserData* bindings; 293 294 GlobalSharedContext(FrontendContext* fc, ScopeKind scopeKind, 295 const JS::ReadOnlyCompileOptions& options, 296 Directives directives, SourceExtent extent); 297 298 ScopeKind scopeKind() const { return scopeKind_; } 299 }; 300 301 inline GlobalSharedContext* SharedContext::asGlobalContext() { 302 MOZ_ASSERT(isGlobalContext()); 303 return static_cast<GlobalSharedContext*>(this); 304 } 305 306 class MOZ_STACK_CLASS EvalSharedContext : public SharedContext { 307 public: 308 EvalScope::ParserData* bindings; 309 310 EvalSharedContext(FrontendContext* fc, CompilationState& compilationState, 311 SourceExtent extent); 312 }; 313 314 inline EvalSharedContext* SharedContext::asEvalContext() { 315 MOZ_ASSERT(isEvalContext()); 316 return static_cast<EvalSharedContext*>(this); 317 } 318 319 enum class HasHeritage { No, Yes }; 320 321 class SuspendableContext : public SharedContext { 322 public: 323 SuspendableContext(FrontendContext* fc, Kind kind, 324 const JS::ReadOnlyCompileOptions& options, 325 Directives directives, SourceExtent extent, 326 bool isGenerator, bool isAsync); 327 328 IMMUTABLE_FLAG_GETTER_SETTER(isAsync, IsAsync) 329 IMMUTABLE_FLAG_GETTER_SETTER(isGenerator, IsGenerator) 330 331 bool needsFinalYield() const { return isGenerator() || isAsync(); } 332 bool needsDotGeneratorName() const { return isGenerator() || isAsync(); } 333 bool needsClearSlotsOnExit() const { return isGenerator() || isAsync(); } 334 bool needsIteratorResult() const { return isGenerator() && !isAsync(); } 335 bool needsPromiseResult() const { return isAsync() && !isGenerator(); } 336 }; 337 338 class FunctionBox : public SuspendableContext { 339 friend struct GCThingList; 340 341 CompilationState& compilationState_; 342 343 // If this FunctionBox refers to a lazy child of the function being 344 // compiled, this field holds the child's immediately enclosing scope's index. 345 // Once compilation succeeds, we will store the scope pointed by this in the 346 // child's BaseScript. (Debugger may become confused if lazy scripts refer to 347 // partially initialized enclosing scopes, so we must avoid storing the 348 // scope in the BaseScript until compilation has completed 349 // successfully.) 350 // This is copied to ScriptStencil. 351 // Any update after the copy should be synced to the ScriptStencil. 352 mozilla::Maybe<ScopeIndex> enclosingScopeIndex_; 353 354 // Names from the named lambda scope, if a named lambda. 355 LexicalScope::ParserData* namedLambdaBindings_ = nullptr; 356 357 // Names from the function scope. 358 FunctionScope::ParserData* functionScopeBindings_ = nullptr; 359 360 // Names from the extra 'var' scope of the function, if the parameter list 361 // has expressions. 362 VarScope::ParserData* extraVarScopeBindings_ = nullptr; 363 364 // The explicit or implicit name of the function. The FunctionFlags indicate 365 // the kind of name. 366 // This is copied to ScriptStencil. 367 // Any update after the copy should be synced to the ScriptStencil. 368 TaggedParserAtomIndex atom_; 369 370 // Index into CompilationStencil::scriptData. 371 ScriptIndex funcDataIndex_ = ScriptIndex(-1); 372 373 // See: FunctionFlags 374 // This is copied to ScriptStencil. 375 // Any update after the copy should be synced to the ScriptStencil. 376 FunctionFlags flags_ = {}; 377 378 // See: ImmutableScriptData::funLength 379 uint16_t length_ = 0; 380 381 // JSFunction::nargs_ 382 // This field is copied to ScriptStencil, and shouldn't be modified after the 383 // copy. 384 uint16_t nargs_ = 0; 385 386 // See: PrivateScriptData::memberInitializers_ 387 // This field is copied to ScriptStencil, and shouldn't be modified after the 388 // copy. 389 MemberInitializers memberInitializers_ = MemberInitializers::Invalid(); 390 391 public: 392 // Back pointer used by asm.js for error messages. 393 FunctionNode* functionNode = nullptr; 394 395 // True if bytecode will be emitted for this function in the current 396 // compilation. 397 bool emitBytecode : 1; 398 399 // This is set by the BytecodeEmitter of the enclosing script when a reference 400 // to this function is generated. This is also used to determine a hoisted 401 // function already is referenced by the bytecode. 402 bool wasEmittedByEnclosingScript_ : 1; 403 404 // Need to emit a synthesized Annex B assignment 405 bool isAnnexB : 1; 406 407 // Track if we saw "use asm". 408 // If we successfully validated it, `flags_` is seto to `AsmJS` kind. 409 bool useAsm : 1; 410 411 // Analysis of parameter list 412 bool hasParameterExprs : 1; 413 bool hasDestructuringArgs : 1; 414 bool hasDuplicateParameters : 1; 415 416 // Arrow function with expression body like: `() => 1`. 417 bool hasExprBody_ : 1; 418 419 // Used to issue an early error in static class blocks. 420 bool allowReturn_ : 1; 421 422 // Tracks if function-related fields are already copied to ScriptStencil. 423 // If this field is true, modification to those fields should be synced with 424 // ScriptStencil by copyUpdated* methods. 425 bool isFunctionFieldCopiedToStencil : 1; 426 427 // True if this is part of initial compilation. 428 // False if this is part of delazification. 429 bool isInitialCompilation : 1; 430 431 // True if this is standalone function 432 // (new Function() including generator/async, or event handler). 433 bool isStandalone : 1; 434 435 // End of fields. 436 437 FunctionBox(FrontendContext* fc, SourceExtent extent, 438 CompilationState& compilationState, Directives directives, 439 GeneratorKind generatorKind, FunctionAsyncKind asyncKind, 440 bool isInitialCompilation, TaggedParserAtomIndex atom, 441 FunctionFlags flags, ScriptIndex index); 442 443 ScriptStencil& functionStencil() const; 444 ScriptStencilExtra& functionExtraStencil() const; 445 446 LexicalScope::ParserData* namedLambdaBindings() { 447 return namedLambdaBindings_; 448 } 449 void setNamedLambdaBindings(LexicalScope::ParserData* bindings) { 450 namedLambdaBindings_ = bindings; 451 } 452 453 FunctionScope::ParserData* functionScopeBindings() { 454 return functionScopeBindings_; 455 } 456 void setFunctionScopeBindings(FunctionScope::ParserData* bindings) { 457 functionScopeBindings_ = bindings; 458 } 459 460 VarScope::ParserData* extraVarScopeBindings() { 461 return extraVarScopeBindings_; 462 } 463 void setExtraVarScopeBindings(VarScope::ParserData* bindings) { 464 extraVarScopeBindings_ = bindings; 465 } 466 467 void initFromLazyFunction(const ScriptStencilExtra& extra, 468 ScopeContext& scopeContext, 469 FunctionSyntaxKind kind); 470 void initFromScriptStencilExtra(const ScriptStencilExtra& extra); 471 void initStandalone(ScopeContext& scopeContext, FunctionSyntaxKind kind); 472 473 private: 474 void initStandaloneOrLazy(ScopeContext& scopeContext, 475 FunctionSyntaxKind kind); 476 477 public: 478 void initWithEnclosingParseContext(ParseContext* enclosing, 479 FunctionSyntaxKind kind); 480 481 void setEnclosingScopeForInnerLazyFunction(ScopeIndex scopeIndex); 482 483 bool wasEmittedByEnclosingScript() const { 484 return wasEmittedByEnclosingScript_; 485 } 486 void setWasEmittedByEnclosingScript(bool wasEmitted) { 487 wasEmittedByEnclosingScript_ = wasEmitted; 488 if (isFunctionFieldCopiedToStencil) { 489 copyUpdatedWasEmitted(); 490 } 491 } 492 493 [[nodiscard]] bool setUseAsm(); 494 [[nodiscard]] bool setAsmJSModule(const JS::WasmModule* module); 495 bool isAsmJSModule() const { return flags_.isAsmJSNative(); } 496 497 bool hasEnclosingScopeIndex() const { return enclosingScopeIndex_.isSome(); } 498 ScopeIndex getEnclosingScopeIndex() const { return *enclosingScopeIndex_; } 499 500 IMMUTABLE_FLAG_GETTER_SETTER(isAsync, IsAsync) 501 IMMUTABLE_FLAG_GETTER_SETTER(isGenerator, IsGenerator) 502 IMMUTABLE_FLAG_GETTER_SETTER(funHasExtensibleScope, FunHasExtensibleScope) 503 IMMUTABLE_FLAG_GETTER_SETTER(functionHasThisBinding, FunctionHasThisBinding) 504 IMMUTABLE_FLAG_GETTER_SETTER(functionHasNewTargetBinding, 505 FunctionHasNewTargetBinding) 506 // NeedsHomeObject: custom logic below. 507 // IsDerivedClassConstructor: custom logic below. 508 // IsFieldInitializer: custom logic below. 509 IMMUTABLE_FLAG_GETTER(useMemberInitializers, UseMemberInitializers) 510 IMMUTABLE_FLAG_GETTER_SETTER(hasRest, HasRest) 511 IMMUTABLE_FLAG_GETTER_SETTER(needsFunctionEnvironmentObjects, 512 NeedsFunctionEnvironmentObjects) 513 IMMUTABLE_FLAG_GETTER_SETTER(functionHasExtraBodyVarScope, 514 FunctionHasExtraBodyVarScope) 515 IMMUTABLE_FLAG_GETTER_SETTER(shouldDeclareArguments, ShouldDeclareArguments) 516 IMMUTABLE_FLAG_GETTER_SETTER(needsArgsObj, NeedsArgsObj) 517 // HasMappedArgsObj: custom logic below. 518 519 bool needsCallObjectRegardlessOfBindings() const { 520 // Always create a CallObject if: 521 // - The scope is extensible at runtime due to sloppy eval. 522 // - The function is a generator or async function. (The debugger reads the 523 // generator object directly from the frame.) 524 525 return funHasExtensibleScope() || isGenerator() || isAsync(); 526 } 527 528 bool needsExtraBodyVarEnvironmentRegardlessOfBindings() const { 529 MOZ_ASSERT(hasParameterExprs); 530 return funHasExtensibleScope(); 531 } 532 533 GeneratorKind generatorKind() const { 534 return isGenerator() ? GeneratorKind::Generator 535 : GeneratorKind::NotGenerator; 536 } 537 538 FunctionAsyncKind asyncKind() const { 539 return isAsync() ? FunctionAsyncKind::AsyncFunction 540 : FunctionAsyncKind::SyncFunction; 541 } 542 543 bool needsFinalYield() const { return isGenerator() || isAsync(); } 544 bool needsDotGeneratorName() const { return isGenerator() || isAsync(); } 545 bool needsClearSlotsOnExit() const { return isGenerator() || isAsync(); } 546 bool needsIteratorResult() const { return isGenerator() && !isAsync(); } 547 bool needsPromiseResult() const { return isAsync() && !isGenerator(); } 548 549 bool isArrow() const { return flags_.isArrow(); } 550 bool isLambda() const { return flags_.isLambda(); } 551 552 bool hasExprBody() const { return hasExprBody_; } 553 void setHasExprBody() { 554 MOZ_ASSERT(isArrow()); 555 hasExprBody_ = true; 556 } 557 558 bool allowReturn() const { return allowReturn_; } 559 560 bool isNamedLambda() const { return flags_.isNamedLambda(!!explicitName()); } 561 bool isGetter() const { return flags_.isGetter(); } 562 bool isSetter() const { return flags_.isSetter(); } 563 bool isMethod() const { return flags_.isMethod(); } 564 bool isClassConstructor() const { return flags_.isClassConstructor(); } 565 566 bool isInterpreted() const { return flags_.hasBaseScript(); } 567 568 FunctionFlags::FunctionKind kind() const { return flags_.kind(); } 569 570 bool hasInferredName() const { return flags_.hasInferredName(); } 571 bool hasGuessedAtom() const { return flags_.hasGuessedAtom(); } 572 573 TaggedParserAtomIndex displayAtom() const { return atom_; } 574 TaggedParserAtomIndex explicitName() const { 575 return (hasInferredName() || hasGuessedAtom()) 576 ? TaggedParserAtomIndex::null() 577 : atom_; 578 } 579 580 // NOTE: We propagate to any existing functions for now. This handles both the 581 // delazification case where functions already exist, and also handles 582 // code-coverage which is not yet deferred. 583 void setInferredName(TaggedParserAtomIndex atom) { 584 atom_ = atom; 585 flags_.setInferredName(); 586 if (isFunctionFieldCopiedToStencil) { 587 copyUpdatedAtomAndFlags(); 588 } 589 } 590 void setGuessedAtom(TaggedParserAtomIndex atom) { 591 atom_ = atom; 592 flags_.setGuessedAtom(); 593 if (isFunctionFieldCopiedToStencil) { 594 copyUpdatedAtomAndFlags(); 595 } 596 } 597 598 bool needsHomeObject() const { 599 return hasFlag(ImmutableFlags::NeedsHomeObject); 600 } 601 void setNeedsHomeObject() { 602 MOZ_ASSERT(flags_.allowSuperProperty()); 603 setFlag(ImmutableFlags::NeedsHomeObject); 604 flags_.setIsExtended(); 605 } 606 607 bool isDerivedClassConstructor() const { 608 return hasFlag(ImmutableFlags::IsDerivedClassConstructor); 609 } 610 void setDerivedClassConstructor() { 611 MOZ_ASSERT(flags_.isClassConstructor()); 612 setFlag(ImmutableFlags::IsDerivedClassConstructor); 613 } 614 615 bool isSyntheticFunction() const { 616 return hasFlag(ImmutableFlags::IsSyntheticFunction); 617 } 618 void setSyntheticFunction() { 619 // Field initializer, class constructor or getter or setter 620 // synthesized from accessor keyword. 621 MOZ_ASSERT(flags_.isMethod() || flags_.isGetter() || flags_.isSetter()); 622 setFlag(ImmutableFlags::IsSyntheticFunction); 623 } 624 625 bool hasSimpleParameterList() const { 626 return !hasRest() && !hasParameterExprs && !hasDestructuringArgs; 627 } 628 629 bool hasMappedArgsObj() const { 630 return !strict() && hasSimpleParameterList(); 631 } 632 633 // Return whether this or an enclosing function is being parsed and 634 // validated as asm.js. Note: if asm.js validation fails, this will be false 635 // while the function is being reparsed. This flag can be used to disable 636 // certain parsing features that are necessary in general, but unnecessary 637 // for validated asm.js. 638 bool useAsmOrInsideUseAsm() const { return useAsm; } 639 640 void setStart(uint32_t offset, uint32_t line, 641 JS::LimitedColumnNumberOneOrigin column) { 642 MOZ_ASSERT(!isScriptExtraFieldCopiedToStencil); 643 extent_.sourceStart = offset; 644 extent_.lineno = line; 645 extent_.column = column; 646 } 647 648 void setEnd(uint32_t end) { 649 MOZ_ASSERT(!isScriptExtraFieldCopiedToStencil); 650 // For all functions except class constructors, the buffer and 651 // toString ending positions are the same. Class constructors override 652 // the toString ending position with the end of the class definition. 653 extent_.sourceEnd = end; 654 extent_.toStringEnd = end; 655 } 656 657 void setCtorToStringEnd(uint32_t end) { 658 extent_.toStringEnd = end; 659 if (isScriptExtraFieldCopiedToStencil) { 660 copyUpdatedExtent(); 661 } 662 } 663 664 void setCtorFunctionHasThisBinding() { 665 immutableFlags_.setFlag(ImmutableFlags::FunctionHasThisBinding, true); 666 if (isScriptExtraFieldCopiedToStencil) { 667 copyUpdatedImmutableFlags(); 668 } 669 } 670 671 void setIsInlinableLargeFunction() { 672 immutableFlags_.setFlag(ImmutableFlags::IsInlinableLargeFunction, true); 673 if (isScriptExtraFieldCopiedToStencil) { 674 copyUpdatedImmutableFlags(); 675 } 676 } 677 678 void setUsesArgumentsIntrinsics() { 679 immutableFlags_.setFlag(ImmutableFlags::UsesArgumentsIntrinsics, true); 680 if (isScriptExtraFieldCopiedToStencil) { 681 copyUpdatedImmutableFlags(); 682 } 683 } 684 685 uint16_t length() const { return length_; } 686 void setLength(uint16_t length) { length_ = length; } 687 688 void setArgCount(uint16_t args) { 689 MOZ_ASSERT(!isFunctionFieldCopiedToStencil); 690 nargs_ = args; 691 } 692 693 size_t nargs() const { return nargs_; } 694 695 const MemberInitializers& memberInitializers() const { 696 MOZ_ASSERT(useMemberInitializers()); 697 return memberInitializers_; 698 } 699 void setMemberInitializers(MemberInitializers memberInitializers) { 700 immutableFlags_.setFlag(ImmutableFlags::UseMemberInitializers, true); 701 memberInitializers_ = memberInitializers; 702 if (isScriptExtraFieldCopiedToStencil) { 703 copyUpdatedImmutableFlags(); 704 copyUpdatedMemberInitializers(); 705 } 706 } 707 708 ScriptIndex index() const { return funcDataIndex_; } 709 710 void finishScriptFlags(); 711 void copyFunctionFields(ScriptStencil& script); 712 void copyFunctionExtraFields(ScriptStencilExtra& scriptExtra); 713 714 // * setCtorFunctionHasThisBinding can be called to a class constructor 715 // with a lazy function, while parsing enclosing class 716 // * setIsInlinableLargeFunction can be called by BCE to update flags of the 717 // previous top-level function, but only in self-hosted mode. 718 void copyUpdatedImmutableFlags(); 719 720 // * setCtorToStringEnd bcan be called to a class constructor with a lazy 721 // function, while parsing enclosing class 722 void copyUpdatedExtent(); 723 724 // * setMemberInitializers can be called to a class constructor with a lazy 725 // function, while emitting enclosing script 726 void copyUpdatedMemberInitializers(); 727 728 // * setEnclosingScopeForInnerLazyFunction can be called to a lazy function, 729 // while emitting enclosing script 730 void copyUpdatedEnclosingScopeIndex(); 731 732 // * setInferredName can be called to a lazy function, while emitting 733 // enclosing script 734 // * setGuessedAtom can be called to both lazy/non-lazy functions, 735 // while running NameFunctions 736 void copyUpdatedAtomAndFlags(); 737 738 // * setWasEmitted can be called to a lazy function, while emitting 739 // enclosing script 740 void copyUpdatedWasEmitted(); 741 }; 742 743 #undef FLAG_GETTER_SETTER 744 #undef IMMUTABLE_FLAG_GETTER_SETTER 745 746 inline FunctionBox* SharedContext::asFunctionBox() { 747 MOZ_ASSERT(isFunctionBox()); 748 return static_cast<FunctionBox*>(this); 749 } 750 751 inline SuspendableContext* SharedContext::asSuspendableContext() { 752 MOZ_ASSERT(isSuspendableContext()); 753 return static_cast<SuspendableContext*>(this); 754 } 755 756 } // namespace frontend 757 } // namespace js 758 759 #endif /* frontend_SharedContext_h */