13
13
import java .util .List ;
14
14
import java .util .Objects ;
15
15
16
+ import com .oracle .truffle .api .CompilerAsserts ;
17
+ import com .oracle .truffle .api .dsl .GenerateInline ;
18
+ import com .oracle .truffle .api .nodes .Node ;
16
19
import com .oracle .truffle .api .object .PropertyGetter ;
17
20
import org .truffleruby .core .kernel .KernelNodes ;
18
21
import org .truffleruby .language .RubyBaseNode ;
32
35
33
36
/** Share the object and all that is reachable from it (see {@link ObjectGraph#getAdjacentObjects}) */
34
37
@ ImportStatic (ShapeCachingGuards .class )
38
+ @ GenerateInline (inlineByDefault = true )
35
39
public abstract class ShareObjectNode extends RubyBaseNode {
36
40
37
41
protected static final int CACHE_LIMIT = 8 ;
38
42
39
- protected final int depth ;
43
+ public final void execute (Node node , RubyDynamicObject object , int depth ) {
44
+ CompilerAsserts .partialEvaluationConstant (depth );
45
+ executeInternal (node , object , depth );
46
+ }
40
47
41
- public ShareObjectNode ( int depth ) {
42
- this . depth = depth ;
48
+ public final void executeCached ( RubyDynamicObject object , int depth ) {
49
+ execute ( this , object , depth ) ;
43
50
}
44
51
45
- public abstract void executeShare ( RubyDynamicObject object );
52
+ protected abstract void executeInternal ( Node node , RubyDynamicObject object , int depth );
46
53
47
54
@ ExplodeLoop
48
55
@ Specialization (
49
56
guards = { "object.getShape() == cachedShape" , "propertyGetters.length <= MAX_EXPLODE_SIZE" },
50
57
assumptions = { "cachedShape.getValidAssumption()" , "sharedShape.getValidAssumption()" },
51
58
limit = "CACHE_LIMIT" )
52
- protected void shareCached (RubyDynamicObject object ,
59
+ protected static void shareCached (Node node , RubyDynamicObject object , int depth ,
53
60
@ Cached ("object.getShape()" ) Shape cachedShape ,
54
61
@ Cached ("createSharedShape(cachedShape)" ) Shape sharedShape ,
55
62
@ CachedLibrary (limit = "1" ) DynamicObjectLibrary objectLibrary ,
@@ -66,12 +73,12 @@ protected void shareCached(RubyDynamicObject object,
66
73
// Note that the metaclass might refer to `object` via `attached`, so it is important to share the object first.
67
74
if (!object .getMetaClass ().getShape ().isShared ()) {
68
75
shareMetaClassProfile .enter ();
69
- SharedObjects .writeBarrier (getLanguage (), object .getMetaClass ());
76
+ SharedObjects .writeBarrier (getLanguage (node ), object .getMetaClass ());
70
77
}
71
78
assert SharedObjects
72
79
.isShared (object .getLogicalClass ()) : "the logical class should have been shared by the metaclass" ;
73
80
74
- shareInternalFieldsNode .execute (this , object , depth );
81
+ shareInternalFieldsNode .execute (node , object , depth );
75
82
76
83
for (int i = 0 ; i < propertyGetters .length ; i ++) {
77
84
final PropertyGetter propertyGetter = propertyGetters [i ];
@@ -82,7 +89,7 @@ protected void shareCached(RubyDynamicObject object,
82
89
assert allFieldsAreShared (object );
83
90
}
84
91
85
- private boolean allFieldsAreShared (RubyDynamicObject object ) {
92
+ private static boolean allFieldsAreShared (RubyDynamicObject object ) {
86
93
for (Object value : ObjectGraph .getAdjacentObjects (object )) {
87
94
assert SharedObjects .isShared (value ) : "unshared field in shared object: " + value ;
88
95
}
@@ -91,13 +98,14 @@ private boolean allFieldsAreShared(RubyDynamicObject object) {
91
98
}
92
99
93
100
@ Specialization (guards = "updateShape(object)" )
94
- protected void updateShapeAndShare (RubyDynamicObject object ) {
95
- executeShare (object );
101
+ protected static void updateShapeAndShare (RubyDynamicObject object , int depth ,
102
+ @ Cached (inline = false ) ShareObjectNode shareObjectNode ) {
103
+ shareObjectNode .executeCached (object , depth );
96
104
}
97
105
98
106
@ Specialization (replaces = { "shareCached" , "updateShapeAndShare" })
99
- protected void shareUncached (RubyDynamicObject object ) {
100
- SharedObjects .writeBarrier (getLanguage (), object );
107
+ protected static void shareUncached (Node node , RubyDynamicObject object , int depth ) {
108
+ SharedObjects .writeBarrier (getLanguage (node ), object );
101
109
}
102
110
103
111
protected static PropertyGetter [] getObjectProperties (Shape shape ) {
@@ -110,7 +118,7 @@ protected static PropertyGetter[] getObjectProperties(Shape shape) {
110
118
return objectProperties .toArray (KernelNodes .CopyInstanceVariablesNode .EMPTY_PROPERTY_GETTER_ARRAY );
111
119
}
112
120
113
- protected WriteBarrierNode [] createWriteBarrierNodes (PropertyGetter [] propertyGetters ) {
121
+ protected static WriteBarrierNode [] createWriteBarrierNodes (PropertyGetter [] propertyGetters ) {
114
122
WriteBarrierNode [] nodes = propertyGetters .length == 0
115
123
? WriteBarrierNode .EMPTY_ARRAY
116
124
: new WriteBarrierNode [propertyGetters .length ];
@@ -120,7 +128,7 @@ protected WriteBarrierNode[] createWriteBarrierNodes(PropertyGetter[] propertyGe
120
128
return nodes ;
121
129
}
122
130
123
- protected Shape createSharedShape (Shape cachedShape ) {
131
+ protected static Shape createSharedShape (Shape cachedShape ) {
124
132
if (cachedShape .isShared ()) {
125
133
throw new UnsupportedOperationException (
126
134
"Thread-safety bug: the object is already shared. This means another thread marked the object as shared concurrently." );
0 commit comments