diff options
Diffstat (limited to 'js/src/frontend/ParseContext.cpp')
-rw-r--r-- | js/src/frontend/ParseContext.cpp | 69 |
1 files changed, 56 insertions, 13 deletions
diff --git a/js/src/frontend/ParseContext.cpp b/js/src/frontend/ParseContext.cpp index ececac705b..622c467822 100644 --- a/js/src/frontend/ParseContext.cpp +++ b/js/src/frontend/ParseContext.cpp @@ -593,6 +593,14 @@ bool ParseContext::hasUsedName(const UsedNameTracker& usedNames, return false; } +bool ParseContext::hasClosedOverName(const UsedNameTracker& usedNames, + TaggedParserAtomIndex name) { + if (auto p = usedNames.lookup(name)) { + return p->value().isClosedOver(scriptId()); + } + return false; +} + bool ParseContext::hasUsedFunctionSpecialName(const UsedNameTracker& usedNames, TaggedParserAtomIndex name) { MOZ_ASSERT(name == TaggedParserAtomIndex::WellKnown::arguments() || @@ -602,6 +610,13 @@ bool ParseContext::hasUsedFunctionSpecialName(const UsedNameTracker& usedNames, functionBox()->bindingsAccessedDynamically(); } +bool ParseContext::hasClosedOverFunctionSpecialName( + const UsedNameTracker& usedNames, TaggedParserAtomIndex name) { + MOZ_ASSERT(name == TaggedParserAtomIndex::WellKnown::arguments()); + return hasClosedOverName(usedNames, name) || + functionBox()->bindingsAccessedDynamically(); +} + bool ParseContext::declareFunctionThis(const UsedNameTracker& usedNames, bool canSkipLazyClosedOverBindings) { // The asm.js validator does all its own symbol-table management so, as an @@ -644,17 +659,41 @@ bool ParseContext::declareFunctionArgumentsObject( ParseContext::Scope& funScope = functionScope(); ParseContext::Scope& _varScope = varScope(); - bool usesArguments = false; bool hasExtraBodyVarScope = &funScope != &_varScope; // Time to implement the odd semantics of 'arguments'. auto argumentsName = TaggedParserAtomIndex::WellKnown::arguments(); - bool tryDeclareArguments; + bool tryDeclareArguments = false; + bool needsArgsObject = false; + + // When delazifying simply defer to the function box. if (canSkipLazyClosedOverBindings) { tryDeclareArguments = funbox->shouldDeclareArguments(); + needsArgsObject = funbox->needsArgsObj(); } else { - tryDeclareArguments = hasUsedFunctionSpecialName(usedNames, argumentsName); + // We cannot compute these values when delazifying, hence why we need to + // rely on the function box flags instead. + bool bindingClosedOver = + hasClosedOverFunctionSpecialName(usedNames, argumentsName); + bool bindingUsedOnlyHere = + hasUsedFunctionSpecialName(usedNames, argumentsName) && + !bindingClosedOver; + + // Declare arguments if there's a closed-over consumer of the binding, or if + // there is a non-length use and we will reference the binding during + // bytecode emission. + tryDeclareArguments = + !funbox->isEligibleForArgumentsLength() || bindingClosedOver; + // If we have a use and the binding isn't closed over, then we will do + // bytecode emission with the arguments intrinsic. + if (bindingUsedOnlyHere && funbox->isEligibleForArgumentsLength()) { + // If we're using the intrinsic we should not be declaring the binding. + MOZ_ASSERT(!tryDeclareArguments); + funbox->setUsesArgumentsIntrinsics(); + } else if (tryDeclareArguments) { + needsArgsObject = true; + } } // ES 9.2.12 steps 19 and 20 say formal parameters, lexical bindings, @@ -670,9 +709,19 @@ bool ParseContext::declareFunctionArgumentsObject( DeclaredNamePtr p = _varScope.lookupDeclaredName(argumentsName); if (p && p->value()->kind() == DeclarationKind::Var) { if (hasExtraBodyVarScope) { + // While there is a binding in the var scope, we should declare + // the binding in the function scope. tryDeclareArguments = true; } else { - usesArguments = true; + // A binding in the function scope (since varScope and functionScope are + // the same) exists, so arguments is used. + if (needsArgsObject) { + funbox->setNeedsArgsObj(); + } + + // There is no point in continuing on below: We know we already have + // a declaration of arguments in the function scope. + return true; } } @@ -685,17 +734,11 @@ bool ParseContext::declareFunctionArgumentsObject( return false; } funbox->setShouldDeclareArguments(); - usesArguments = true; - } else if (hasExtraBodyVarScope) { - // Formal parameters shadow the arguments object. - return true; + if (needsArgsObject) { + funbox->setNeedsArgsObj(); + } } } - - if (usesArguments) { - funbox->setNeedsArgsObj(); - } - return true; } |