14
14
import org .truffleruby .language .RubyBaseNode ;
15
15
import org .truffleruby .language .dispatch .DispatchNode ;
16
16
17
+ import java .util .ArrayList ;
18
+
17
19
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
20
+ import com .oracle .truffle .api .dsl .Bind ;
18
21
import com .oracle .truffle .api .dsl .Cached ;
19
22
import com .oracle .truffle .api .dsl .GenerateUncached ;
20
23
import com .oracle .truffle .api .dsl .Specialization ;
24
+ import com .oracle .truffle .api .profiles .ConditionProfile ;
21
25
22
26
public class MarkingServiceNodes {
23
27
@@ -26,13 +30,38 @@ public abstract static class KeepAliveNode extends RubyBaseNode {
26
30
27
31
public abstract void execute (ValueWrapper object );
28
32
29
- @ Specialization
30
- protected void executeAddToList (ValueWrapper object ) {
31
- addToList (getLanguage ().getCurrentThread ().getCurrentFiber ().extensionCallStack , object );
33
+ @ Specialization (guards = "!stack.hasKeptObjects()" )
34
+ protected void keepFirstObject (ValueWrapper object ,
35
+ @ Bind ("getStack(object)" ) ExtensionCallStack stack ) {
36
+ stack .current .preservedObject = object ;
32
37
}
33
38
34
- protected void addToList (ExtensionCallStack stack , ValueWrapper object ) {
35
- stack .keepObject (object );
39
+ @ Specialization (guards = "stack.hasSingleKeptObject()" )
40
+ protected void keepCreatingList (ValueWrapper object ,
41
+ @ Bind ("getStack(object)" ) ExtensionCallStack stack ,
42
+ @ Cached ConditionProfile sameObjectProfile ) {
43
+ if (sameObjectProfile .profile (object != stack .current .preservedObject )) {
44
+ createKeptList (object , stack );
45
+ }
46
+ }
47
+
48
+ @ Specialization (guards = { "stack.hasKeptObjects()" , "!stack.hasSingleKeptObject()" })
49
+ @ TruffleBoundary
50
+ protected void keepAddingToList (ValueWrapper object ,
51
+ @ Bind ("getStack(object)" ) ExtensionCallStack stack ) {
52
+ stack .current .preservedObjects .add (object );
53
+ }
54
+
55
+ @ TruffleBoundary
56
+ private void createKeptList (ValueWrapper object , ExtensionCallStack stack ) {
57
+ stack .current .preservedObjects = new ArrayList <>();
58
+ stack .current .preservedObjects .add (stack .current .preservedObject );
59
+ stack .current .preservedObjects .add (object );
60
+ }
61
+
62
+ // We take a parameter so that the bind isn't considered cacheable.
63
+ protected ExtensionCallStack getStack (ValueWrapper object ) {
64
+ return getLanguage ().getCurrentThread ().getCurrentFiber ().extensionCallStack ;
36
65
}
37
66
}
38
67
0 commit comments