Bug 68500

Summary: DFG does not support compiling functions as constructors
Product: WebKit Reporter: Filip Pizlo <fpizlo>
Component: JavaScriptCoreAssignee: Nobody <webkit-unassigned>
Status: RESOLVED FIXED    
Severity: Normal CC: rniwa
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: All   
OS: All   
Bug Depends on: 68642    
Bug Blocks:    
Attachments:
Description Flags
the patch oliver: review+

Description Filip Pizlo 2011-09-20 20:32:23 PDT
The optimizing compiler in JavaScriptCore can't compile constructors.  That should be fixed.
Comment 1 Filip Pizlo 2011-09-21 14:28:24 PDT
Created attachment 108234 [details]
the patch
Comment 2 Geoffrey Garen 2011-09-21 14:46:10 PDT
Comment on attachment 108234 [details]
the patch

r=me

> Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:1538
> +        SpeculateCellOperand proto(this, node.child1());

'this' is always a cell. Does the DFG know that? Something good to fix in a follow-up patch, if not. (SpeculateCellOperand here is fine, but you should make sure the branch gets elided under the covers.)

> Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:1563
> +        // Need to verify that the prototype is an object. If we have reason to believe
> +        // that it's a FinalObject then we speculate on that directly. Otherwise we
> +        // do the slow (structure-based) check.
> +        if (shouldSpeculateFinalObject(node.child1()))
> +            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr)));
> +        else {
> +            m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
> +            slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
> +        }
> +        
> +        // Load the inheritorID (the Structure that objects who have protoGPR as the prototype
> +        // use to refer to that prototype). If the inheritorID is not set, go to slow path.
> +        m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSObject::offsetOfInheritorID()), scratchGPR);
> +        slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, scratchGPR));

You could remove all of this loading and  branching in a follow-up patch if you made assignments to function.prototype eagerly jettison the function's constructor code.
Comment 3 Filip Pizlo 2011-09-21 14:58:05 PDT
> > Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:1538
> > +        SpeculateCellOperand proto(this, node.child1());
> 
> 'this' is always a cell. Does the DFG know that? Something good to fix in a follow-up patch, if not. (SpeculateCellOperand here is fine, but you should make sure the branch gets elided under the covers.)

The code you're referring to is speculating that the function.prototype is a cell.  Is that guaranteed?

> 
> > Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:1563
> > +        // Need to verify that the prototype is an object. If we have reason to believe
> > +        // that it's a FinalObject then we speculate on that directly. Otherwise we
> > +        // do the slow (structure-based) check.
> > +        if (shouldSpeculateFinalObject(node.child1()))
> > +            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr)));
> > +        else {
> > +            m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
> > +            slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
> > +        }
> > +        
> > +        // Load the inheritorID (the Structure that objects who have protoGPR as the prototype
> > +        // use to refer to that prototype). If the inheritorID is not set, go to slow path.
> > +        m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSObject::offsetOfInheritorID()), scratchGPR);
> > +        slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, scratchGPR));
> 
> You could remove all of this loading and  branching in a follow-up patch if you made assignments to function.prototype eagerly jettison the function's constructor code.

That would be interesting.  It would have to be done carefully, like making sure that there is no way any other JS code can execute in the prologue of the constructor.  I think that this should be trivially true once you know that .prototype is not insane.

For now though, I'm going for softer targets.  Like all of the insanity on the put_by_id's that follow create_this.  We don't do anything special for them right now in DFG.
Comment 4 Filip Pizlo 2011-09-21 15:16:32 PDT
Landed in r95672.
Comment 5 Ryosuke Niwa 2011-09-22 10:49:23 PDT
It appears that this patch caused hundreds of tests to fail:
http://build.webkit.org/builders/SnowLeopard%20Intel%20Release%20%28Tests%29/builds/33283
Comment 6 Ryosuke Niwa 2011-09-22 10:49:35 PDT
It appears that this patch caused hundreds of tests to fail:
http://build.webkit.org/builders/SnowLeopard%20Intel%20Release%20%28Tests%29/builds/33283
Comment 7 Ryosuke Niwa 2011-09-22 10:52:29 PDT
I'm sorry but I have to roll out this patch for now. We're losing the entire test coverage due to this failure.