|
40 | 40 | */
|
41 | 41 | package com.oracle.graal.python.builtins.modules;
|
42 | 42 |
|
| 43 | +import static com.oracle.graal.python.builtins.objects.partial.PartialBuiltins.getNewPartialArgs; |
43 | 44 | import static com.oracle.graal.python.nodes.BuiltinNames.PARTIAL;
|
44 | 45 | import static com.oracle.graal.python.nodes.ErrorMessages.REDUCE_EMPTY_SEQ;
|
45 | 46 | import static com.oracle.graal.python.nodes.ErrorMessages.S_ARG_MUST_BE_CALLABLE;
|
|
53 | 54 | import com.oracle.graal.python.builtins.PythonBuiltinClassType;
|
54 | 55 | import com.oracle.graal.python.builtins.PythonBuiltins;
|
55 | 56 | import com.oracle.graal.python.builtins.objects.PNone;
|
| 57 | +import com.oracle.graal.python.builtins.objects.common.HashingStorage; |
| 58 | +import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary; |
| 59 | +import com.oracle.graal.python.builtins.objects.dict.PDict; |
56 | 60 | import com.oracle.graal.python.builtins.objects.function.PKeyword;
|
57 | 61 | import com.oracle.graal.python.builtins.objects.partial.PPartial;
|
58 | 62 | import com.oracle.graal.python.lib.PyCallableCheckNode;
|
|
72 | 76 | import com.oracle.truffle.api.dsl.NodeFactory;
|
73 | 77 | import com.oracle.truffle.api.dsl.Specialization;
|
74 | 78 | import com.oracle.truffle.api.frame.VirtualFrame;
|
| 79 | +import com.oracle.truffle.api.library.CachedLibrary; |
75 | 80 | import com.oracle.truffle.api.profiles.ConditionProfile;
|
76 | 81 |
|
77 | 82 | @CoreFunctions(defineModule = "_functools")
|
@@ -160,56 +165,87 @@ Object doConvert(Object myCmp) {
|
160 | 165 | "of the given arguments and keywords.\n")
|
161 | 166 | @GenerateNodeFactory
|
162 | 167 | public abstract static class PartialNode extends PythonBuiltinNode {
|
| 168 | + protected boolean isPartialWithoutDict(GetDictIfExistsNode getDict, Object[] args, HashingStorageLibrary lib, boolean withKwDict) { |
| 169 | + return isPartialWithoutDict(getDict, args) && withKwDict == ((PPartial) args[0]).hasKw(lib); |
| 170 | + } |
| 171 | + |
163 | 172 | protected boolean isPartialWithoutDict(GetDictIfExistsNode getDict, Object[] args) {
|
164 | 173 | return getDict.execute(args[0]) == null && args[0] instanceof PPartial;
|
165 | 174 | }
|
166 | 175 |
|
| 176 | + protected boolean withKeywords(PKeyword[] keywords) { |
| 177 | + return keywords.length > 0; |
| 178 | + } |
| 179 | + |
167 | 180 | protected boolean atLeastOneArg(Object[] args) {
|
168 | 181 | return args.length >= 1;
|
169 | 182 | }
|
170 | 183 |
|
171 |
| - @Specialization(guards = {"atLeastOneArg(args)", "isPartialWithoutDict(getDict, args)"}) |
172 |
| - Object createFromPartialWoDict(Object cls, Object[] args, PKeyword[] keywords, |
| 184 | + @Specialization(guards = {"atLeastOneArg(args)", "isPartialWithoutDict(getDict, args, lib, false)"}) |
| 185 | + Object createFromPartialWoDictWoKw(Object cls, Object[] args, PKeyword[] keywords, |
173 | 186 | @Cached GetDictIfExistsNode getDict,
|
174 | 187 | @Cached ConditionProfile hasArgsProfile,
|
175 |
| - @Cached ConditionProfile hasKeywordsProfile) { |
| 188 | + @Cached ConditionProfile hasKeywordsProfile, |
| 189 | + @CachedLibrary(limit = "1") HashingStorageLibrary lib) { |
176 | 190 | assert args[0] instanceof PPartial;
|
177 | 191 | final PPartial function = (PPartial) args[0];
|
178 |
| - final Object[] pArgs = function.getArgs(); |
179 |
| - final PKeyword[] pKeywords = function.getKw(); |
180 |
| - |
181 |
| - Object[] newArgs; |
182 |
| - if (hasArgsProfile.profile(args.length > 1)) { |
183 |
| - newArgs = new Object[pArgs.length + args.length - 1]; |
184 |
| - PythonUtils.arraycopy(pArgs, 0, newArgs, 0, pArgs.length); |
185 |
| - PythonUtils.arraycopy(args, 1, newArgs, pArgs.length, args.length - 1); |
186 |
| - } else { |
187 |
| - newArgs = pArgs; |
188 |
| - } |
| 192 | + Object[] funcArgs = getNewPartialArgs(function, args, hasArgsProfile, 1); |
189 | 193 |
|
190 |
| - PKeyword[] newKeywords; |
| 194 | + PDict funcKwDict; |
191 | 195 | if (hasKeywordsProfile.profile(keywords.length > 0)) {
|
192 |
| - newKeywords = new PKeyword[pKeywords.length + keywords.length]; |
193 |
| - PythonUtils.arraycopy(pKeywords, 0, newKeywords, 0, pKeywords.length); |
194 |
| - PythonUtils.arraycopy(keywords, 0, newKeywords, pKeywords.length, keywords.length); |
| 196 | + funcKwDict = factory().createDict(keywords); |
195 | 197 | } else {
|
196 |
| - newKeywords = pKeywords; |
| 198 | + funcKwDict = factory().createDict(); |
197 | 199 | }
|
198 | 200 |
|
199 |
| - return factory().createPartial(cls, function.getFn(), newArgs, newKeywords); |
| 201 | + return factory().createPartial(cls, function.getFn(), funcArgs, funcKwDict); |
| 202 | + } |
| 203 | + |
| 204 | + @Specialization(guards = {"atLeastOneArg(args)", "isPartialWithoutDict(getDict, args, lib, true)", "!withKeywords(keywords)"}) |
| 205 | + Object createFromPartialWoDictWKw(Object cls, Object[] args, PKeyword[] keywords, |
| 206 | + @Cached GetDictIfExistsNode getDict, |
| 207 | + @Cached ConditionProfile hasArgsProfile, |
| 208 | + @CachedLibrary(limit = "1") HashingStorageLibrary lib) { |
| 209 | + assert args[0] instanceof PPartial; |
| 210 | + final PPartial function = (PPartial) args[0]; |
| 211 | + Object[] funcArgs = getNewPartialArgs(function, args, hasArgsProfile, 1); |
| 212 | + return factory().createPartial(cls, function.getFn(), funcArgs, function.getKwCopy(factory(), lib)); |
| 213 | + } |
| 214 | + |
| 215 | + @Specialization(guards = {"atLeastOneArg(args)", "isPartialWithoutDict(getDict, args, lib, true)", "withKeywords(keywords)"}) |
| 216 | + Object createFromPartialWoDictWKwKw(VirtualFrame frame, Object cls, Object[] args, PKeyword[] keywords, |
| 217 | + @Cached GetDictIfExistsNode getDict, |
| 218 | + @Cached ConditionProfile hasArgsProfile, |
| 219 | + @Cached HashingStorage.InitNode initNode, |
| 220 | + @CachedLibrary(limit = "1") HashingStorageLibrary lib) { |
| 221 | + assert args[0] instanceof PPartial; |
| 222 | + final PPartial function = (PPartial) args[0]; |
| 223 | + Object[] funcArgs = getNewPartialArgs(function, args, hasArgsProfile, 1); |
| 224 | + |
| 225 | + HashingStorage storage = function.getKw().getDictStorage(); |
| 226 | + storage = lib.addAllToOther(initNode.execute(frame, PNone.NO_VALUE, keywords), storage); |
| 227 | + |
| 228 | + return factory().createPartial(cls, function.getFn(), funcArgs, factory().createDict(storage)); |
200 | 229 | }
|
201 | 230 |
|
202 | 231 | @Specialization(guards = {"atLeastOneArg(args)", "!isPartialWithoutDict(getDict, args)"})
|
203 | 232 | Object createGeneric(Object cls, Object[] args, PKeyword[] keywords,
|
204 | 233 | @Cached GetDictIfExistsNode getDict,
|
| 234 | + @Cached ConditionProfile hasKeywordsProfile, |
205 | 235 | @Cached PyCallableCheckNode callableCheckNode) {
|
206 | 236 | Object function = args[0];
|
207 | 237 | if (!callableCheckNode.execute(function)) {
|
208 | 238 | throw raise(PythonBuiltinClassType.TypeError, S_ARG_MUST_BE_CALLABLE, "the first");
|
209 | 239 | }
|
210 | 240 |
|
211 | 241 | final Object[] funcArgs = PythonUtils.arrayCopyOfRange(args, 1, args.length);
|
212 |
| - return factory().createPartial(cls, function, funcArgs, keywords); |
| 242 | + PDict funcKwDict; |
| 243 | + if (hasKeywordsProfile.profile(keywords.length > 0)) { |
| 244 | + funcKwDict = factory().createDict(keywords); |
| 245 | + } else { |
| 246 | + funcKwDict = factory().createDict(); |
| 247 | + } |
| 248 | + return factory().createPartial(cls, function, funcArgs, funcKwDict); |
213 | 249 | }
|
214 | 250 |
|
215 | 251 | @Specialization(guards = "!atLeastOneArg(args)")
|
|
0 commit comments