Bug 153293

Summary: Current implementation of Parser::createSavePoint is a foot gun
Product: WebKit Reporter: Saam Barati <saam>
Component: JavaScriptCoreAssignee: Saam Barati <saam>
Status: RESOLVED FIXED    
Severity: Normal CC: benjamin, commit-queue, fpizlo, ggaren, gskachkov, keith_miller, mark.lam, msaboff, oliver, rniwa, sukolsak, ysuzuki
Priority: P2    
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
patch
none
patch
none
patch
none
patch none

Description Saam Barati 2016-01-20 16:06:18 PST
We often create a SavePoint, and restore it, when we really want to do more.
Often we want to save and restore some internal fields and not just lexer state.
Comment 1 Oliver Hunt 2016-01-20 16:08:46 PST
SavePoint should be saving everything necessary - I'm not saying it is, i'm saying that the whole point of it is to do that. SavePoint should not be a footgun, it should just be "correct"

The correct solution is probably to put all parser state, and all lever state, into structs so that SavePoint can just do a struct copy and not worry about things going out of sync.
Comment 2 Saam Barati 2016-01-20 16:29:04 PST
Created attachment 269400 [details]
patch
Comment 3 Saam Barati 2016-01-20 16:30:48 PST
(In reply to comment #1)
> SavePoint should be saving everything necessary - I'm not saying it is, i'm
> saying that the whole point of it is to do that. SavePoint should not be a
> footgun, it should just be "correct"
I agree. SavePoint should just work. I've renamed the old SavePoint
to LexerState and made the new SavePoint LexerState+ParserState.
Comment 4 Saam Barati 2016-01-20 16:33:24 PST
(In reply to comment #1)

> The correct solution is probably to put all parser state, and all lever
> state, into structs so that SavePoint can just do a struct copy and not
> worry about things going out of sync.
That's a good idea. I'll change it so that Parser now owns
a ParserState. It might not be as clean to have LexerState
be this way.
Comment 5 Saam Barati 2016-01-20 16:46:39 PST
Created attachment 269402 [details]
patch
Comment 6 Saam Barati 2016-01-20 16:54:44 PST
Created attachment 269403 [details]
patch

renamed the bug
Comment 7 Oliver Hunt 2016-01-20 17:24:12 PST
Comment on attachment 269403 [details]
patch

View in context: https://bugs.webkit.org/attachment.cgi?id=269403&action=review

> Source/JavaScriptCore/parser/Parser.h:1302
> +    ALWAYS_INLINE LexerState saveLexerState()

An idea: make this internalSaveLexerState, make it private, make SavePoint a friend of lexer, and have SavePoint have a saveLexerState(Lexer*) function that calls it.

But that's a somewhat convoluted so maybe not worth it?

> Source/JavaScriptCore/parser/Parser.h:1368
>      const Identifier* m_lastIdentifier;
>      const Identifier* m_lastFunctionName;

We should probably pull all of these into parser state. What's the rational for not doing so?
Comment 8 Saam Barati 2016-01-21 13:12:53 PST
Comment on attachment 269403 [details]
patch

View in context: https://bugs.webkit.org/attachment.cgi?id=269403&action=review

>> Source/JavaScriptCore/parser/Parser.h:1302
>> +    ALWAYS_INLINE LexerState saveLexerState()
> 
> An idea: make this internalSaveLexerState, make it private, make SavePoint a friend of lexer, and have SavePoint have a saveLexerState(Lexer*) function that calls it.
> 
> But that's a somewhat convoluted so maybe not worth it?

Ok. The reason I did it this way is that there are a few places where we only need to 
save lexer information (i.e, one token lookahead).
That said, I think it's still somewhat of a footgun to have this. Let me see
what the performance is if we always use SavePoints.

>> Source/JavaScriptCore/parser/Parser.h:1368
>>      const Identifier* m_lastFunctionName;
> 
> We should probably pull all of these into parser state. What's the rational for not doing so?

I thought about this, and I think for correctness/completeness, we should have it.
We also might want m_statementDepth there, too, even though we sometimes 
manage manually with DepthManager.
Comment 9 Saam Barati 2016-01-22 10:42:56 PST
It's perf neutral to always use SavePoints.
Going to do that.
I'm going to rename saveLexerState to internalSaveLexerState, but
I'm going to keep it a Parser method because it consults Parser's fields.
Comment 10 Saam Barati 2016-01-22 11:43:24 PST
Created attachment 269594 [details]
patch
Comment 11 WebKit Commit Bot 2016-01-22 14:52:52 PST
Comment on attachment 269594 [details]
patch

Clearing flags on attachment: 269594

Committed r195484: <http://trac.webkit.org/changeset/195484>
Comment 12 WebKit Commit Bot 2016-01-22 14:52:56 PST
All reviewed patches have been landed.  Closing bug.
Comment 13 Ryosuke Niwa 2016-02-21 09:57:45 PST
This regressed Dromaeo CSS selector tests by 2.5%.
Comment 14 Saam Barati 2016-03-22 18:33:59 PDT
(In reply to comment #13)
> This regressed Dromaeo CSS selector tests by 2.5%.

Writing this for the record.

This patch didn't actually regress Dromaeo. Our calculations
of performance showed a regression because this patch fixed a 
bug where one Dromaeo test wouldn't parse. Because it now passes
with this patch, we showed a regression.