|
33 | 33 | import com.oracle.truffle.api.CompilerDirectives; |
34 | 34 | import com.oracle.truffle.api.dsl.Cached; |
35 | 35 | import com.oracle.truffle.api.dsl.Specialization; |
| 36 | +import com.oracle.truffle.api.library.CachedLibrary; |
36 | 37 | import com.oracle.truffle.api.nodes.ExplodeLoop; |
37 | 38 | import com.oracle.truffle.api.profiles.BranchProfile; |
38 | 39 | import com.oracle.truffle.api.profiles.ConditionProfile; |
39 | 40 | import com.oracle.truffle.api.profiles.ValueProfile; |
40 | 41 | import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; |
| 42 | +import com.oracle.truffle.r.nodes.builtin.base.QuantifierNodeGen.ProcessArgumentNodeGen; |
| 43 | +import com.oracle.truffle.r.runtime.data.VectorDataLibrary; |
| 44 | +import com.oracle.truffle.r.runtime.data.VectorDataLibrary.SeqIterator; |
| 45 | +import com.oracle.truffle.r.runtime.nodes.RBaseNode; |
41 | 46 | import com.oracle.truffle.r.runtime.nodes.unary.CastNode; |
42 | 47 | import com.oracle.truffle.r.runtime.DSLConfig; |
43 | 48 | import com.oracle.truffle.r.runtime.RError; |
|
48 | 53 | import com.oracle.truffle.r.runtime.data.RNull; |
49 | 54 | import com.oracle.truffle.r.runtime.data.RLogicalVector; |
50 | 55 | import com.oracle.truffle.r.runtime.data.model.RAbstractVector; |
51 | | -import com.oracle.truffle.r.runtime.ops.na.NACheck; |
52 | 56 |
|
53 | 57 | public abstract class Quantifier extends RBuiltinNode.Arg2 { |
54 | 58 | protected static final int MAX_CACHED_LENGTH = 10; |
55 | 59 |
|
56 | | - private final NACheck naCheck = NACheck.create(); |
57 | | - private final BranchProfile trueBranch = BranchProfile.create(); |
58 | | - private final BranchProfile falseBranch = BranchProfile.create(); |
59 | | - |
60 | 60 | @Children private final CastNode[] argCastNodes = new CastNode[Math.max(1, DSLConfig.getCacheSize(MAX_CACHED_LENGTH))]; |
| 61 | + @Children private final ProcessArgumentNode[] processArgumentNodes = new ProcessArgumentNode[Math.max(1, DSLConfig.getCacheSize(MAX_CACHED_LENGTH))]; |
| 62 | + private final BranchProfile nullBranch = BranchProfile.create(); |
61 | 63 |
|
62 | 64 | private static final class ProfileCastNode extends CastNode { |
63 | 65 |
|
@@ -141,37 +143,61 @@ protected byte op(RArgsValuesAndNames args, boolean naRm, |
141 | 143 | } |
142 | 144 |
|
143 | 145 | private byte processArgument(Object argValue, int index, boolean naRm) { |
144 | | - byte result = RRuntime.asLogical(emptyVectorResult()); |
145 | 146 | if (argValue != RNull.instance) { |
146 | 147 | if (argCastNodes[index] == null) { |
147 | 148 | CompilerDirectives.transferToInterpreterAndInvalidate(); |
148 | 149 | createArgCast(index); |
149 | 150 | } |
150 | 151 | Object castValue = argCastNodes[index].doCast(argValue); |
151 | | - if (castValue instanceof RLogicalVector) { |
152 | | - RLogicalVector vector = (RLogicalVector) castValue; |
153 | | - naCheck.enable(vector); |
154 | | - for (int i = 0; i < vector.getLength(); i++) { |
155 | | - byte b = vector.getDataAt(i); |
156 | | - if (!naRm && naCheck.check(b)) { |
157 | | - result = RRuntime.LOGICAL_NA; |
158 | | - } else if (b == RRuntime.asLogical(!emptyVectorResult())) { |
159 | | - trueBranch.enter(); |
160 | | - return RRuntime.asLogical(!emptyVectorResult()); |
161 | | - } |
162 | | - } |
163 | | - } else { |
164 | | - byte b = (byte) castValue; |
165 | | - naCheck.enable(true); |
166 | | - if (!naRm && naCheck.check(b)) { |
| 152 | + if (processArgumentNodes[index] == null) { |
| 153 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
| 154 | + processArgumentNodes[index] = insert(ProcessArgumentNodeGen.create(this)); |
| 155 | + } |
| 156 | + return processArgumentNodes[index].execute(castValue, naRm); |
| 157 | + } |
| 158 | + nullBranch.enter(); |
| 159 | + return RRuntime.asLogical(emptyVectorResult()); |
| 160 | + } |
| 161 | + |
| 162 | + abstract static class ProcessArgumentNode extends RBaseNode { |
| 163 | + private final Quantifier parent; |
| 164 | + |
| 165 | + protected ProcessArgumentNode(Quantifier parent) { |
| 166 | + this.parent = parent; |
| 167 | + } |
| 168 | + |
| 169 | + public abstract byte execute(Object vector, boolean naRm); |
| 170 | + |
| 171 | + @Specialization(limit = "getTypedVectorDataLibraryCacheSize()") |
| 172 | + byte doVector(RLogicalVector vector, boolean naRm, |
| 173 | + @CachedLibrary("vector.getData()") VectorDataLibrary argDataLib) { |
| 174 | + Object data = vector.getData(); |
| 175 | + SeqIterator it = argDataLib.iterator(data); |
| 176 | + byte result = RRuntime.asLogical(parent.emptyVectorResult()); |
| 177 | + while (argDataLib.next(data, it)) { |
| 178 | + byte b = argDataLib.getNextLogical(data, it); |
| 179 | + if (!naRm && argDataLib.getNACheck(data).check(b)) { |
167 | 180 | result = RRuntime.LOGICAL_NA; |
168 | | - } else if (b == RRuntime.asLogical(!emptyVectorResult())) { |
169 | | - trueBranch.enter(); |
170 | | - return RRuntime.asLogical(!emptyVectorResult()); |
| 181 | + } else if (b == RRuntime.asLogical(!parent.emptyVectorResult())) { |
| 182 | + return RRuntime.asLogical(!parent.emptyVectorResult()); |
171 | 183 | } |
172 | 184 | } |
| 185 | + return result; |
| 186 | + } |
| 187 | + |
| 188 | + @Specialization |
| 189 | + byte doSingleByte(byte value, boolean naRm, |
| 190 | + @Cached BranchProfile isNAProfile, |
| 191 | + @Cached BranchProfile trueBranchProfile) { |
| 192 | + if (!naRm && RRuntime.isNA(value)) { |
| 193 | + isNAProfile.enter(); |
| 194 | + return RRuntime.LOGICAL_NA; |
| 195 | + } else if (value == RRuntime.asLogical(!parent.emptyVectorResult())) { |
| 196 | + return RRuntime.asLogical(!parent.emptyVectorResult()); |
| 197 | + } else { |
| 198 | + trueBranchProfile.enter(); |
| 199 | + return RRuntime.asLogical(parent.emptyVectorResult()); |
| 200 | + } |
173 | 201 | } |
174 | | - falseBranch.enter(); |
175 | | - return result; |
176 | 202 | } |
177 | 203 | } |
0 commit comments