14
14
import org .truffleruby .Layouts ;
15
15
import org .truffleruby .RubyContext ;
16
16
import org .truffleruby .collections .LongHashMap ;
17
+ import org .truffleruby .extra .ffi .Pointer ;
17
18
import org .truffleruby .language .NotProvided ;
18
19
19
20
import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
22
23
23
24
public class ValueWrapperManager {
24
25
26
+ static final int UNSET_HANDLE = -1 ;
27
+
25
28
@ CompilationFinal private DynamicObject undefWrapper = null ;
26
29
@ CompilationFinal private DynamicObject trueWrapper = null ;
27
30
@ CompilationFinal private DynamicObject falseWrapper = null ;
28
31
29
32
private final LongHashMap <DynamicObject > longMap = new LongHashMap <>(128 );
30
33
private final LongHashMap <WeakReference <DynamicObject >> handleMap = new LongHashMap <>(1024 );
31
34
32
- RubyContext context ;
35
+ private final RubyContext context ;
33
36
34
37
public ValueWrapperManager (RubyContext context ) {
35
38
this .context = context ;
36
39
}
37
40
38
41
public DynamicObject undefWrapper () {
39
- return undefWrapper != null ? undefWrapper : (undefWrapper = Layouts .VALUE_WRAPPER .createValueWrapper (NotProvided .INSTANCE , ValueWrapperObjectType .UNSET_HANDLE ));
40
-
42
+ if (undefWrapper == null ) {
43
+ undefWrapper = Layouts .VALUE_WRAPPER .createValueWrapper (NotProvided .INSTANCE , UNSET_HANDLE );
44
+ }
45
+ return undefWrapper ;
41
46
}
42
47
43
48
public DynamicObject booleanWrapper (boolean value ) {
44
49
if (value ) {
45
- return trueWrapper != null ? trueWrapper : (trueWrapper = Layouts .VALUE_WRAPPER .createValueWrapper (true , ValueWrapperObjectType .UNSET_HANDLE ));
50
+ if (trueWrapper == null ) {
51
+ trueWrapper = Layouts .VALUE_WRAPPER .createValueWrapper (true , UNSET_HANDLE );
52
+ }
53
+ return trueWrapper ;
46
54
} else {
47
- return falseWrapper != null ? falseWrapper : (falseWrapper = createFalseWrapper ());
55
+ if (falseWrapper == null ) {
56
+ falseWrapper = createFalseWrapper ();
57
+ }
58
+ return falseWrapper ;
48
59
}
49
60
}
50
61
@@ -61,14 +72,14 @@ private DynamicObject createFalseWrapper() {
61
72
public synchronized DynamicObject longWrapper (long value ) {
62
73
DynamicObject wrapper = longMap .get (value );
63
74
if (wrapper == null ) {
64
- wrapper = Layouts .VALUE_WRAPPER .createValueWrapper (value , ValueWrapperObjectType .UNSET_HANDLE );
75
+ wrapper = Layouts .VALUE_WRAPPER .createValueWrapper (value , ValueWrapperManager .UNSET_HANDLE );
65
76
longMap .put (value , wrapper );
66
77
}
67
78
return wrapper ;
68
79
}
69
80
70
81
public DynamicObject doubleWrapper (double value ) {
71
- return Layouts .VALUE_WRAPPER .createValueWrapper (value , ValueWrapperObjectType .UNSET_HANDLE );
82
+ return Layouts .VALUE_WRAPPER .createValueWrapper (value , ValueWrapperManager .UNSET_HANDLE );
72
83
}
73
84
74
85
@ TruffleBoundary
@@ -94,4 +105,27 @@ public synchronized void removeFromHandleMap(long handle) {
94
105
handleMap .remove (handle );
95
106
}
96
107
108
+ @ TruffleBoundary
109
+ public synchronized long createNativeHandle (DynamicObject wrapper ) {
110
+ Pointer handlePointer = Pointer .malloc (8 );
111
+ long handleAddress = handlePointer .getAddress ();
112
+ Layouts .VALUE_WRAPPER .setHandle (wrapper , handleAddress );
113
+ addToHandleMap (handleAddress , wrapper );
114
+ addFinalizer (wrapper , handlePointer );
115
+ return handleAddress ;
116
+ }
117
+
118
+ public void addFinalizer (DynamicObject wrapper , Pointer handle ) {
119
+ context .getFinalizationService ().addFinalizer (
120
+ wrapper , null , ValueWrapperObjectType .class ,
121
+ createFinalizer (handle ), null );
122
+ }
123
+
124
+ private Runnable createFinalizer (Pointer handle ) {
125
+ return () -> {
126
+ this .removeFromHandleMap (handle .getAddress ());
127
+ handle .free ();
128
+ };
129
+
130
+ }
97
131
}
0 commit comments