14
14
import java .util .List ;
15
15
import java .util .Set ;
16
16
17
+ import com .oracle .truffle .api .CompilerDirectives ;
17
18
import com .oracle .truffle .api .dsl .GenerateNodeFactory ;
18
19
import com .oracle .truffle .api .dsl .GenerateUncached ;
19
20
import com .oracle .truffle .api .frame .FrameInstance .FrameAccess ;
21
+ import com .oracle .truffle .api .frame .FrameSlotKind ;
20
22
import com .oracle .truffle .api .profiles .ConditionProfile ;
21
23
import org .truffleruby .Layouts ;
22
24
import org .truffleruby .RubyContext ;
35
37
import org .truffleruby .core .string .RubyString ;
36
38
import org .truffleruby .core .string .StringNodes .MakeStringNode ;
37
39
import org .truffleruby .language .CallStackManager ;
38
- import org .truffleruby .language .Nil ;
39
40
import org .truffleruby .language .RubyBaseNode ;
40
41
import org .truffleruby .language .RubyBaseNodeWithExecute ;
41
42
import org .truffleruby .language .RubyNode ;
47
48
import org .truffleruby .language .locals .FindDeclarationVariableNodes ;
48
49
import org .truffleruby .language .locals .FindDeclarationVariableNodes .FindAndReadDeclarationVariableNode ;
49
50
import org .truffleruby .language .locals .FindDeclarationVariableNodes .FrameSlotAndDepth ;
51
+ import org .truffleruby .language .locals .FrameDescriptorNamesIterator ;
50
52
import org .truffleruby .language .locals .WriteFrameSlotNode ;
51
53
import org .truffleruby .language .locals .WriteFrameSlotNodeGen ;
52
54
60
62
import com .oracle .truffle .api .dsl .Specialization ;
61
63
import com .oracle .truffle .api .frame .Frame ;
62
64
import com .oracle .truffle .api .frame .FrameDescriptor ;
63
- import com .oracle .truffle .api .frame .FrameSlot ;
64
65
import com .oracle .truffle .api .frame .MaterializedFrame ;
65
66
import com .oracle .truffle .api .frame .VirtualFrame ;
66
67
import com .oracle .truffle .api .source .SourceSection ;
68
+ import org .truffleruby .parser .ParentFrameDescriptor ;
69
+ import org .truffleruby .parser .TranslatorEnvironment ;
67
70
68
71
@ CoreModule (value = "Binding" , isClass = true )
69
72
public abstract class BindingNodes {
@@ -83,25 +86,34 @@ public static RubyBinding createBinding(RubyContext context, RubyLanguage langua
83
86
}
84
87
85
88
@ TruffleBoundary
86
- public static FrameDescriptor newFrameDescriptor () {
87
- return new FrameDescriptor (Nil .INSTANCE );
89
+ public static FrameDescriptor newFrameDescriptor (RubyBinding binding ) {
90
+ FrameDescriptor parentDescriptor = binding .getFrame ().getFrameDescriptor ();
91
+ var ref = new ParentFrameDescriptor (parentDescriptor );
92
+ return TranslatorEnvironment .newFrameDescriptorBuilder (ref , false ).build ();
88
93
}
89
94
95
+ static final int NEW_VAR_INDEX = 1 ;
96
+
90
97
@ TruffleBoundary
91
- public static FrameDescriptor newFrameDescriptor (String name ) {
92
- final FrameDescriptor frameDescriptor = new FrameDescriptor (Nil .INSTANCE );
98
+ public static FrameDescriptor newFrameDescriptor (FrameDescriptor parentDescriptor , String name ) {
93
99
assert name != null && !name .isEmpty ();
94
- frameDescriptor .addFrameSlot (name );
95
- return frameDescriptor ;
100
+
101
+ var ref = new ParentFrameDescriptor (parentDescriptor );
102
+ var builder = TranslatorEnvironment .newFrameDescriptorBuilder (ref , false );
103
+ int index = builder .addSlot (FrameSlotKind .Illegal , name , null );
104
+ if (index != NEW_VAR_INDEX ) {
105
+ throw CompilerDirectives .shouldNotReachHere ("new binding variable not at index 1" );
106
+ }
107
+ return builder .build ();
96
108
}
97
109
98
110
public static FrameDescriptor getFrameDescriptor (RubyBinding binding ) {
99
111
return binding .getFrame ().getFrameDescriptor ();
100
112
}
101
113
102
114
public static MaterializedFrame newFrame (RubyBinding binding , FrameDescriptor frameDescriptor ) {
103
- final MaterializedFrame frame = binding .getFrame ();
104
- final MaterializedFrame newFrame = newFrame (frame , frameDescriptor );
115
+ final MaterializedFrame parentFrame = binding .getFrame ();
116
+ final MaterializedFrame newFrame = newFrame (parentFrame , frameDescriptor );
105
117
binding .setFrame (newFrame );
106
118
return newFrame ;
107
119
}
@@ -121,20 +133,17 @@ public static MaterializedFrame newFrame(MaterializedFrame parent, FrameDescript
121
133
}
122
134
123
135
public static void insertAncestorFrame (RubyBinding binding , MaterializedFrame ancestorFrame ) {
124
- MaterializedFrame frame = binding .getFrame ();
125
- while (RubyArguments .getDeclarationFrame (frame ) != null ) {
126
- frame = RubyArguments .getDeclarationFrame (frame );
127
- }
136
+ MaterializedFrame frame = FindDeclarationVariableNodes .getOuterDeclarationFrame (binding .getFrame ());
128
137
RubyArguments .setDeclarationFrame (frame , ancestorFrame );
129
138
130
139
// We need to invalidate caches depending on the top frame, so create a new empty frame
131
- newFrame (binding , newFrameDescriptor ());
140
+ newFrame (binding , newFrameDescriptor (binding ));
132
141
}
133
142
134
143
@ TruffleBoundary
135
144
public static boolean assignsNewUserVariables (FrameDescriptor descriptor ) {
136
- for (FrameSlot slot : descriptor . getSlots ( )) {
137
- if (!BindingNodes .isHiddenVariable (slot . getIdentifier () )) {
145
+ for (Object identifier : FrameDescriptorNamesIterator . iterate ( descriptor )) {
146
+ if (!BindingNodes .isHiddenVariable (identifier )) {
138
147
return true ;
139
148
}
140
149
}
@@ -151,8 +160,9 @@ public static boolean isHiddenVariable(Object name) {
151
160
152
161
private static boolean isHiddenVariable (String name ) {
153
162
assert !name .isEmpty ();
154
- return name .charAt (0 ) == '$' || // Frame-local global variable
155
- name .charAt (0 ) == Layouts .TEMP_PREFIX_CHAR ;
163
+ final char first = name .charAt (0 );
164
+ return first == '$' || // Frame-local global variable
165
+ first == Layouts .TEMP_PREFIX_CHAR ;
156
166
}
157
167
158
168
@ CoreMethod (names = { "dup" , "clone" })
@@ -324,13 +334,12 @@ protected RubyBaseNodeWithExecute coerceToString(RubyBaseNodeWithExecute name) {
324
334
"!isHiddenVariable(cachedName)" ,
325
335
"getFrameDescriptor(binding) == cachedFrameDescriptor" ,
326
336
"cachedFrameSlot != null" },
327
- assumptions = "cachedFrameDescriptor.getVersion()" ,
328
337
limit = "getCacheLimit()" )
329
338
protected Object localVariableSetCached (RubyBinding binding , String name , Object value ,
330
339
@ Cached ("name" ) String cachedName ,
331
340
@ Cached ("getFrameDescriptor(binding)" ) FrameDescriptor cachedFrameDescriptor ,
332
341
@ Cached ("findFrameSlotOrNull(name, binding.getFrame())" ) FrameSlotAndDepth cachedFrameSlot ,
333
- @ Cached ("createWriteNode(cachedFrameSlot)" ) WriteFrameSlotNode writeLocalVariableNode ) {
342
+ @ Cached ("createWriteNode(cachedFrameSlot.slot )" ) WriteFrameSlotNode writeLocalVariableNode ) {
334
343
final MaterializedFrame frame = RubyArguments
335
344
.getDeclarationFrame (binding .getFrame (), cachedFrameSlot .depth );
336
345
writeLocalVariableNode .executeWrite (frame , value );
@@ -343,15 +352,13 @@ protected Object localVariableSetCached(RubyBinding binding, String name, Object
343
352
"!isHiddenVariable(cachedName)" ,
344
353
"getFrameDescriptor(binding) == cachedFrameDescriptor" ,
345
354
"cachedFrameSlot == null" },
346
- assumptions = "cachedFrameDescriptor.getVersion()" ,
347
355
limit = "getCacheLimit()" )
348
356
protected Object localVariableSetNewCached (RubyBinding binding , String name , Object value ,
349
357
@ Cached ("name" ) String cachedName ,
350
358
@ Cached ("getFrameDescriptor(binding)" ) FrameDescriptor cachedFrameDescriptor ,
351
359
@ Cached ("findFrameSlotOrNull(name, binding.getFrame())" ) FrameSlotAndDepth cachedFrameSlot ,
352
- @ Cached ("newFrameDescriptor(name)" ) FrameDescriptor newDescriptor ,
353
- @ Cached ("findFrameSlot(name, newDescriptor)" ) FrameSlotAndDepth newFrameSlot ,
354
- @ Cached ("createWriteNode(newFrameSlot)" ) WriteFrameSlotNode writeLocalVariableNode ) {
360
+ @ Cached ("newFrameDescriptor(cachedFrameDescriptor, name)" ) FrameDescriptor newDescriptor ,
361
+ @ Cached ("createWriteNode(NEW_VAR_INDEX)" ) WriteFrameSlotNode writeLocalVariableNode ) {
355
362
final MaterializedFrame frame = newFrame (binding , newDescriptor );
356
363
writeLocalVariableNode .executeWrite (frame , value );
357
364
return value ;
@@ -364,13 +371,15 @@ protected Object localVariableSetNewCached(RubyBinding binding, String name, Obj
364
371
protected Object localVariableSetUncached (RubyBinding binding , String name , Object value ) {
365
372
MaterializedFrame frame = binding .getFrame ();
366
373
final FrameSlotAndDepth frameSlot = FindDeclarationVariableNodes .findFrameSlotOrNull (name , frame );
367
- final FrameSlot slot ;
374
+ final int slot ;
368
375
if (frameSlot != null ) {
369
376
frame = RubyArguments .getDeclarationFrame (frame , frameSlot .depth );
370
377
slot = frameSlot .slot ;
371
378
} else {
372
- frame = newFrame (binding , newFrameDescriptor (name ));
373
- slot = frame .getFrameDescriptor ().findFrameSlot (name );
379
+ var newDescriptor = newFrameDescriptor (getFrameDescriptor (binding ), name );
380
+ frame = newFrame (binding , newDescriptor );
381
+ assert newDescriptor .getSlotName (NEW_VAR_INDEX ) == name ;
382
+ slot = NEW_VAR_INDEX ;
374
383
}
375
384
frame .setObject (slot , value );
376
385
return value ;
@@ -384,8 +393,8 @@ protected Object localVariableSetLastLine(RubyBinding binding, String name, Obje
384
393
coreExceptions ().nameError ("Bad local variable name" , binding , name , this ));
385
394
}
386
395
387
- protected WriteFrameSlotNode createWriteNode (FrameSlotAndDepth frameSlot ) {
388
- return WriteFrameSlotNodeGen .create (frameSlot . slot );
396
+ protected WriteFrameSlotNode createWriteNode (int frameSlot ) {
397
+ return WriteFrameSlotNodeGen .create (frameSlot );
389
398
}
390
399
391
400
protected int getCacheLimit () {
@@ -397,10 +406,7 @@ protected int getCacheLimit() {
397
406
@ ImportStatic (BindingNodes .class )
398
407
public abstract static class LocalVariablesNode extends PrimitiveArrayArgumentsNode {
399
408
400
- @ Specialization (
401
- guards = "getFrameDescriptor(binding) == cachedFrameDescriptor" ,
402
- assumptions = "cachedFrameDescriptor.getVersion()" ,
403
- limit = "getCacheLimit()" )
409
+ @ Specialization (guards = "getFrameDescriptor(binding) == cachedFrameDescriptor" , limit = "getCacheLimit()" )
404
410
protected RubyArray localVariablesCached (RubyBinding binding ,
405
411
@ Cached ("getFrameDescriptor(binding)" ) FrameDescriptor cachedFrameDescriptor ,
406
412
@ Cached ("listLocalVariablesAsSymbols(getContext(), binding.getFrame())" ) RubyArray names ) {
@@ -423,9 +429,9 @@ public RubyArray listLocalVariablesAsSymbols(RubyContext context, MaterializedFr
423
429
}
424
430
425
431
private void addNamesFromFrame (Frame frame , Set <Object > names ) {
426
- for (FrameSlot slot : frame .getFrameDescriptor (). getSlots ( )) {
427
- if (!isHiddenVariable (slot . getIdentifier () )) {
428
- names .add (getSymbol ((String ) slot . getIdentifier () ));
432
+ for (Object identifier : FrameDescriptorNamesIterator . iterate ( frame .getFrameDescriptor ())) {
433
+ if (!isHiddenVariable (identifier )) {
434
+ names .add (getSymbol ((String ) identifier ));
429
435
}
430
436
}
431
437
}
@@ -436,9 +442,9 @@ public static List<String> listLocalVariablesWithDuplicates(MaterializedFrame fr
436
442
Frame currentFrame = frame ;
437
443
while (currentFrame != null ) {
438
444
final FrameDescriptor frameDescriptor = currentFrame .getFrameDescriptor ();
439
- for (FrameSlot slot : frameDescriptor . getSlots ( )) {
440
- if (!isHiddenVariable (slot . getIdentifier () )) {
441
- members .add (slot . getIdentifier (). toString () );
445
+ for (Object identifier : FrameDescriptorNamesIterator . iterate ( frameDescriptor )) {
446
+ if (!isHiddenVariable (identifier )) {
447
+ members .add (( String ) identifier );
442
448
}
443
449
}
444
450
if (receiverName != null ) {
@@ -524,7 +530,8 @@ protected RubyBinding binding(VirtualFrame frame) {
524
530
// Use the current frame to initialize the arguments, etc, correctly
525
531
final RubyBinding binding = BindingNodes
526
532
.createBinding (getContext (), getLanguage (), frame .materialize (), getEncapsulatingSourceSection ());
527
- final MaterializedFrame newFrame = newFrame (binding , newFrameDescriptor ());
533
+
534
+ final MaterializedFrame newFrame = newFrame (binding , getLanguage ().emptyDeclarationDescriptor );
528
535
RubyArguments .setDeclarationFrame (newFrame , null ); // detach from the current frame
529
536
return binding ;
530
537
}
0 commit comments