|
24 | 24 | import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; |
25 | 25 | import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; |
26 | 26 |
|
27 | | -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; |
| 27 | +import com.oracle.truffle.api.CompilerDirectives; |
28 | 28 | import com.oracle.truffle.api.dsl.Cached; |
29 | 29 | import com.oracle.truffle.api.dsl.Specialization; |
30 | 30 | import com.oracle.truffle.api.profiles.BranchProfile; |
31 | 31 | import com.oracle.truffle.r.nodes.attributes.RemoveFixedAttributeNode; |
32 | 32 | import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetClassAttributeNode; |
33 | 33 | import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; |
| 34 | +import com.oracle.truffle.r.nodes.builtin.base.UnClassNodeGen.RemoveClassAttrNodeGen; |
34 | 35 | import com.oracle.truffle.r.runtime.builtins.RBuiltin; |
35 | 36 | import com.oracle.truffle.r.runtime.data.RAttributable; |
36 | 37 | import com.oracle.truffle.r.runtime.data.RNull; |
37 | 38 | import com.oracle.truffle.r.runtime.data.RShareable; |
38 | | -import com.oracle.truffle.r.runtime.data.RVector; |
39 | 39 | import com.oracle.truffle.r.runtime.data.model.RAbstractVector; |
| 40 | +import com.oracle.truffle.r.runtime.data.nodes.VectorReuse; |
| 41 | +import com.oracle.truffle.r.runtime.nodes.RBaseNode; |
40 | 42 |
|
41 | 43 | @RBuiltin(name = "unclass", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) |
42 | 44 | public abstract class UnClass extends RBuiltinNode.Arg1 { |
43 | | - private final BranchProfile objectProfile = BranchProfile.create(); |
44 | | - private final BranchProfile shareableProfile = BranchProfile.create(); |
45 | | - |
46 | 45 | static { |
47 | 46 | Casts casts = new Casts(UnClass.class); |
48 | 47 | casts.arg("x").mustNotBeMissing().asAttributable(true, true, true); |
49 | 48 | } |
50 | 49 |
|
| 50 | + @Child private RemoveClassAttrNode removeClassAttrNode; |
| 51 | + |
51 | 52 | @Specialization |
52 | 53 | protected RNull unClass(RNull rnull) { |
53 | 54 | return rnull; |
54 | 55 | } |
55 | 56 |
|
56 | | - @TruffleBoundary |
57 | | - private static Object unClassVector(RAbstractVector arg) { |
58 | | - RVector<?> resultVector = arg.materialize(); |
59 | | - if (!resultVector.isTemporary()) { |
60 | | - resultVector = resultVector.copy(); |
61 | | - resultVector.incRefCount(); |
62 | | - } |
63 | | - return RVector.setVectorClassAttr(resultVector, null); |
64 | | - } |
65 | | - |
66 | | - // TODO: this specialization could go away if connections were simple vectors (we wouldn't need |
67 | | - // special method for setting class attributes then) |
68 | 57 | @Specialization |
69 | | - protected Object unClass(RAbstractVector arg, |
| 58 | + protected Object unClass(RAttributable arg, |
70 | 59 | @Cached("create()") GetClassAttributeNode getClassNode) { |
71 | 60 | if (getClassNode.isObject(arg)) { |
72 | | - objectProfile.enter(); |
73 | | - return unClassVector(arg); |
| 61 | + if (removeClassAttrNode == null) { |
| 62 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
| 63 | + removeClassAttrNode = insert(RemoveClassAttrNodeGen.create()); |
| 64 | + } |
| 65 | + return removeClassAttrNode.execute(arg); |
74 | 66 | } |
75 | 67 | return arg; |
76 | 68 | } |
77 | 69 |
|
78 | | - @Specialization(guards = "notAbstractVector(arg)") |
79 | | - protected Object unClass(RAttributable arg, |
80 | | - @Cached("createClass()") RemoveFixedAttributeNode removeClassNode, |
81 | | - @Cached("create()") GetClassAttributeNode getClassNode) { |
82 | | - if (getClassNode.getClassAttr(arg) != null) { |
83 | | - objectProfile.enter(); |
84 | | - if (arg instanceof RShareable) { |
| 70 | + protected abstract static class RemoveClassAttrNode extends RBaseNode { |
| 71 | + public abstract Object execute(RAttributable attributable); |
| 72 | + |
| 73 | + @Specialization(guards = "reuse.supports(x)") |
| 74 | + protected Object doVector(RAbstractVector x, |
| 75 | + @Cached("createClass()") RemoveFixedAttributeNode removeClassNode, |
| 76 | + @Cached("createTemporary(x)") VectorReuse reuse) { |
| 77 | + RAbstractVector result = reuse.getMaterializedResult(x); |
| 78 | + removeClassNode.execute(result); |
| 79 | + return result; |
| 80 | + } |
| 81 | + |
| 82 | + @Specialization(replaces = "doVector") |
| 83 | + protected Object doVectorGeneric(RAbstractVector x, |
| 84 | + @Cached("createClass()") RemoveFixedAttributeNode removeClassNode, |
| 85 | + @Cached("createTemporaryGeneric()") VectorReuse reuse) { |
| 86 | + return doVector(x, removeClassNode, reuse); |
| 87 | + } |
| 88 | + |
| 89 | + @Specialization(guards = "notAbstractVector(x)") |
| 90 | + protected Object unClass(RAttributable x, |
| 91 | + @Cached BranchProfile shareableProfile, |
| 92 | + @Cached("createClass()") RemoveFixedAttributeNode removeClassNode) { |
| 93 | + RAttributable result = x; |
| 94 | + if (x instanceof RShareable) { |
85 | 95 | shareableProfile.enter(); |
86 | | - RShareable shareable = (RShareable) arg; |
| 96 | + RShareable shareable = (RShareable) x; |
87 | 97 | if (!shareable.isTemporary()) { |
88 | | - shareable = shareable.copy(); |
89 | | - shareable.incRefCount(); |
| 98 | + result = (RAttributable) shareable.copy(); |
90 | 99 | } |
91 | 100 | } |
92 | | - removeClassNode.execute(arg); |
| 101 | + removeClassNode.execute(result); |
| 102 | + return result; |
93 | 103 | } |
94 | | - return arg; |
95 | | - } |
96 | 104 |
|
97 | | - protected boolean notAbstractVector(Object arg) { |
98 | | - return !(arg instanceof RAbstractVector); |
| 105 | + protected static boolean notAbstractVector(Object arg) { |
| 106 | + return !(arg instanceof RAbstractVector); |
| 107 | + } |
99 | 108 | } |
100 | 109 | } |
0 commit comments