WebKit Bugzilla
Attachment 343871 Details for
Bug 184074
: We shouldn't recurse into the parser when gathering metadata about various function offsets
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
patch
a-backup.diff (text/plain), 32.65 KB, created by
Saam Barati
on 2018-06-28 16:51:10 PDT
(
hide
)
Description:
patch
Filename:
MIME Type:
Creator:
Saam Barati
Created:
2018-06-28 16:51:10 PDT
Size:
32.65 KB
patch
obsolete
>Index: JSTests/ChangeLog >=================================================================== >--- JSTests/ChangeLog (revision 233338) >+++ JSTests/ChangeLog (working copy) >@@ -1,3 +1,28 @@ >+2018-06-28 Saam Barati <sbarati@apple.com> >+ >+ 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 NOBODY (OOPS!). >+ >+ * 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. >+ (runNearStackLimit.t): >+ (runNearStackLimit): >+ (__f_690.switch.case.1.switch.catch.prototype.catch): >+ (prototype.runNearStackLimit): >+ (prototype.return.__f_690): >+ * stress/is-constructor.js: >+ * stress/tailCallForwardArguments.js: >+ (putFuncToPrivateName.createBuiltin): >+ > 2018-06-27 Mark Lam <mark.lam@apple.com> > > DFG's compileReallocatePropertyStorage() and compileAllocatePropertyStorage() slow paths should also clear unused properties. >Index: JSTests/microbenchmarks/try-get-by-id-basic.js >=================================================================== >--- JSTests/microbenchmarks/try-get-by-id-basic.js (revision 233316) >+++ JSTests/microbenchmarks/try-get-by-id-basic.js (working copy) >@@ -8,7 +8,7 @@ const check = (got, expect) => { if (got > > const bench = f => { > // Re-create the builtin each time, so each benchmark gets its own value prediction. >- const fooPlusBar = createBuiltin(`(function(o) { return @tryGetById(o, "foo") + @tryGetById(o, "bar"); })`); >+ const fooPlusBar = createBuiltin(`(function (o) { return @tryGetById(o, "foo") + @tryGetById(o, "bar"); })`); > noInline(fooPlusBar); > f(fooPlusBar); > } >Index: JSTests/microbenchmarks/try-get-by-id-polymorphic.js >=================================================================== >--- JSTests/microbenchmarks/try-get-by-id-polymorphic.js (revision 233316) >+++ JSTests/microbenchmarks/try-get-by-id-polymorphic.js (working copy) >@@ -6,7 +6,7 @@ var it = 1e5; > > const check = (got, expect) => { if (got != expect) throw "Error: bad result got " + got + " expected " + expect; }; > >-fooPlusBar = createBuiltin(`(function(o) { return @tryGetById(o, "foo") + @tryGetById(o, "bar"); })`); >+fooPlusBar = createBuiltin(`(function (o) { return @tryGetById(o, "foo") + @tryGetById(o, "bar"); })`); > noInline(fooPlusBar); > > const bench = f => { f(); } >Index: JSTests/stress/array-push-with-force-exit.js >=================================================================== >--- JSTests/stress/array-push-with-force-exit.js (revision 233316) >+++ JSTests/stress/array-push-with-force-exit.js (working copy) >@@ -1,6 +1,6 @@ > var createBuiltin = $vm.createBuiltin; > >-var target = createBuiltin(`(function(array) >+var target = createBuiltin(`(function (array) > { > if (array) { > @idWithProfile(array, "SpecOther").push(42); >Index: JSTests/stress/dont-crash-on-stack-overflow-when-parsing-builtin.js >=================================================================== >--- JSTests/stress/dont-crash-on-stack-overflow-when-parsing-builtin.js (nonexistent) >+++ JSTests/stress/dont-crash-on-stack-overflow-when-parsing-builtin.js (working copy) >@@ -0,0 +1,13 @@ >+//@ runDefault("--maxPerThreadStackUsage=10000", "--reservedZoneSize=0") >+ >+function f() { >+ try { >+ f(); >+ } catch (e) { >+ try { >+ Map.prototype.forEach.call('', {}); >+ } catch (e) {} >+ } >+} >+ >+f() >Index: JSTests/stress/dont-crash-on-stack-overflow-when-parsing-default-constructor.js >=================================================================== >--- JSTests/stress/dont-crash-on-stack-overflow-when-parsing-default-constructor.js (nonexistent) >+++ JSTests/stress/dont-crash-on-stack-overflow-when-parsing-default-constructor.js (working copy) >@@ -0,0 +1,31 @@ >+//@ runDefault("--maxPerThreadStackUsage=10000", "--reservedZoneSize=0") >+ >+function runNearStackLimit(f) { >+ function t() { >+ try { >+ return t(); >+ } catch (e) { >+ return f(); >+ } >+ } >+ return t() >+} >+function __f_690() { >+ switch (__v_2951) { >+ case 1: >+ switch (__v_2952) { >+ case 434: >+ try { >+ } catch (__v_3322) { >+ try { >+ new class extends (class {}, {}) {}(); >+ } catch (e) {} >+ } >+ } >+ } >+} >+runNearStackLimit(() => { >+ return __f_690(); >+}) >+{ >+}; >Index: JSTests/stress/is-constructor.js >=================================================================== >--- JSTests/stress/is-constructor.js (revision 233316) >+++ JSTests/stress/is-constructor.js (working copy) >@@ -5,7 +5,7 @@ function assert(x) { > throw Error("Bad"); > } > >-let isConstructor = createBuiltin("(function(c) { return @isConstructor(c); })"); >+let isConstructor = createBuiltin("(function (c) { return @isConstructor(c); })"); > > // Functions. > assert(isConstructor(assert)); >Index: JSTests/stress/tailCallForwardArguments.js >=================================================================== >--- JSTests/stress/tailCallForwardArguments.js (revision 233316) >+++ JSTests/stress/tailCallForwardArguments.js (working copy) >@@ -1,7 +1,7 @@ > var createBuiltin = $vm.createBuiltin; > > // This is pretty bad but I need a private name. >-var putFuncToPrivateName = createBuiltin(`(function(func) { @arrayIteratorIsDone = func })`) >+var putFuncToPrivateName = createBuiltin(`(function (func) { @arrayIteratorIsDone = func })`) > putFuncToPrivateName(function (a,b) { return b; }) > > function createTailCallForwardingFuncWith(body, thisValue) { >Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 233316) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,57 @@ >+2018-06-28 Saam Barati <sbarati@apple.com> >+ >+ 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 NOBODY (OOPS!). >+ >+ 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. >+ > 2018-06-27 Saam Barati <sbarati@apple.com> > > Add some more register state information when we crash in repatchPutById >Index: Source/JavaScriptCore/builtins/AsyncFromSyncIteratorPrototype.js >=================================================================== >--- Source/JavaScriptCore/builtins/AsyncFromSyncIteratorPrototype.js (revision 233316) >+++ Source/JavaScriptCore/builtins/AsyncFromSyncIteratorPrototype.js (working copy) >@@ -151,6 +151,8 @@ function throw(exception) > @globalPrivate > function createAsyncFromSyncIterator(syncIterator, nextMethod) > { >+ "use strict"; >+ > if (!@isObject(syncIterator)) > @throwTypeError('Only objects can be wrapped by async-from-sync wrapper'); > >@@ -161,6 +163,8 @@ function createAsyncFromSyncIterator(syn > @constructor > function AsyncFromSyncIteratorConstructor(syncIterator, nextMethod) > { >+ "use strict"; >+ > @putByIdDirectPrivate(this, "syncIterator", syncIterator); > @putByIdDirectPrivate(this, "nextMethod", nextMethod); > } >Index: Source/JavaScriptCore/builtins/BuiltinExecutables.cpp >=================================================================== >--- Source/JavaScriptCore/builtins/BuiltinExecutables.cpp (revision 233316) >+++ Source/JavaScriptCore/builtins/BuiltinExecutables.cpp (working copy) >@@ -85,40 +85,175 @@ UnlinkedFunctionExecutable* createBuilti > > UnlinkedFunctionExecutable* BuiltinExecutables::createExecutable(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility) > { >+ // Someone should get mad at me for writing this code. But, it prevents us from recursing into >+ // the parser, and hence, from throwing OOM/stack overflow when parsing a builtin. >+ StringView view = source.view(); >+ RELEASE_ASSERT(!view.isNull()); >+ RELEASE_ASSERT(view.is8Bit()); >+ auto* characters = view.characters8(); >+ RELEASE_ASSERT(view.length() >= 14); // strlen("(function(){})") == 14 >+ RELEASE_ASSERT(characters[0] == '('); >+ RELEASE_ASSERT(characters[1] == 'f'); >+ RELEASE_ASSERT(characters[2] == 'u'); >+ RELEASE_ASSERT(characters[3] == 'n'); >+ RELEASE_ASSERT(characters[4] == 'c'); >+ RELEASE_ASSERT(characters[5] == 't'); >+ RELEASE_ASSERT(characters[6] == 'i'); >+ RELEASE_ASSERT(characters[7] == 'o'); >+ RELEASE_ASSERT(characters[8] == 'n'); >+ RELEASE_ASSERT(characters[9] == ' '); >+ RELEASE_ASSERT(characters[10] == '('); >+ >+ JSTokenLocation start; >+ start.line = -1; >+ start.lineStartOffset = -1; >+ start.startOffset = 10; >+ start.endOffset = -1; >+ >+ JSTokenLocation end; >+ end.line = 1; >+ end.lineStartOffset = 0; >+ end.startOffset = 1; >+ end.endOffset = -1; >+ >+ unsigned startColumn = 10; // strlen("function (") == 10 >+ int functionKeywordStart = 1; // (f >+ int functionNameStart = 10; >+ int parametersStart = 10; >+ bool isInStrictContext = false; >+ bool isArrowFunctionBodyExpression = false; >+ >+ unsigned parameterCount; >+ { >+ unsigned i = 11; >+ unsigned commas = 0; >+ bool sawOneParam = false; >+ bool hasRestParam = false; >+ while (true) { >+ ASSERT(i < view.length()); >+ if (characters[i] == ')') >+ break; >+ >+ if (characters[i] == ',') >+ ++commas; >+ else if (!Lexer<LChar>::isWhiteSpace(characters[i])) >+ sawOneParam = true; >+ >+ if (i + 2 < view.length() && characters[i] == '.' && characters[i + 1] == '.' && characters[i + 2] == '.') >+ hasRestParam = true; >+ >+ ++i; >+ } >+ >+ if (commas) >+ parameterCount = commas + 1; >+ else if (sawOneParam) >+ parameterCount = 1; >+ else >+ parameterCount = 0; >+ >+ if (hasRestParam) { >+ RELEASE_ASSERT(parameterCount); >+ --parameterCount; >+ } >+ } >+ >+ unsigned lineCount = 0; >+ unsigned endColumn = 0; >+ unsigned offsetOfLastNewline = 0; >+ for (unsigned i = 0; i < view.length(); ++i) { >+ if (characters[i] == '\n') { >+ ++lineCount; >+ endColumn = 0; >+ offsetOfLastNewline = i; >+ } else >+ ++endColumn; >+ >+ if (!isInStrictContext && (characters[i] == '"' || characters[i] == '\'')) { >+ if (i + 1 + strlen("use strict") <= view.length()) { >+ if (!memcmp(characters + i + 1, "use strict", strlen("use strict"))) >+ isInStrictContext = true; >+ } >+ } >+ } >+ >+ int closeBraceOffsetFromEnd = 1; >+ while (true) { >+ if (characters[view.length() - closeBraceOffsetFromEnd] == '}') >+ break; >+ ++closeBraceOffsetFromEnd; >+ } >+ >+ unsigned positionBeforeLastNewlineLineStartOffset = 0; // This is the second to last newline + 1. >+ for (int i = offsetOfLastNewline - 1; true; ) { >+ if (i < 0) >+ break; >+ if (characters[i] == '\n') { >+ positionBeforeLastNewlineLineStartOffset = i + 1; >+ break; >+ } >+ --i; >+ } >+ > JSTextPosition positionBeforeLastNewline; >- ParserError error; >+ positionBeforeLastNewline.line = lineCount; >+ positionBeforeLastNewline.offset = offsetOfLastNewline; >+ positionBeforeLastNewline.lineStartOffset = positionBeforeLastNewlineLineStartOffset; >+ >+ SourceCode newSource = source.subExpression(10, view.length() - closeBraceOffsetFromEnd, 0, 10); > bool isBuiltinDefaultClassConstructor = constructorKind != ConstructorKind::None; >- JSParserBuiltinMode builtinMode = isBuiltinDefaultClassConstructor ? JSParserBuiltinMode::NotBuiltin : JSParserBuiltinMode::Builtin; > UnlinkedFunctionKind kind = isBuiltinDefaultClassConstructor ? UnlinkedNormalFunction : UnlinkedBuiltinFunction; >- std::unique_ptr<ProgramNode> program = parse<ProgramNode>( >- &vm, source, Identifier(), builtinMode, >- JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, error, >- &positionBeforeLastNewline, constructorKind); >- >- if (!program) { >- dataLog("Fatal error compiling builtin function '", name.string(), "': ", error.message()); >- CRASH(); >+ >+ FunctionMetadataNode metadata( >+ start, end, startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, >+ isInStrictContext, constructorKind, constructorKind == ConstructorKind::Extends ? SuperBinding::Needed : SuperBinding::NotNeeded, >+ parameterCount, SourceParseMode::NormalFunctionMode, isArrowFunctionBodyExpression); >+ >+ metadata.finishParsing(newSource, Identifier(), FunctionMode::FunctionExpression); >+ metadata.overrideName(name); >+ metadata.setEndPosition(positionBeforeLastNewline); >+ >+ if (!ASSERT_DISABLED || Options::validateBytecode()) { >+ JSTextPosition positionBeforeLastNewlineFromParser; >+ ParserError error; >+ JSParserBuiltinMode builtinMode = isBuiltinDefaultClassConstructor ? JSParserBuiltinMode::NotBuiltin : JSParserBuiltinMode::Builtin; >+ std::unique_ptr<ProgramNode> program = parse<ProgramNode>( >+ &vm, source, Identifier(), builtinMode, >+ JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, error, >+ &positionBeforeLastNewlineFromParser, constructorKind); >+ >+ if (program) { >+ StatementNode* exprStatement = program->singleStatement(); >+ RELEASE_ASSERT(exprStatement); >+ RELEASE_ASSERT(exprStatement->isExprStatement()); >+ ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr(); >+ RELEASE_ASSERT(funcExpr); >+ RELEASE_ASSERT(funcExpr->isFuncExprNode()); >+ FunctionMetadataNode* metadataFromParser = static_cast<FuncExprNode*>(funcExpr)->metadata(); >+ RELEASE_ASSERT(!program->hasCapturedVariables()); >+ >+ metadataFromParser->setEndPosition(positionBeforeLastNewlineFromParser); >+ RELEASE_ASSERT(metadataFromParser); >+ RELEASE_ASSERT(metadataFromParser->ident().isNull()); >+ >+ // This function assumes an input string that would result in a single anonymous function expression. >+ metadataFromParser->setEndPosition(positionBeforeLastNewlineFromParser); >+ RELEASE_ASSERT(metadataFromParser); >+ metadataFromParser->overrideName(name); >+ metadataFromParser->setEndPosition(positionBeforeLastNewlineFromParser); >+ >+ if (metadata != *metadataFromParser || positionBeforeLastNewlineFromParser != positionBeforeLastNewline) { >+ WTFLogAlways("Metadata of parser and hand rolled parser don't match\n"); >+ CRASH(); >+ } >+ } else { >+ RELEASE_ASSERT(error.isValid()); >+ RELEASE_ASSERT(error.type() == ParserError::StackOverflow); >+ } > } > >- StatementNode* exprStatement = program->singleStatement(); >- RELEASE_ASSERT(exprStatement); >- RELEASE_ASSERT(exprStatement->isExprStatement()); >- ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr(); >- RELEASE_ASSERT(funcExpr); >- RELEASE_ASSERT(funcExpr->isFuncExprNode()); >- FunctionMetadataNode* metadata = static_cast<FuncExprNode*>(funcExpr)->metadata(); >- RELEASE_ASSERT(!program->hasCapturedVariables()); >- >- metadata->setEndPosition(positionBeforeLastNewline); >- RELEASE_ASSERT(metadata); >- RELEASE_ASSERT(metadata->ident().isNull()); >- >- // This function assumes an input string that would result in a single anonymous function expression. >- metadata->setEndPosition(positionBeforeLastNewline); >- RELEASE_ASSERT(metadata); >- metadata->overrideName(name); > VariableEnvironment dummyTDZVariables; >- UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, kind, constructAbility, JSParserScriptMode::Classic, dummyTDZVariables, DerivedContextType::None, isBuiltinDefaultClassConstructor); >+ UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, &metadata, kind, constructAbility, JSParserScriptMode::Classic, dummyTDZVariables, DerivedContextType::None, isBuiltinDefaultClassConstructor); > return functionExecutable; > } > >Index: Source/JavaScriptCore/builtins/GlobalOperations.js >=================================================================== >--- Source/JavaScriptCore/builtins/GlobalOperations.js (revision 233316) >+++ Source/JavaScriptCore/builtins/GlobalOperations.js (working copy) >@@ -62,12 +62,15 @@ function isDictionary(object) > @overriddenName="get [Symbol.species]" > function speciesGetter() > { >+ "use strict"; > return this; > } > > @globalPrivate > function speciesConstructor(obj, defaultConstructor) > { >+ "use strict"; >+ > var constructor = obj.constructor; > if (constructor === @undefined) > return defaultConstructor; >@@ -84,6 +87,8 @@ function speciesConstructor(obj, default > @globalPrivate > function copyDataProperties(target, source, excludedSet) > { >+ "use strict"; >+ > if (!@isObject(target)) > @throwTypeError("target needs to be an object"); > >@@ -109,6 +114,8 @@ function copyDataProperties(target, sour > @globalPrivate > function copyDataPropertiesNoExclusions(target, source) > { >+ "use strict"; >+ > if (!@isObject(target)) > @throwTypeError("target needs to be an object"); > >Index: Source/JavaScriptCore/builtins/PromiseOperations.js >=================================================================== >--- Source/JavaScriptCore/builtins/PromiseOperations.js (revision 233316) >+++ Source/JavaScriptCore/builtins/PromiseOperations.js (working copy) >@@ -87,6 +87,7 @@ function newPromiseCapability(constructo > @globalPrivate > function newHandledRejectedPromise(error) > { >+ "use strict"; > let promise = @Promise.@reject(error); > @putByIdDirectPrivate(promise, "promiseIsHandled", true); > return promise; >Index: Source/JavaScriptCore/builtins/RegExpPrototype.js >=================================================================== >--- Source/JavaScriptCore/builtins/RegExpPrototype.js (revision 233316) >+++ Source/JavaScriptCore/builtins/RegExpPrototype.js (working copy) >@@ -63,7 +63,10 @@ function regExpExec(regexp, str) > } > > @globalPrivate >-function hasObservableSideEffectsForRegExpMatch(regexp) { >+function hasObservableSideEffectsForRegExpMatch(regexp) >+{ >+ "use strict"; >+ > // This is accessed by the RegExpExec internal function. > let regexpExec = @tryGetById(regexp, "exec"); > if (regexpExec !== @regExpBuiltinExec) >@@ -351,7 +354,10 @@ function search(strArg) > } > > @globalPrivate >-function hasObservableSideEffectsForRegExpSplit(regexp) { >+function hasObservableSideEffectsForRegExpSplit(regexp) >+{ >+ "use strict"; >+ > // This is accessed by the RegExpExec internal function. > let regexpExec = @tryGetById(regexp, "exec"); > if (regexpExec !== @regExpBuiltinExec) >Index: Source/JavaScriptCore/builtins/StringPrototype.js >=================================================================== >--- Source/JavaScriptCore/builtins/StringPrototype.js (revision 233316) >+++ Source/JavaScriptCore/builtins/StringPrototype.js (working copy) >@@ -191,7 +191,10 @@ function padEnd(maxLength/*, fillString* > } > > @globalPrivate >-function hasObservableSideEffectsForStringReplace(regexp, replacer) { >+function hasObservableSideEffectsForStringReplace(regexp, replacer) >+{ >+ "use strict"; >+ > if (replacer !== @regExpPrototypeSymbolReplace) > return true; > >@@ -235,6 +238,8 @@ function replace(search, replace) > @globalPrivate > function getDefaultCollator() > { >+ "use strict"; >+ > return @getDefaultCollator.collator || (@getDefaultCollator.collator = new @Collator()); > } > >Index: Source/JavaScriptCore/parser/Nodes.cpp >=================================================================== >--- Source/JavaScriptCore/parser/Nodes.cpp (revision 233316) >+++ Source/JavaScriptCore/parser/Nodes.cpp (working copy) >@@ -214,6 +214,29 @@ FunctionMetadataNode::FunctionMetadataNo > ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind)); > } > >+FunctionMetadataNode::FunctionMetadataNode( >+ const JSTokenLocation& startLocation, >+ const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, >+ int functionKeywordStart, int functionNameStart, int parametersStart, bool isInStrictContext, >+ ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression) >+ : Node(endLocation) >+ , m_startColumn(startColumn) >+ , m_endColumn(endColumn) >+ , m_functionKeywordStart(functionKeywordStart) >+ , m_functionNameStart(functionNameStart) >+ , m_parametersStart(parametersStart) >+ , m_startStartOffset(startLocation.startOffset) >+ , m_parameterCount(parameterCount) >+ , m_parseMode(mode) >+ , m_isInStrictContext(isInStrictContext) >+ , m_superBinding(static_cast<unsigned>(superBinding)) >+ , m_constructorKind(static_cast<unsigned>(constructorKind)) >+ , m_isArrowFunctionBodyExpression(isArrowFunctionBodyExpression) >+{ >+ ASSERT(m_superBinding == static_cast<unsigned>(superBinding)); >+ ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind)); >+} >+ > void FunctionMetadataNode::finishParsing(const SourceCode& source, const Identifier& ident, FunctionMode functionMode) > { > m_source = source; >@@ -227,6 +250,55 @@ void FunctionMetadataNode::setEndPositio > m_endColumn = position.offset - position.lineStartOffset; > } > >+bool FunctionMetadataNode::operator==(const FunctionMetadataNode& other) const >+{ >+ return m_ident == other.m_ident >+ && m_ecmaName == other.m_ecmaName >+ && m_inferredName == other.m_inferredName >+ && m_functionMode== other.m_functionMode >+ && m_startColumn== other.m_startColumn >+ && m_endColumn== other.m_endColumn >+ && m_functionKeywordStart== other.m_functionKeywordStart >+ && m_functionNameStart== other.m_functionNameStart >+ && m_parametersStart== other.m_parametersStart >+ && m_source== other.m_source >+ && m_classSource== other.m_classSource >+ && m_startStartOffset== other.m_startStartOffset >+ && m_parameterCount== other.m_parameterCount >+ && m_lastLine== other.m_lastLine >+ && m_parseMode== other.m_parseMode >+ && m_isInStrictContext == other.m_isInStrictContext >+ && m_superBinding == other.m_superBinding >+ && m_constructorKind == other.m_constructorKind >+ && m_isArrowFunctionBodyExpression == other.m_isArrowFunctionBodyExpression >+ && m_position == other.m_position; >+} >+ >+void FunctionMetadataNode::dump(PrintStream& stream) const >+{ >+ stream.println("m_ident ", m_ident); >+ stream.println("m_ecmaName ", m_ecmaName); >+ stream.println("m_inferredName ", m_inferredName); >+ stream.println("m_functionMode ", static_cast<uint32_t>(m_functionMode)); >+ stream.println("m_startColumn ", m_startColumn); >+ stream.println("m_endColumn ", m_endColumn); >+ stream.println("m_functionKeywordStart ", m_functionKeywordStart); >+ stream.println("m_functionNameStart ", m_functionNameStart); >+ stream.println("m_parametersStart ", m_parametersStart); >+ stream.println("m_classSource.isNull() ", m_classSource.isNull()); >+ stream.println("m_startStartOffset ", m_startStartOffset); >+ stream.println("m_parameterCount ", m_parameterCount); >+ stream.println("m_lastLine ", m_lastLine); >+ stream.println("m_parseMode ", static_cast<uint32_t>(m_parseMode)); >+ stream.println("m_isInStrictContext ", m_isInStrictContext); >+ stream.println("m_superBinding ", m_superBinding); >+ stream.println("m_constructorKind ", m_constructorKind); >+ stream.println("m_isArrowFunctionBodyExpression ", m_isArrowFunctionBodyExpression); >+ stream.println("position().line ", position().line); >+ stream.println("position().offset ", position().offset); >+ stream.println("position().lineStartOffset ", position().lineStartOffset); >+} >+ > // ------------------------------ FunctionNode ----------------------------- > > FunctionNode::FunctionNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters* parameters, const SourceCode& sourceCode, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&) >Index: Source/JavaScriptCore/parser/Nodes.h >=================================================================== >--- Source/JavaScriptCore/parser/Nodes.h (revision 233316) >+++ Source/JavaScriptCore/parser/Nodes.h (working copy) >@@ -1988,6 +1988,14 @@ namespace JSC { > int functionNameStart, int parametersStart, bool isInStrictContext, > ConstructorKind, SuperBinding, unsigned parameterCount, > SourceParseMode, bool isArrowFunctionBodyExpression); >+ FunctionMetadataNode( >+ const JSTokenLocation& start, const JSTokenLocation& end, >+ unsigned startColumn, unsigned endColumn, int functionKeywordStart, >+ int functionNameStart, int parametersStart, bool isInStrictContext, >+ ConstructorKind, SuperBinding, unsigned parameterCount, >+ SourceParseMode, bool isArrowFunctionBodyExpression); >+ >+ void dump(PrintStream&) const; > > void finishParsing(const SourceCode&, const Identifier&, FunctionMode); > >@@ -2028,7 +2036,13 @@ namespace JSC { > } > unsigned lastLine() const { return m_lastLine; } > >- protected: >+ bool operator==(const FunctionMetadataNode&) const; >+ bool operator!=(const FunctionMetadataNode& other) const >+ { >+ return !(*this == other); >+ } >+ >+ public: > Identifier m_ident; > Identifier m_ecmaName; > Identifier m_inferredName; >Index: Source/JavaScriptCore/parser/Parser.h >=================================================================== >--- Source/JavaScriptCore/parser/Parser.h (revision 233316) >+++ Source/JavaScriptCore/parser/Parser.h (working copy) >@@ -1964,8 +1964,11 @@ std::unique_ptr<ParsedNode> parse( > if (positionBeforeLastNewline) > *positionBeforeLastNewline = parser.positionBeforeLastNewline(); > if (builtinMode == JSParserBuiltinMode::Builtin) { >- if (!result) >- dataLogLn("Error compiling builtin: ", error.message()); >+ if (!result) { >+ ASSERT(error.isValid()); >+ if (error.type() != ParserError::StackOverflow) >+ dataLogLn("Unexpected error compiling builtin: ", error.message()); >+ } > } > } else { > ASSERT_WITH_MESSAGE(defaultConstructorKind == ConstructorKind::None, "BuiltinExecutables::createDefaultConstructor should always use a 8-bit string"); >Index: Source/JavaScriptCore/parser/ParserError.h >=================================================================== >--- Source/JavaScriptCore/parser/ParserError.h (revision 233316) >+++ Source/JavaScriptCore/parser/ParserError.h (working copy) >@@ -83,6 +83,7 @@ public: > const JSToken& token() const { return m_token; } > const String& message() const { return m_message; } > int line() const { return m_line; } >+ ErrorType type() const { return m_type; } > > JSObject* toErrorObject( > JSGlobalObject* globalObject, const SourceCode& source, >Index: Source/JavaScriptCore/parser/ParserTokens.h >=================================================================== >--- Source/JavaScriptCore/parser/ParserTokens.h (revision 233316) >+++ Source/JavaScriptCore/parser/ParserTokens.h (working copy) >@@ -202,6 +202,17 @@ struct JSTextPosition { > > operator int() const { return offset; } > >+ bool operator==(const JSTextPosition& other) const >+ { >+ return line == other.line >+ && offset == other.offset >+ && lineStartOffset == other.lineStartOffset; >+ } >+ bool operator!=(const JSTextPosition& other) const >+ { >+ return !(*this == other); >+ } >+ > int line; > int offset; > int lineStartOffset; >Index: Source/JavaScriptCore/parser/SourceCode.h >=================================================================== >--- Source/JavaScriptCore/parser/SourceCode.h (revision 233316) >+++ Source/JavaScriptCore/parser/SourceCode.h (working copy) >@@ -79,7 +79,21 @@ namespace JSC { > > SourceProvider* provider() const { return m_provider.get(); } > >- SourceCode subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn); >+ SourceCode subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn) const; >+ >+ bool operator==(const SourceCode& other) const >+ { >+ return m_firstLine == other.m_firstLine >+ && m_startColumn == other.m_startColumn >+ && m_provider == other.m_provider >+ && m_startOffset == other.m_startOffset >+ && m_endOffset == other.m_endOffset; >+ } >+ >+ bool operator!=(const SourceCode& other) const >+ { >+ return !(*this == other); >+ } > > private: > OrdinalNumber m_firstLine; >@@ -91,7 +105,7 @@ namespace JSC { > return SourceCode(StringSourceProvider::create(source, sourceOrigin, url, startPosition, sourceType), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt()); > } > >- inline SourceCode SourceCode::subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn) >+ inline SourceCode SourceCode::subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn) const > { > startColumn += 1; // Convert to base 1. > return SourceCode(RefPtr<SourceProvider> { provider() }, openBrace, closeBrace + 1, firstLine, startColumn);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
mark.lam
:
review+
ews-watchlist
:
commit-queue-
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 184074
:
336656
|
336770
|
336771
|
336775
|
336848
|
336849
|
338407
|
338584
|
339406
|
343216
|
343842
|
343871
|
343926
|
343927