Skip to content

Commit d6f58f0

Browse files
committed
[GR-24909] Ensure pointer identity for small int/long wrappers in compiled code.
PullRequest: graalpython/1160
2 parents e0c6510 + 23a35d9 commit d6f58f0

File tree

3 files changed

+51
-11
lines changed

3 files changed

+51
-11
lines changed

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_misc.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -194,6 +194,7 @@ def compile_module(self, name):
194194
lambda: (
195195
(True, lambda arg0, *args: arg0),
196196
(False, lambda arg0, *args: arg0),
197+
(1000, lambda arg0, *args: arg0),
197198
(10, lambda arg0, *args: arg0),
198199
(10.0, lambda arg0, *args: arg0),
199200
(float('nan'), lambda arg0, *args: arg0),
@@ -256,7 +257,7 @@ def compile_module(self, name):
256257
),
257258
code="""
258259
PyObject* wrap_PyEval_GetBuiltins() {
259-
return Py_TYPE(PyEval_GetBuiltins());
260+
return (PyObject *) Py_TYPE(PyEval_GetBuiltins());
260261
}
261262
""",
262263
resultspec="O",

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -351,11 +351,25 @@ static PrimitiveNativeWrapper doIntegerSmall(@SuppressWarnings("unused") CExtCon
351351
return PrimitiveNativeWrapper.createInt(i);
352352
}
353353

354+
/**
355+
* Generic integer conversion.<br/>
356+
* In the interpreter: we just lookup the cached primitive native wrapper and use this
357+
* instance. In compiled code, we do the same but create a fresh copy such that the compiler
358+
* always sees a fresh instance. This avoids a phi and certainly a real allocation. Note: it
359+
* is important to copy the existing cached wrapper because otherwise pointer equality is
360+
* not ensured (see also:
361+
* {@link AsPythonObjectBaseNode#mayUsePrimitive(IsPointerNode, PrimitiveNativeWrapper)}).
362+
*/
354363
@Specialization(replaces = "doIntegerSmall")
355364
static PrimitiveNativeWrapper doInteger(@SuppressWarnings("unused") CExtContext cextContext, int i,
356365
@Shared("contextRef") @CachedContext(PythonLanguage.class) ContextReference<PythonContext> contextRef) {
357-
if (CompilerDirectives.inInterpreter() && CApiGuards.isSmallInteger(i)) {
358-
return doIntegerSmall(cextContext, i, contextRef);
366+
if (CApiGuards.isSmallInteger(i)) {
367+
if (CompilerDirectives.inInterpreter()) {
368+
return doIntegerSmall(cextContext, i, contextRef);
369+
} else {
370+
// for explanation: see method doc
371+
return doIntegerSmall(cextContext, i, contextRef).copy();
372+
}
359373
}
360374
return PrimitiveNativeWrapper.createInt(i);
361375
}
@@ -373,8 +387,13 @@ static PrimitiveNativeWrapper doLongSmall(@SuppressWarnings("unused") CExtContex
373387
@Specialization(replaces = "doLongSmall")
374388
static PrimitiveNativeWrapper doLong(@SuppressWarnings("unused") CExtContext cextContext, long l,
375389
@Shared("contextRef") @CachedContext(PythonLanguage.class) ContextReference<PythonContext> contextRef) {
376-
if (CompilerDirectives.inInterpreter() && CApiGuards.isSmallLong(l)) {
377-
return doLongSmall(cextContext, l, contextRef);
390+
if (CApiGuards.isSmallLong(l)) {
391+
// for explanation of this construct: see 'ToSulongNode.doInteger'
392+
if (CompilerDirectives.inInterpreter()) {
393+
return doLongSmall(cextContext, l, contextRef);
394+
} else {
395+
return doLongSmall(cextContext, l, contextRef).copy();
396+
}
378397
}
379398
return PrimitiveNativeWrapper.createLong(l);
380399
}
@@ -602,17 +621,27 @@ static PrimitiveNativeWrapper doLongSmall(@SuppressWarnings("unused") CExtContex
602621
@Specialization(replaces = "doIntegerSmall")
603622
static PrimitiveNativeWrapper doInteger(CExtContext cextContext, int i,
604623
@Shared("contextRef") @CachedContext(PythonLanguage.class) ContextReference<PythonContext> contextRef) {
605-
if (CompilerDirectives.inInterpreter() && CApiGuards.isSmallInteger(i)) {
606-
return doIntegerSmall(cextContext, i, contextRef);
624+
if (CApiGuards.isSmallInteger(i)) {
625+
// for explanation of this construct: see 'ToSulongNode.doInteger'
626+
if (CompilerDirectives.inInterpreter()) {
627+
return doIntegerSmall(cextContext, i, contextRef);
628+
} else {
629+
return doIntegerSmall(cextContext, i, contextRef).copy();
630+
}
607631
}
608632
return PrimitiveNativeWrapper.createInt(i);
609633
}
610634

611635
@Specialization(replaces = "doLongSmall")
612636
static PrimitiveNativeWrapper doLong(CExtContext cextContext, long l,
613637
@Shared("contextRef") @CachedContext(PythonLanguage.class) ContextReference<PythonContext> contextRef) {
614-
if (CompilerDirectives.inInterpreter() && CApiGuards.isSmallLong(l)) {
615-
return doLongSmall(cextContext, l, contextRef);
638+
if (CApiGuards.isSmallLong(l)) {
639+
// for explanation of this construct: see 'ToSulongNode.doInteger'
640+
if (CompilerDirectives.inInterpreter()) {
641+
return doLongSmall(cextContext, l, contextRef);
642+
} else {
643+
return doLongSmall(cextContext, l, contextRef).copy();
644+
}
616645
}
617646
return PrimitiveNativeWrapper.createLong(l);
618647
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/DynamicObjectNativeWrapper.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1475,6 +1475,12 @@ private PrimitiveNativeWrapper(double dvalue) {
14751475
this.dvalue = dvalue;
14761476
}
14771477

1478+
private PrimitiveNativeWrapper(byte state, long value, double dvalue) {
1479+
this.state = state;
1480+
this.value = value;
1481+
this.dvalue = dvalue;
1482+
}
1483+
14781484
public byte getState() {
14791485
return state;
14801486
}
@@ -1554,7 +1560,11 @@ public boolean equals(Object obj) {
15541560

15551561
@Override
15561562
public int hashCode() {
1557-
return (int) (value ^ Double.doubleToRawLongBits(dvalue) ^ state);
1563+
return (Long.hashCode(value) ^ Long.hashCode(Double.doubleToRawLongBits(dvalue)) ^ state);
1564+
}
1565+
1566+
PrimitiveNativeWrapper copy() {
1567+
return new PrimitiveNativeWrapper(state, value, dvalue);
15581568
}
15591569

15601570
@Override

0 commit comments

Comments
 (0)