Bug 139533 - REGRESSION: Use of undefined CallFrame::ScopeChain value
Summary: REGRESSION: Use of undefined CallFrame::ScopeChain value
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: 528+ (Nightly build)
Hardware: All All
: P2 Normal
Assignee: Michael Saboff
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2014-12-11 00:10 PST by Michael Saboff
Modified: 2014-12-11 18:50 PST (History)
3 users (show)

See Also:


Attachments
Patch (28.47 KB, patch)
2014-12-11 01:06 PST, Michael Saboff
mark.lam: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Saboff 2014-12-11 00:10:04 PST
The CallFrame ScopeChain slot is still being read and written, even though the JSScope* value is now being stored in an allocated register.  When the DFG inlines functions and then one of those inlined functions OSR exits, the ScopeChain slots for the callee's that were inlined will contain whatever values are in memory.  The memory for the ScopeChain slots will contain values from the registers allocated by the DFG for the main and inlined functions.

The problem is that there is some other residual code elsewhere that assumes that the scope slot of the header contains valid and appropriate JSScope* values.  Currently the main code paths that read and write the ScopeChain slot in the CallFrame header and the code paths for making calls.  They are still copying from the caller’s scope slot to the callee’s scope slot.  The DFG doesn’t know anything special about the scope slots.

The fix is to eliminate all the vestige code that reads / writes the old scope slot in the header and then get rid of the space in the header.

<rdar://problem/19194440>
Comment 1 Michael Saboff 2014-12-11 01:06:11 PST
Created attachment 243109 [details]
Patch
Comment 2 Mark Lam 2014-12-11 06:50:53 PST
Comment on attachment 243109 [details]
Patch

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

r=me with suggested cleanup in ChangeLog and CallFrame.h.

> Source/JavaScriptCore/ChangeLog:13
> +        Removed CallFrame::scope() and CallFrame::setScope() and eliminated or changed
> +        all usages of these funcitons.  In some cases the scope is passed in or determined
> +        another way.  In some cases the scope is used to calculate other values.  Lastly
> +        were places where these functions where used that are no longer needed.  For
> +        example when making a call, the caller's ScopeChain was copied to the callee's
> +        ScopeChain.

I think it’s implicitly stated here, but can you please say it explicitly that though you are removing the CallFrame scope getter/setter functions:
1. the ScopeChain slot still exists in the CallFrame
2. it just won’t be used anymore
3. it’ll be removed later

Did I understand this correctly?

> Source/JavaScriptCore/interpreter/CallFrame.h:191
> +        ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, JSScope*,

Why not remove the JSScope* arg altogether?

> Source/JavaScriptCore/jit/JITOpcodes32_64.cpp:905
> +    callOperation(operationCreateActivation, regT0, 0);

It seems wrong to me that we always pass a literal constant 0 for the offset of activation register.  Either:
1. it is contractually fixed to be constant 0 and we don’t need to pass it, or
2. we should “compute” the value.

But I understand that this is pre-existing code, and can be cleaned up in a separate patch.

> Source/JavaScriptCore/jit/JITOpcodes.cpp:676
> +    callOperation(operationCreateActivation, regT0, 0);

Ditto.
Comment 3 Michael Saboff 2014-12-11 07:44:02 PST
(In reply to comment #2)
> Comment on attachment 243109 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=243109&action=review
> 
> r=me with suggested cleanup in ChangeLog and CallFrame.h.
> 
> > Source/JavaScriptCore/ChangeLog:13
> > +        Removed CallFrame::scope() and CallFrame::setScope() and eliminated or changed
> > +        all usages of these funcitons.  In some cases the scope is passed in or determined
> > +        another way.  In some cases the scope is used to calculate other values.  Lastly
> > +        were places where these functions where used that are no longer needed.  For
> > +        example when making a call, the caller's ScopeChain was copied to the callee's
> > +        ScopeChain.
> 
> I think it’s implicitly stated here, but can you please say it explicitly
> that though you are removing the CallFrame scope getter/setter functions:
> 1. the ScopeChain slot still exists in the CallFrame
> 2. it just won’t be used anymore
> 3. it’ll be removed later
> 
> Did I understand this correctly?

You understand correctly and I'll add appropriate comments to the ChangeLog.

> > Source/JavaScriptCore/interpreter/CallFrame.h:191
> > +        ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, JSScope*,
> 
> Why not remove the JSScope* arg altogether?

Will do.

> > Source/JavaScriptCore/jit/JITOpcodes32_64.cpp:905
> > +    callOperation(operationCreateActivation, regT0, 0);
> 
> It seems wrong to me that we always pass a literal constant 0 for the offset
> of activation register.  Either:
> 1. it is contractually fixed to be constant 0 and we don’t need to pass it,
> or
> 2. we should “compute” the value.
> 
> But I understand that this is pre-existing code, and can be cleaned up in a
> separate patch.
> 
> > Source/JavaScriptCore/jit/JITOpcodes.cpp:676
> > +    callOperation(operationCreateActivation, regT0, 0);
> 
> Ditto.

The literal 0 in these two locations are existing.  The DFG computes a value, but the baseline always uses 0.  This appears to be by design.
Comment 4 Michael Saboff 2014-12-11 07:52:49 PST
(In reply to comment #3)

> > > Source/JavaScriptCore/interpreter/CallFrame.h:191
> > > +        ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, JSScope*,
> > 
> > Why not remove the JSScope* arg altogether?

init() was dead code, so I deleted the whole function.
Comment 5 Michael Saboff 2014-12-11 08:40:52 PST
Committed r177146: <http://trac.webkit.org/changeset/177146>
Comment 6 Carlos Alberto Lopez Perez 2014-12-11 09:08:56 PST
(In reply to comment #5)
> Committed r177146: <http://trac.webkit.org/changeset/177146>

This has broken the GTK and EFL builds: https://build.webkit.org/builders/GTK%20Linux%2064-bit%20Release%20%28Build%29/builds/53500/steps/compile-webkit/logs/stdio
Comment 7 Mark Lam 2014-12-11 09:11:58 PST
(In reply to comment #4)
> init() was dead code, so I deleted the whole function.

init() is still in use buy JSGlobalObject.cpp to create the globalExec.  This broke the build.  I restored CallFrame::init() minus the JSScope* arg, and also removed the arg from the caller.

Build fix landed in r177149: <http://trac.webkit.org/r177149>.
Comment 8 Carlos Alberto Lopez Perez 2014-12-11 09:40:36 PST
(In reply to comment #7)
> (In reply to comment #4)
> > init() was dead code, so I deleted the whole function.
> 
> init() is still in use buy JSGlobalObject.cpp to create the globalExec. 
> This broke the build.  I restored CallFrame::init() minus the JSScope* arg,
> and also removed the arg from the caller.
> 
> Build fix landed in r177149: <http://trac.webkit.org/r177149>.

Worked :) Thanks!
Comment 9 Michael Saboff 2014-12-11 09:42:02 PST
(In reply to comment #7)
> (In reply to comment #4)
> > init() was dead code, so I deleted the whole function.
> 
> init() is still in use buy JSGlobalObject.cpp to create the globalExec. 
> This broke the build.  I restored CallFrame::init() minus the JSScope* arg,
> and also removed the arg from the caller.
> 
> Build fix landed in r177149: <http://trac.webkit.org/r177149>.

Thanks.  My bad.
Comment 10 Geoffrey Garen 2014-12-11 14:23:40 PST
This patch really should not have been r+ed without a regression test. Michael, please write a regression test.
Comment 11 Mark Lam 2014-12-11 18:50:27 PST
(In reply to comment #10)
> This patch really should not have been r+ed without a regression test.
> Michael, please write a regression test.

To follow up, Michael has added the regression test in http://trac.webkit.org/changeset/177203.