128
128
import org .truffleruby .language .objects .PropertyFlags ;
129
129
import org .truffleruby .language .objects .ReadObjectFieldNode ;
130
130
import org .truffleruby .language .objects .ReadObjectFieldNodeGen ;
131
- import org .truffleruby .language .objects .SelfNode ;
132
131
import org .truffleruby .language .objects .ShapeCachingGuards ;
133
132
import org .truffleruby .language .objects .SingletonClassNode ;
134
133
import org .truffleruby .language .objects .TaintNode ;
@@ -571,13 +570,16 @@ public RubyRootNode getRootNode() {
571
570
}
572
571
}
573
572
574
- public abstract Object execute (VirtualFrame frame , Object self , DynamicObject str , DynamicObject binding , DynamicObject file , int line );
573
+ public abstract Object execute (VirtualFrame frame , Object self , DynamicObject source , DynamicObject binding , DynamicObject file , int line );
574
+
575
+ // If the source defines new local variables, those should be set in the Binding.
576
+ // So we have 2 specializations for whether or not the code defines new local variables.
575
577
576
578
@ Specialization (guards = {
577
579
"equalNode.execute(rope(source), cachedSource)" ,
578
580
"equalNode.execute(rope(file), cachedFile)" ,
579
581
"line == cachedLine" ,
580
- "assignsNoNewVariables( cachedRootNode)" ,
582
+ "!assignsNewUserVariables(getDescriptor( cachedRootNode) )" ,
581
583
"bindingDescriptor == getBindingDescriptor(binding)"
582
584
}, limit = "getCacheLimit()" )
583
585
public Object evalBindingNoAddsVarsCached (
@@ -602,8 +604,8 @@ public Object evalBindingNoAddsVarsCached(
602
604
"equalNode.execute(rope(source), cachedSource)" ,
603
605
"equalNode.execute(rope(file), cachedFile)" ,
604
606
"line == cachedLine" ,
605
- "!assignsNoNewVariables( cachedRootNode)" ,
606
- "assignsNoNewVariables( rootNodeToEval)" ,
607
+ "assignsNewUserVariables(getDescriptor( cachedRootNode) )" ,
608
+ "!assignsNewUserVariables(getDescriptor( rootNodeToEval) )" ,
607
609
"bindingDescriptor == getBindingDescriptor(binding)"
608
610
}, limit = "getCacheLimit()" )
609
611
public Object evalBindingAddsVarsCached (
@@ -617,13 +619,12 @@ public Object evalBindingAddsVarsCached(
617
619
@ Cached ("line" ) int cachedLine ,
618
620
@ Cached ("getBindingDescriptor(binding)" ) FrameDescriptor bindingDescriptor ,
619
621
@ Cached ("compileSource(cachedSource, getBindingFrame(binding), cachedFile, cachedLine)" ) RootNodeWrapper cachedRootNode ,
620
- @ Cached ("newBindingDescriptor(getContext(), cachedRootNode)" ) FrameDescriptor newBindingDescriptor ,
622
+ @ Cached ("getDescriptor( cachedRootNode).copy( )" ) FrameDescriptor newBindingDescriptor ,
621
623
@ Cached ("compileSource(cachedSource, getBindingFrame(binding), newBindingDescriptor, cachedFile, cachedLine)" ) RootNodeWrapper rootNodeToEval ,
622
624
@ Cached ("createCallTarget(rootNodeToEval)" ) RootCallTarget cachedCallTarget ,
623
625
@ Cached ("create(cachedCallTarget)" ) DirectCallNode callNode ,
624
626
@ Cached ("create()" ) RopeNodes .EqualNode equalNode ) {
625
- final MaterializedFrame parentFrame = BindingNodes .newFrame (binding ,
626
- newBindingDescriptor );
627
+ final MaterializedFrame parentFrame = BindingNodes .newFrame (binding , newBindingDescriptor );
627
628
return eval (self , rootNodeToEval , cachedCallTarget , callNode , parentFrame );
628
629
}
629
630
@@ -658,7 +659,7 @@ private CodeLoader.DeferredCall doEvalX(Object self, Rope source,
658
659
final DeclarationContext declarationContext = RubyArguments .getDeclarationContext (frame );
659
660
final FrameDescriptor descriptor = frame .getFrameDescriptor ();
660
661
RubyRootNode rootNode = buildRootNode (source , frame , file , line , false );
661
- if (! frameHasOnlySelf (descriptor )) {
662
+ if (assignsNewUserVariables (descriptor )) {
662
663
Layouts .BINDING .setFrame (binding , frame );
663
664
}
664
665
return getContext ().getCodeLoader ().prepareExecute (
@@ -687,32 +688,26 @@ protected FrameDescriptor getBindingDescriptor(DynamicObject binding) {
687
688
return BindingNodes .getFrameDescriptor (binding );
688
689
}
689
690
690
- protected FrameDescriptor newBindingDescriptor (RubyContext context , RootNodeWrapper rootNode ) {
691
- FrameDescriptor descriptor = rootNode .getRootNode ().getFrameDescriptor ();
692
- FrameDescriptor newDescriptor = new FrameDescriptor (context .getCoreLibrary ().getNil ());
693
- for (FrameSlot frameSlot : descriptor .getSlots ()) {
694
- newDescriptor .findOrAddFrameSlot (frameSlot .getIdentifier ());
695
- }
696
- return newDescriptor ;
691
+ protected FrameDescriptor getDescriptor (RootNodeWrapper rootNode ) {
692
+ return rootNode .getRootNode ().getFrameDescriptor ();
697
693
}
698
694
699
695
protected MaterializedFrame getBindingFrame (DynamicObject binding ) {
700
696
return BindingNodes .getFrame (binding );
701
697
}
702
698
703
- protected int getCacheLimit ( ) {
704
- return getContext (). getOptions (). EVAL_CACHE ;
705
- }
706
-
707
- protected boolean assignsNoNewVariables ( RootNodeWrapper rootNode ) {
708
- FrameDescriptor descriptor = rootNode . getRootNode (). getFrameDescriptor ();
709
- return frameHasOnlySelf ( descriptor ) ;
699
+ protected static boolean assignsNewUserVariables ( FrameDescriptor descriptor ) {
700
+ for ( FrameSlot slot : descriptor . getSlots ()) {
701
+ if (! BindingNodes . isHiddenVariable ( slot . getIdentifier ())) {
702
+ return true ;
703
+ }
704
+ }
705
+ return false ;
710
706
}
711
707
712
- private boolean frameHasOnlySelf ( FrameDescriptor descriptor ) {
713
- return descriptor . getSize () == 1 && SelfNode . SELF_IDENTIFIER . equals ( descriptor . getSlots (). get ( 0 ). getIdentifier ()) ;
708
+ protected int getCacheLimit ( ) {
709
+ return getContext (). getOptions (). EVAL_CACHE ;
714
710
}
715
-
716
711
}
717
712
718
713
@ CoreMethod (names = "freeze" )
0 commit comments