55
55
import com .oracle .graal .python .builtins .objects .cext .PythonObjectNativeWrapperMRFactory .ToPyObjectNodeGen ;
56
56
import com .oracle .graal .python .builtins .objects .cext .PythonObjectNativeWrapperMRFactory .WriteNativeMemberNodeGen ;
57
57
import com .oracle .graal .python .builtins .objects .cext .UnicodeObjectNodes .UnicodeAsWideCharNode ;
58
+ import com .oracle .graal .python .builtins .objects .common .HashingStorageNodes ;
59
+ import com .oracle .graal .python .builtins .objects .common .HashingStorageNodes .GetItemNode ;
60
+ import com .oracle .graal .python .builtins .objects .common .HashingStorageNodes .SetItemNode ;
58
61
import com .oracle .graal .python .builtins .objects .dict .PDict ;
59
62
import com .oracle .graal .python .builtins .objects .memoryview .PBuffer ;
60
63
import com .oracle .graal .python .builtins .objects .object .PythonObject ;
92
95
import com .oracle .truffle .api .nodes .Node ;
93
96
import com .oracle .truffle .api .nodes .UnexpectedResultException ;
94
97
95
- @ MessageResolution (receiverType = PythonObjectNativeWrapper .class )
98
+ @ MessageResolution (receiverType = PythonNativeWrapper .class )
96
99
public class PythonObjectNativeWrapperMR {
97
100
protected static String GP_OBJECT = "gp_object" ;
98
101
99
102
@ Resolve (message = "READ" )
100
103
abstract static class ReadNode extends Node {
101
104
@ Child private ReadNativeMemberNode readNativeMemberNode ;
102
105
103
- public Object access (Object object , Object key ) {
106
+ public Object access (PythonNativeWrapper object , String key ) {
107
+ // special key for the debugger
104
108
if (key .equals (GP_OBJECT )) {
105
- return (( PythonNativeWrapper ) object ) .getDelegate ();
109
+ return object .getDelegate ();
106
110
}
107
- if (readNativeMemberNode == null ) {
108
- CompilerDirectives .transferToInterpreterAndInvalidate ();
109
- readNativeMemberNode = insert (ReadNativeMemberNode .create ());
111
+ if (NativeMemberNames .isValid (key )) {
112
+ if (readNativeMemberNode == null ) {
113
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
114
+ readNativeMemberNode = insert (ReadNativeMemberNode .create ());
115
+ }
116
+ return readNativeMemberNode .execute (object .getDelegate (), key );
110
117
}
111
- return readNativeMemberNode . execute ((( PythonNativeWrapper ) object ). getDelegate (), key );
118
+ throw UnknownIdentifierException . raise ( key . toString () );
112
119
}
113
120
}
114
121
@@ -117,10 +124,11 @@ public Object access(Object object, Object key) {
117
124
abstract static class ReadNativeMemberNode extends PBaseNode {
118
125
@ Child GetClassNode getClass = GetClassNode .create ();
119
126
@ Child private ToSulongNode toSulongNode ;
127
+ @ Child private HashingStorageNodes .GetItemNode getItemNode ;
120
128
121
129
@ CompilationFinal long wcharSize = -1 ;
122
130
123
- abstract Object execute (Object receiver , Object key );
131
+ abstract Object execute (Object receiver , String key );
124
132
125
133
@ Specialization (guards = "eq(OB_BASE, key)" )
126
134
Object doObBase (Object o , @ SuppressWarnings ("unused" ) String key ) {
@@ -132,11 +140,6 @@ Object doObBase(PString o, @SuppressWarnings("unused") String key) {
132
140
return getToSulongNode ().execute (o );
133
141
}
134
142
135
- @ Specialization (guards = "eq(_BASE, key)" )
136
- Object doObBase (String o , @ SuppressWarnings ("unused" ) String key ) {
137
- return getToSulongNode ().execute (o );
138
- }
139
-
140
143
@ Specialization (guards = "eq(OB_REFCNT, key)" )
141
144
int doObRefcnt (@ SuppressWarnings ("unused" ) Object o , @ SuppressWarnings ("unused" ) String key ) {
142
145
return 0 ;
@@ -187,7 +190,7 @@ Object doTpName(PythonClass object, @SuppressWarnings("unused") String key) {
187
190
Object doTpBase (PythonClass object , @ SuppressWarnings ("unused" ) String key ) {
188
191
PythonClass superClass = object .getSuperClass ();
189
192
if (superClass != null ) {
190
- return PythonObjectNativeWrapper . wrap (superClass );
193
+ return getToSulongNode (). execute (superClass );
191
194
}
192
195
return getToSulongNode ().execute (object );
193
196
}
@@ -275,16 +278,16 @@ Object doObItem(PSequence object, @SuppressWarnings("unused") String key) {
275
278
}
276
279
277
280
@ Specialization (guards = "eq(UNICODE_WSTR, key)" )
278
- Object doWstr (String object , @ SuppressWarnings ("unused" ) String key ,
281
+ Object doWstr (PString object , @ SuppressWarnings ("unused" ) String key ,
279
282
@ Cached ("create(0)" ) UnicodeAsWideCharNode asWideCharNode ) {
280
- return new PySequenceArrayWrapper (asWideCharNode .execute (object , sizeofWchar (), object .length ()));
283
+ return new PySequenceArrayWrapper (asWideCharNode .execute (object , sizeofWchar (), object .len ()));
281
284
}
282
285
283
286
@ Specialization (guards = "eq(UNICODE_WSTR_LENGTH, key)" )
284
- long doWstrLength (String object , @ SuppressWarnings ("unused" ) String key ,
287
+ long doWstrLength (PString object , @ SuppressWarnings ("unused" ) String key ,
285
288
@ Cached ("create(0)" ) UnicodeAsWideCharNode asWideCharNode ) {
286
289
long sizeofWchar = sizeofWchar ();
287
- PBytes result = asWideCharNode .execute (object , sizeofWchar , object .length ());
290
+ PBytes result = asWideCharNode .execute (object , sizeofWchar , object .len ());
288
291
return result .len () / sizeofWchar ;
289
292
}
290
293
@@ -306,8 +309,16 @@ Object doObSval(PBuffer object, @SuppressWarnings("unused") String key) {
306
309
}
307
310
308
311
@ Fallback
309
- Object doGeneric (@ SuppressWarnings ("unused" ) Object receiver , Object key ) {
310
- throw UnknownIdentifierException .raise (key .toString ());
312
+ Object doGeneric (Object object , String key ) {
313
+ // This is the preliminary generic case: There are native members we know that they
314
+ // exist but we do currently not represent them. So, store them into a dynamic object
315
+ // such that native code at least reads the value that was written before.
316
+ if (object instanceof PythonAbstractObject ) {
317
+ PythonObjectNativeWrapper nativeWrapper = ((PythonAbstractObject ) object ).getNativeWrapper ();
318
+ assert nativeWrapper != null ;
319
+ return getGetItemNode ().execute (nativeWrapper .getNativeMemberStore (), key );
320
+ }
321
+ throw UnknownIdentifierException .raise (key );
311
322
}
312
323
313
324
protected boolean eq (String expected , String actual ) {
@@ -318,6 +329,14 @@ public static ReadNativeMemberNode create() {
318
329
return ReadNativeMemberNodeGen .create ();
319
330
}
320
331
332
+ private HashingStorageNodes .GetItemNode getGetItemNode () {
333
+ if (getItemNode == null ) {
334
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
335
+ getItemNode = insert (GetItemNode .create ());
336
+ }
337
+ return getItemNode ;
338
+ }
339
+
321
340
private ToSulongNode getToSulongNode () {
322
341
if (toSulongNode == null ) {
323
342
CompilerDirectives .transferToInterpreterAndInvalidate ();
@@ -343,21 +362,25 @@ private long sizeofWchar() {
343
362
344
363
@ Resolve (message = "WRITE" )
345
364
abstract static class WriteNode extends Node {
346
- @ Child private WriteNativeMemberNode readNativeMemberNode ;
365
+ @ Child private WriteNativeMemberNode writeNativeMemberNode ;
347
366
348
- public Object access (Object object , Object key , Object value ) {
349
- if (readNativeMemberNode == null ) {
350
- CompilerDirectives .transferToInterpreterAndInvalidate ();
351
- readNativeMemberNode = insert (WriteNativeMemberNode .create ());
367
+ public Object access (PythonNativeWrapper object , String key , Object value ) {
368
+ if (NativeMemberNames .isValid (key )) {
369
+ if (writeNativeMemberNode == null ) {
370
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
371
+ writeNativeMemberNode = insert (WriteNativeMemberNode .create ());
372
+ }
373
+ return writeNativeMemberNode .execute (object .getDelegate (), key , value );
352
374
}
353
- return readNativeMemberNode . execute ((( PythonNativeWrapper ) object ). getDelegate (), key , value );
375
+ throw UnknownIdentifierException . raise ( key );
354
376
}
355
377
}
356
378
357
379
@ ImportStatic ({NativeMemberNames .class , PGuards .class })
358
380
abstract static class WriteNativeMemberNode extends Node {
381
+ @ Child private HashingStorageNodes .SetItemNode setItemNode ;
359
382
360
- abstract Object execute (Object receiver , Object key , Object value );
383
+ abstract Object execute (Object receiver , String key , Object value );
361
384
362
385
@ Specialization (guards = "eq(OB_TYPE, key)" )
363
386
Object doObType (PythonObject object , @ SuppressWarnings ("unused" ) String key , @ SuppressWarnings ("unused" ) PythonClass value ) {
@@ -399,15 +422,31 @@ Object doTpSubclasses(PythonClass object, @SuppressWarnings("unused") String key
399
422
}
400
423
401
424
@ Fallback
402
- Object doGeneric (Object object , Object key , @ SuppressWarnings ("unused" ) Object value ) {
403
- CompilerDirectives .transferToInterpreter ();
404
- throw new AssertionError ("Cannot modify member '" + key + "' of " + object );
425
+ Object doGeneric (Object object , String key , Object value ) {
426
+ // This is the preliminary generic case: There are native members we know that they
427
+ // exist but we do currently not represent them. So, store them into a dynamic object
428
+ // such that native code at least reads the value that was written before.
429
+ if (object instanceof PythonAbstractObject ) {
430
+ PythonObjectNativeWrapper nativeWrapper = ((PythonAbstractObject ) object ).getNativeWrapper ();
431
+ assert nativeWrapper != null ;
432
+ getSetItemNode ().execute (null , nativeWrapper .createNativeMemberStore (), key , value );
433
+ return value ;
434
+ }
435
+ throw UnknownIdentifierException .raise (key );
405
436
}
406
437
407
438
protected boolean eq (String expected , String actual ) {
408
439
return expected .equals (actual );
409
440
}
410
441
442
+ private HashingStorageNodes .SetItemNode getSetItemNode () {
443
+ if (setItemNode == null ) {
444
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
445
+ setItemNode = insert (SetItemNode .create ());
446
+ }
447
+ return setItemNode ;
448
+ }
449
+
411
450
public static WriteNativeMemberNode create () {
412
451
return WriteNativeMemberNodeGen .create ();
413
452
}
@@ -470,7 +509,7 @@ public int access(Object object, Object fieldName) {
470
509
@ Resolve (message = "HAS_KEYS" )
471
510
abstract static class HasKeysNode extends Node {
472
511
public Object access (Object obj ) {
473
- return obj instanceof PythonObjectNativeWrapper ;
512
+ return obj instanceof PythonNativeWrapper ;
474
513
}
475
514
}
476
515
@@ -479,7 +518,7 @@ abstract static class PForeignKeysNode extends Node {
479
518
@ Child Node objKeys = Message .KEYS .createNode ();
480
519
481
520
public Object access (Object object ) {
482
- if (object instanceof PythonObjectNativeWrapper ) {
521
+ if (object instanceof PythonNativeWrapper ) {
483
522
return PythonLanguage .getContext ().getEnv ().asGuestValue (new String []{GP_OBJECT });
484
523
} else {
485
524
throw UnsupportedMessageException .raise (Message .KEYS );
@@ -503,7 +542,7 @@ Object access(PythonNativeWrapper obj) {
503
542
abstract static class IsPointerNode extends Node {
504
543
@ Child private Node isPointerNode ;
505
544
506
- Object access (PythonObjectNativeWrapper obj ) {
545
+ Object access (PythonNativeWrapper obj ) {
507
546
return obj .isNative () && (!(obj .getNativePointer () instanceof TruffleObject ) || ForeignAccess .sendIsPointer (getIsPointerNode (), (TruffleObject ) obj .getNativePointer ()));
508
547
}
509
548
0 commit comments