|
1 | 1 | /*
|
2 |
| - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
4 | 4 | *
|
5 | 5 | * The Universal Permissive License (UPL), Version 1.0
|
|
58 | 58 | import com.oracle.graal.python.nodes.PNodeWithContext;
|
59 | 59 | import com.oracle.graal.python.nodes.PRaiseNode;
|
60 | 60 | import com.oracle.graal.python.nodes.SpecialMethodNames;
|
61 |
| -import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode; |
| 61 | +import com.oracle.graal.python.nodes.control.GetIteratorExpressionNode.GetIteratorNode; |
| 62 | +import com.oracle.graal.python.nodes.control.GetNextNode; |
62 | 63 | import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
|
63 | 64 | import com.oracle.graal.python.nodes.interop.PTypeToForeignNode;
|
64 | 65 | import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
|
65 | 66 | import com.oracle.graal.python.runtime.PythonOptions;
|
66 | 67 | import com.oracle.graal.python.runtime.exception.PException;
|
67 | 68 | import com.oracle.graal.python.runtime.object.PythonObjectFactory;
|
68 |
| -import com.oracle.graal.python.runtime.sequence.PSequence; |
69 | 69 | import com.oracle.truffle.api.CompilerDirectives;
|
70 | 70 | import com.oracle.truffle.api.dsl.Cached;
|
71 | 71 | import com.oracle.truffle.api.dsl.ImportStatic;
|
|
78 | 78 | import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
79 | 79 | import com.oracle.truffle.api.interop.UnsupportedTypeException;
|
80 | 80 | import com.oracle.truffle.api.library.CachedLibrary;
|
| 81 | +import com.oracle.truffle.api.profiles.BranchProfile; |
81 | 82 |
|
82 | 83 | abstract class AccessForeignItemNodes {
|
83 | 84 |
|
@@ -214,26 +215,34 @@ protected abstract static class SetForeignItemNode extends AccessForeignItemBase
|
214 | 215 |
|
215 | 216 | public abstract Object execute(VirtualFrame frame, Object object, Object idx, Object value);
|
216 | 217 |
|
217 |
| - @Specialization |
218 |
| - public Object doForeignObjectSlice(VirtualFrame frame, Object object, PSlice idxSlice, PSequence pvalues, |
219 |
| - @CachedLibrary(limit = "3") InteropLibrary lib, |
220 |
| - @Cached("create(__GETITEM__)") LookupAndCallBinaryNode getItemNode, |
221 |
| - @Cached("create()") PTypeToForeignNode valueToForeignNode) { |
| 218 | + @Specialization(limit = "getCallSiteInlineCacheMaxDepth()") |
| 219 | + public Object doForeignObjectSlice(VirtualFrame frame, Object object, PSlice idxSlice, Object pvalues, |
| 220 | + @CachedLibrary("object") InteropLibrary lib, |
| 221 | + @Cached GetIteratorNode getIterator, |
| 222 | + @Cached GetNextNode getNext, |
| 223 | + @Cached PTypeToForeignNode valueToForeignNode, |
| 224 | + @Cached BranchProfile unsupportedMessage, |
| 225 | + @Cached BranchProfile unsupportedType, |
| 226 | + @Cached BranchProfile wrongIndex) { |
| 227 | + Object value; |
| 228 | + SliceInfo mslice; |
222 | 229 | try {
|
223 |
| - SliceInfo mslice = materializeSlice(idxSlice, object, lib); |
224 |
| - for (int i = mslice.start, j = 0; i < mslice.stop; i += mslice.step, j++) { |
225 |
| - Object convertedValue = valueToForeignNode.executeConvert(getItemNode.executeObject(frame, pvalues, j)); |
226 |
| - writeForeignValue(object, i, convertedValue, lib); |
227 |
| - } |
228 |
| - return PNone.NONE; |
229 |
| - } catch (UnsupportedTypeException | UnsupportedMessageException e) { |
230 |
| - throw raise(AttributeError, "%s instance has no attribute '__setitem__'", object); |
| 230 | + mslice = materializeSlice(idxSlice, object, lib); |
| 231 | + } catch (UnsupportedMessageException e) { |
| 232 | + throw raiseNoSetItem(object); |
231 | 233 | }
|
| 234 | + Object iter = getIterator.executeWith(frame, pvalues); |
| 235 | + for (int i = mslice.start; i < mslice.stop; i += mslice.step) { |
| 236 | + value = getNext.execute(frame, iter); |
| 237 | + Object convertedValue = valueToForeignNode.executeConvert(value); |
| 238 | + writeForeignValue(object, i, convertedValue, lib, unsupportedMessage, unsupportedType, wrongIndex); |
| 239 | + } |
| 240 | + return PNone.NONE; |
232 | 241 | }
|
233 | 242 |
|
234 |
| - @Specialization |
| 243 | + @Specialization(limit = "getCallSiteInlineCacheMaxDepth()") |
235 | 244 | public Object doForeignKey(Object object, String key, Object value,
|
236 |
| - @CachedLibrary(limit = "3") InteropLibrary lib) { |
| 245 | + @CachedLibrary("object") InteropLibrary lib) { |
237 | 246 | if (lib.hasMembers(object)) {
|
238 | 247 | if (lib.isMemberWritable(object, key)) {
|
239 | 248 | try {
|
@@ -272,33 +281,42 @@ private PException raiseAttributeError(String key) {
|
272 | 281 | public Object doForeignObject(VirtualFrame frame, Object object, Object idx, Object value,
|
273 | 282 | @CachedLibrary("object") InteropLibrary lib,
|
274 | 283 | @CachedLibrary("idx") PythonObjectLibrary pythonLib,
|
275 |
| - @Cached("create()") PTypeToForeignNode valueToForeignNode) { |
276 |
| - try { |
277 |
| - int convertedIdx = pythonLib.asSizeWithState(idx, PArguments.getThreadState(frame)); |
278 |
| - Object convertedValue = valueToForeignNode.executeConvert(value); |
279 |
| - writeForeignValue(object, convertedIdx, convertedValue, lib); |
280 |
| - return PNone.NONE; |
281 |
| - } catch (UnsupportedTypeException e) { |
282 |
| - throw raise(AttributeError, "%s instance has no attribute '__setitem__'", object); |
283 |
| - } |
| 284 | + @Cached PTypeToForeignNode valueToForeignNode, |
| 285 | + @Cached BranchProfile unsupportedMessage, |
| 286 | + @Cached BranchProfile unsupportedType, |
| 287 | + @Cached BranchProfile wrongIndex) { |
| 288 | + int convertedIdx = pythonLib.asSizeWithState(idx, PArguments.getThreadState(frame)); |
| 289 | + Object convertedValue = valueToForeignNode.executeConvert(value); |
| 290 | + writeForeignValue(object, convertedIdx, convertedValue, lib, unsupportedMessage, unsupportedType, wrongIndex); |
| 291 | + return PNone.NONE; |
284 | 292 | }
|
285 | 293 |
|
286 |
| - private void writeForeignValue(Object object, int idx, Object value, InteropLibrary libForObject) throws UnsupportedTypeException { |
| 294 | + private void writeForeignValue(Object object, int idx, Object value, InteropLibrary libForObject, BranchProfile unsupportedMessage, BranchProfile unsupportedType, BranchProfile wrongIndex) { |
287 | 295 | if (libForObject.hasArrayElements(object)) {
|
288 | 296 | if (libForObject.isArrayElementWritable(object, idx)) {
|
289 | 297 | try {
|
290 | 298 | libForObject.writeArrayElement(object, idx, value);
|
291 | 299 | return;
|
292 | 300 | } catch (InvalidArrayIndexException ex) {
|
293 |
| - // fall through |
| 301 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
| 302 | + throw new IllegalStateException("Array element should be writable, as per test"); |
294 | 303 | } catch (UnsupportedMessageException e) {
|
295 |
| - CompilerDirectives.transferToInterpreter(); |
| 304 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
296 | 305 | throw new IllegalStateException("Array element should be writable, as per test");
|
| 306 | + } catch (UnsupportedTypeException e) { |
| 307 | + unsupportedType.enter(); |
| 308 | + throw raise(TypeError, "type '%p' is not supported by the foreign object", value); |
297 | 309 | }
|
298 | 310 | }
|
| 311 | + wrongIndex.enter(); |
299 | 312 | throw raise(IndexError, "invalid index %s", idx);
|
300 | 313 | }
|
301 |
| - throw raise(AttributeError, "%s instance has no attribute '__setitem__'", object); |
| 314 | + unsupportedMessage.enter(); |
| 315 | + throw raiseNoSetItem(object); |
| 316 | + } |
| 317 | + |
| 318 | + private PException raiseNoSetItem(Object object) { |
| 319 | + return raise(AttributeError, "%s instance has no attribute '__setitem__'", object); |
302 | 320 | }
|
303 | 321 |
|
304 | 322 | public static SetForeignItemNode create() {
|
|
0 commit comments