Ignore:
Timestamp:
Jun 29, 2018, 4:40:25 PM (7 years ago)
Author:
[email protected]
Message:

We shouldn't recurse into the parser when gathering metadata about various function offsets
https://bugs.webkit.org/show_bug.cgi?id=184074
<rdar://problem/37165897>

Reviewed by Mark Lam.

JSTests:

  • microbenchmarks/try-get-by-id-basic.js:

(const.bench.f.const.fooPlusBar.createBuiltin):

  • microbenchmarks/try-get-by-id-polymorphic.js:

(fooPlusBar.createBuiltin):

  • stress/array-push-with-force-exit.js:
  • stress/dont-crash-on-stack-overflow-when-parsing-builtin.js: Added.

(f):

  • stress/dont-crash-on-stack-overflow-when-parsing-default-constructor.js: Added.

(foo):
(prototype.runNearStackLimit):

  • stress/is-constructor.js:
  • stress/tailCallForwardArguments.js:

(putFuncToPrivateName.createBuiltin):

Source/JavaScriptCore:

Prior to this patch, when we made a builtin, we had to make an UnlinkedFunctionExecutable
for that builtin. This required calling into the parser. However, the parser
may throw a stack overflow. We were not able to recover from that. The only
reason we called into the parser here is that we were gathering text offsets
and various metadata for things in the builtin function. This patch writes a
mini parser that figures this information out without calling into the full
parser. (I've also added a debug assert that verifies the mini parser stays in
sync with the full parser.) The result of this is that BuiltinExecutbles::createExecutable
always succeeds.

  • builtins/AsyncFromSyncIteratorPrototype.js:

(globalPrivate.createAsyncFromSyncIterator):
(globalPrivate.AsyncFromSyncIteratorConstructor):

  • builtins/BuiltinExecutables.cpp:

(JSC::BuiltinExecutables::createExecutable):

  • builtins/GlobalOperations.js:

(globalPrivate.getter.overriddenName.string_appeared_here.speciesGetter):
(globalPrivate.speciesConstructor):
(globalPrivate.copyDataProperties):
(globalPrivate.copyDataPropertiesNoExclusions):

  • builtins/PromiseOperations.js:

(globalPrivate.newHandledRejectedPromise):

  • builtins/RegExpPrototype.js:

(globalPrivate.hasObservableSideEffectsForRegExpMatch):
(globalPrivate.hasObservableSideEffectsForRegExpSplit):

  • builtins/StringPrototype.js:

(globalPrivate.hasObservableSideEffectsForStringReplace):
(globalPrivate.getDefaultCollator):

  • parser/Nodes.cpp:

(JSC::FunctionMetadataNode::FunctionMetadataNode):
(JSC::FunctionMetadataNode::operator== const):
(JSC::FunctionMetadataNode::dump const):

  • parser/Nodes.h:
  • parser/Parser.h:

(JSC::parse):

  • parser/ParserError.h:

(JSC::ParserError::type const):

  • parser/ParserTokens.h:

(JSC::JSTextPosition::operator== const):
(JSC::JSTextPosition::operator!= const):

  • parser/SourceCode.h:

(JSC::SourceCode::operator== const):
(JSC::SourceCode::operator!= const):
(JSC::SourceCode::subExpression const):
(JSC::SourceCode::subExpression): Deleted.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/parser/Nodes.cpp

    r229608 r233377  
    215215}
    216216
     217FunctionMetadataNode::FunctionMetadataNode(
     218    const JSTokenLocation& startLocation,
     219    const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn,
     220    int functionKeywordStart, int functionNameStart, int parametersStart, bool isInStrictContext,
     221    ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression)
     222        : Node(endLocation)
     223        , m_startColumn(startColumn)
     224        , m_endColumn(endColumn)
     225        , m_functionKeywordStart(functionKeywordStart)
     226        , m_functionNameStart(functionNameStart)
     227        , m_parametersStart(parametersStart)
     228        , m_startStartOffset(startLocation.startOffset)
     229        , m_parameterCount(parameterCount)
     230        , m_parseMode(mode)
     231        , m_isInStrictContext(isInStrictContext)
     232        , m_superBinding(static_cast<unsigned>(superBinding))
     233        , m_constructorKind(static_cast<unsigned>(constructorKind))
     234        , m_isArrowFunctionBodyExpression(isArrowFunctionBodyExpression)
     235{
     236    ASSERT(m_superBinding == static_cast<unsigned>(superBinding));
     237    ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind));
     238}
     239
    217240void FunctionMetadataNode::finishParsing(const SourceCode& source, const Identifier& ident, FunctionMode functionMode)
    218241{
     
    226249    m_lastLine = position.line;
    227250    m_endColumn = position.offset - position.lineStartOffset;
     251}
     252
     253bool FunctionMetadataNode::operator==(const FunctionMetadataNode& other) const
     254{
     255    return m_ident == other.m_ident
     256        && m_ecmaName == other.m_ecmaName
     257        && m_inferredName == other.m_inferredName
     258        && m_functionMode== other.m_functionMode
     259        && m_startColumn== other.m_startColumn
     260        && m_endColumn== other.m_endColumn
     261        && m_functionKeywordStart== other.m_functionKeywordStart
     262        && m_functionNameStart== other.m_functionNameStart
     263        && m_parametersStart== other.m_parametersStart
     264        && m_source== other.m_source
     265        && m_classSource== other.m_classSource
     266        && m_startStartOffset== other.m_startStartOffset
     267        && m_parameterCount== other.m_parameterCount
     268        && m_lastLine== other.m_lastLine
     269        && m_parseMode== other.m_parseMode
     270        && m_isInStrictContext == other.m_isInStrictContext
     271        && m_superBinding == other.m_superBinding
     272        && m_constructorKind == other.m_constructorKind
     273        && m_isArrowFunctionBodyExpression == other.m_isArrowFunctionBodyExpression
     274        && m_position == other.m_position;
     275}
     276
     277void FunctionMetadataNode::dump(PrintStream& stream) const
     278{
     279    stream.println("m_ident ", m_ident);
     280    stream.println("m_ecmaName ", m_ecmaName);
     281    stream.println("m_inferredName ", m_inferredName);
     282    stream.println("m_functionMode ", static_cast<uint32_t>(m_functionMode));
     283    stream.println("m_startColumn ", m_startColumn);
     284    stream.println("m_endColumn ", m_endColumn);
     285    stream.println("m_functionKeywordStart ", m_functionKeywordStart);
     286    stream.println("m_functionNameStart ", m_functionNameStart);
     287    stream.println("m_parametersStart ", m_parametersStart);
     288    stream.println("m_classSource.isNull() ", m_classSource.isNull());
     289    stream.println("m_startStartOffset ", m_startStartOffset);
     290    stream.println("m_parameterCount ", m_parameterCount);
     291    stream.println("m_lastLine ", m_lastLine);
     292    stream.println("m_parseMode ", static_cast<uint32_t>(m_parseMode));
     293    stream.println("m_isInStrictContext ", m_isInStrictContext);
     294    stream.println("m_superBinding ", m_superBinding);
     295    stream.println("m_constructorKind ", m_constructorKind);
     296    stream.println("m_isArrowFunctionBodyExpression ", m_isArrowFunctionBodyExpression);
     297    stream.println("position().line ", position().line);
     298    stream.println("position().offset ", position().offset);
     299    stream.println("position().lineStartOffset ", position().lineStartOffset);
    228300}
    229301
Note: See TracChangeset for help on using the changeset viewer.